Changeset 13779 in vbox for trunk/src/VBox/Main/ConsoleImpl.cpp
- Timestamp:
- Nov 4, 2008 9:46:13 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/ConsoleImpl.cpp
r13762 r13779 96 96 #include <algorithm> 97 97 #include <memory> // for auto_ptr 98 #include <vector> 98 99 99 100 … … 1062 1063 rc = VERR_UNRESOLVED_ERROR; /** @todo translate error code */ 1063 1064 return rc; 1065 } 1066 1067 HRESULT Console::doEnumerateGuestProperties (INPTR BSTR aPatterns, 1068 ComSafeArrayOut(BSTR, aNames), 1069 ComSafeArrayOut(BSTR, aValues), 1070 ComSafeArrayOut(ULONG64, aTimestamps), 1071 ComSafeArrayOut(BSTR, aFlags)) 1072 { 1073 using namespace guestProp; 1074 1075 VBOXHGCMSVCPARM parm[3]; 1076 1077 Utf8Str utf8Patterns(aPatterns); 1078 parm[0].type = VBOX_HGCM_SVC_PARM_PTR; 1079 parm[0].u.pointer.addr = utf8Patterns.mutableRaw(); 1080 parm[0].u.pointer.size = utf8Patterns.length() + 1; 1081 1082 /* 1083 * Now things get slightly complicated. Due to a race with the guest adding 1084 * properties, there is no good way to know how much large a buffer to provide 1085 * the service to enumerate into. We choose a decent starting size and loop a 1086 * few times, each time retrying with the size suggested by the service plus 1087 * one Kb. 1088 */ 1089 size_t cchBuf = 4096; 1090 Utf8Str Utf8Buf; 1091 int vrc = VERR_BUFFER_OVERFLOW; 1092 for (unsigned i = 0; i < 10 && (VERR_BUFFER_OVERFLOW == vrc); ++i) 1093 { 1094 Utf8Buf.alloc(cchBuf + 1024); 1095 if (Utf8Buf.isNull()) 1096 return E_OUTOFMEMORY; 1097 parm[1].type = VBOX_HGCM_SVC_PARM_PTR; 1098 parm[1].u.pointer.addr = Utf8Buf.mutableRaw(); 1099 parm[1].u.pointer.size = cchBuf + 1024; 1100 vrc = mVMMDev->hgcmHostCall ("VBoxGuestPropSvc", ENUM_PROPS_HOST, 3, 1101 &parm[0]); 1102 if (parm[2].type != VBOX_HGCM_SVC_PARM_32BIT) 1103 return setError (E_FAIL, tr ("Internal application error")); 1104 cchBuf = parm[2].u.uint32; 1105 } 1106 if (VERR_BUFFER_OVERFLOW == vrc) 1107 return setError (E_UNEXPECTED, tr ("Temporary failure due to guest activity, please retry")); 1108 1109 /* 1110 * Finally we have to unpack the data returned by the service into the safe 1111 * arrays supplied by the caller. We start by counting the number of entries. 1112 */ 1113 const char *pszBuf 1114 = reinterpret_cast<const char *>(parm[1].u.pointer.addr); 1115 unsigned cEntries = 0; 1116 /* The list is terminated by a zero-length string at the end of a set 1117 * of four strings. */ 1118 for (size_t i = 0; strlen(pszBuf + i) != 0; ) 1119 { 1120 /* We are counting sets of four strings. */ 1121 for (unsigned j = 0; j < 4; ++j) 1122 i += strlen(pszBuf + i) + 1; 1123 ++cEntries; 1124 } 1125 1126 /* 1127 * And now we create the COM safe arrays and fill them in. 1128 */ 1129 com::SafeArray <BSTR> names(cEntries); 1130 com::SafeArray <BSTR> values(cEntries); 1131 com::SafeArray <ULONG64> timestamps(cEntries); 1132 com::SafeArray <BSTR> flags(cEntries); 1133 size_t iBuf = 0; 1134 /* Rely on the service to have formated the data correctly. */ 1135 for (unsigned i = 0; i < cEntries; ++i) 1136 { 1137 size_t cchName = strlen(pszBuf + iBuf); 1138 Bstr(pszBuf + iBuf).detachTo(&names[i]); 1139 iBuf += cchName + 1; 1140 size_t cchValue = strlen(pszBuf + iBuf); 1141 Bstr(pszBuf + iBuf).detachTo(&values[i]); 1142 iBuf += cchValue + 1; 1143 size_t cchTimestamp = strlen(pszBuf + iBuf); 1144 timestamps[i] = RTStrToUInt64(pszBuf + iBuf); 1145 iBuf += cchTimestamp + 1; 1146 size_t cchFlags = strlen(pszBuf + iBuf); 1147 Bstr(pszBuf + iBuf).detachTo(&flags[i]); 1148 iBuf += cchFlags + 1; 1149 } 1150 names.detachTo(ComSafeArrayOutArg (aNames)); 1151 values.detachTo(ComSafeArrayOutArg (aValues)); 1152 timestamps.detachTo(ComSafeArrayOutArg (aTimestamps)); 1153 flags.detachTo(ComSafeArrayOutArg (aFlags)); 1154 return S_OK; 1064 1155 } 1065 1156 #endif … … 3687 3778 * autoVMCaller, so there is no need to hold a lock of this */ 3688 3779 3689 using namespace guestProp; 3690 3691 VBOXHGCMSVCPARM parm[3]; 3692 3693 Utf8Str utf8Patterns(aPatterns); 3694 parm[0].type = VBOX_HGCM_SVC_PARM_PTR; 3695 parm[0].u.pointer.addr = utf8Patterns.mutableRaw(); 3696 parm[0].u.pointer.size = utf8Patterns.length() + 1; 3697 3698 /* 3699 * Now things get slightly complicated. Due to a race with the guest adding 3700 * properties, there is no good way to know how much large a buffer to provide 3701 * the service to enumerate into. We choose a decent starting size and loop a 3702 * few times, each time retrying with the size suggested by the service plus 3703 * one Kb. 3704 */ 3705 size_t cchBuf = 4096; 3706 Utf8Str Utf8Buf; 3707 int vrc = VERR_BUFFER_OVERFLOW; 3708 for (unsigned i = 0; i < 10 && (VERR_BUFFER_OVERFLOW == vrc); ++i) 3709 { 3710 Utf8Buf.alloc(cchBuf + 1024); 3711 if (Utf8Buf.isNull()) 3712 return E_OUTOFMEMORY; 3713 parm[1].type = VBOX_HGCM_SVC_PARM_PTR; 3714 parm[1].u.pointer.addr = Utf8Buf.mutableRaw(); 3715 parm[1].u.pointer.size = cchBuf + 1024; 3716 vrc = mVMMDev->hgcmHostCall ("VBoxGuestPropSvc", ENUM_PROPS_HOST, 3, 3717 &parm[0]); 3718 if (parm[2].type != VBOX_HGCM_SVC_PARM_32BIT) 3719 return setError (E_FAIL, tr ("Internal application error")); 3720 cchBuf = parm[2].u.uint32; 3721 } 3722 if (VERR_BUFFER_OVERFLOW == vrc) 3723 return setError (E_UNEXPECTED, tr ("Temporary failure due to guest activity, please retry")); 3724 3725 /* 3726 * Finally we have to unpack the data returned by the service into the safe 3727 * arrays supplied by the caller. We start by counting the number of entries. 3728 */ 3729 const char *pszBuf 3730 = reinterpret_cast<const char *>(parm[1].u.pointer.addr); 3731 unsigned cEntries = 0; 3732 /* The list is terminated by a zero-length string at the end of a set 3733 * of four strings. */ 3734 for (size_t i = 0; strlen(pszBuf + i) != 0; ) 3735 { 3736 /* We are counting sets of four strings. */ 3737 for (unsigned j = 0; j < 4; ++j) 3738 i += strlen(pszBuf + i) + 1; 3739 ++cEntries; 3740 } 3741 3742 /* 3743 * And now we create the COM safe arrays and fill them in. 3744 */ 3745 com::SafeArray <BSTR> names(cEntries); 3746 com::SafeArray <BSTR> values(cEntries); 3747 com::SafeArray <ULONG64> timestamps(cEntries); 3748 com::SafeArray <BSTR> flags(cEntries); 3749 size_t iBuf = 0; 3750 /* Rely on the service to have formated the data correctly. */ 3751 for (unsigned i = 0; i < cEntries; ++i) 3752 { 3753 size_t cchName = strlen(pszBuf + iBuf); 3754 Bstr(pszBuf + iBuf).detachTo(&names[i]); 3755 iBuf += cchName + 1; 3756 size_t cchValue = strlen(pszBuf + iBuf); 3757 Bstr(pszBuf + iBuf).detachTo(&values[i]); 3758 iBuf += cchValue + 1; 3759 size_t cchTimestamp = strlen(pszBuf + iBuf); 3760 timestamps[i] = RTStrToUInt64(pszBuf + iBuf); 3761 iBuf += cchTimestamp + 1; 3762 size_t cchFlags = strlen(pszBuf + iBuf); 3763 Bstr(pszBuf + iBuf).detachTo(&flags[i]); 3764 iBuf += cchFlags + 1; 3765 } 3766 names.detachTo(ComSafeArrayOutArg (aNames)); 3767 values.detachTo(ComSafeArrayOutArg (aValues)); 3768 timestamps.detachTo(ComSafeArrayOutArg (aTimestamps)); 3769 flags.detachTo(ComSafeArrayOutArg (aFlags)); 3770 return S_OK; 3780 return doEnumerateGuestProperties (aPatterns, ComSafeArrayOutArg(aNames), 3781 ComSafeArrayOutArg(aValues), 3782 ComSafeArrayOutArg(aTimestamps), 3783 ComSafeArrayOutArg(aFlags)); 3771 3784 #endif /* else !defined (VBOX_WITH_GUEST_PROPS) */ 3772 3785 } … … 4633 4646 #ifdef VBOX_WITH_HGCM 4634 4647 4648 # ifdef VBOX_WITH_GUEST_PROPS 4649 4650 /* Save all guest property store entries to the machine XML file */ 4651 com::SafeArray <BSTR> namesOut; 4652 com::SafeArray <BSTR> valuesOut; 4653 com::SafeArray <ULONG64> timestampsOut; 4654 com::SafeArray <BSTR> flagsOut; 4655 Bstr pattern(""); 4656 if (pattern.isNull()) 4657 rc = E_OUTOFMEMORY; 4658 else 4659 rc = doEnumerateGuestProperties (Bstr (""), ComSafeArrayAsOutParam (namesOut), 4660 ComSafeArrayAsOutParam (valuesOut), 4661 ComSafeArrayAsOutParam (timestampsOut), 4662 ComSafeArrayAsOutParam (flagsOut)); 4663 if (SUCCEEDED(rc)) 4664 { 4665 try 4666 { 4667 std::vector <BSTR> names; 4668 std::vector <BSTR> values; 4669 std::vector <ULONG64> timestamps; 4670 std::vector <BSTR> flags; 4671 for (unsigned i = 0; i < namesOut.size(); ++i) 4672 { 4673 uint32_t fFlags; 4674 guestProp::validateFlags (Utf8Str(flagsOut[i]).raw(), &fFlags); 4675 if ( !( fFlags & guestProp::TRANSIENT) 4676 || (mMachineState == MachineState_Saving) 4677 ) 4678 { 4679 names.push_back(namesOut[i]); 4680 values.push_back(valuesOut[i]); 4681 timestamps.push_back(timestampsOut[i]); 4682 flags.push_back(flagsOut[i]); 4683 } 4684 } 4685 com::SafeArray <BSTR> namesIn (names); 4686 com::SafeArray <BSTR> valuesIn (values); 4687 com::SafeArray <ULONG64> timestampsIn (timestamps); 4688 com::SafeArray <BSTR> flagsIn (flags); 4689 if ( namesIn.isNull() 4690 || valuesIn.isNull() 4691 || timestampsIn.isNull() 4692 || flagsIn.isNull() 4693 ) 4694 throw std::bad_alloc(); 4695 /* PushGuestProperties() calls DiscardSettings(), which calls us back */ 4696 alock.leave(); 4697 mControl->PushGuestProperties (ComSafeArrayAsInParam (namesIn), 4698 ComSafeArrayAsInParam (valuesIn), 4699 ComSafeArrayAsInParam (timestampsIn), 4700 ComSafeArrayAsInParam (flagsIn)); 4701 alock.enter(); 4702 } 4703 catch (std::bad_alloc) 4704 { 4705 rc = E_OUTOFMEMORY; 4706 } 4707 } 4708 4709 /* advance percent count */ 4710 if (aProgress) 4711 aProgress->notifyProgress (99 * (++ step) / StepCount ); 4712 4713 # endif /* VBOX_WITH_GUEST_PROPS defined */ 4714 4635 4715 /* Shutdown HGCM services before stopping the guest, because they might 4636 4716 * need a cleanup. */ … … 4650 4730 if (aProgress) 4651 4731 aProgress->notifyProgress (99 * (++ step) / StepCount ); 4652 4653 # ifdef VBOX_WITH_GUEST_PROPS4654 4655 /* Save all guest property store entries to the machine XML file */4656 PCFGMNODE pValues = CFGMR3GetChild (CFGMR3GetRoot (mpVM), "GuestProps/Values/");4657 PCFGMNODE pTimestamps = CFGMR3GetChild (CFGMR3GetRoot (mpVM), "GuestProps/Timestamps/");4658 PCFGMNODE pFlags = CFGMR3GetChild (CFGMR3GetRoot (mpVM), "GuestProps/Flags/");4659 4660 /* Count the number of entries we have */4661 unsigned cValues = 0;4662 PCFGMLEAF pValue;4663 for (pValue = CFGMR3GetFirstValue (pValues); pValue != NULL;4664 pValue = CFGMR3GetNextValue (pValue))4665 {4666 char szPropName[guestProp::MAX_NAME_LEN];4667 vrc = CFGMR3GetValueName (pValue, szPropName, sizeof(szPropName));4668 if (RT_SUCCESS(vrc))4669 {4670 /* Do not send transient properties unless we are saving state */4671 uint32_t fFlags = guestProp::NILFLAG;4672 CFGMR3QueryU32 (pFlags, szPropName, &fFlags);4673 if (!(fFlags & guestProp::TRANSIENT) ||4674 (mMachineState == MachineState_Saving))4675 ++cValues;4676 }4677 }4678 4679 /* And pack them into safe arrays */4680 com::SafeArray <BSTR> names(cValues);4681 com::SafeArray <BSTR> values(cValues);4682 com::SafeArray <ULONG64> timestamps(cValues);4683 com::SafeArray <BSTR> flags(cValues);4684 pValue = CFGMR3GetFirstValue (pValues);4685 4686 vrc = VINF_SUCCESS;4687 unsigned iProp = 0;4688 while (pValue != NULL && RT_SUCCESS (vrc))4689 {4690 using namespace guestProp;4691 4692 char szPropName [MAX_NAME_LEN];4693 char szPropValue [MAX_VALUE_LEN];4694 char szPropFlags [MAX_FLAGS_LEN];4695 ULONG64 u64Timestamp = 0; /* default */4696 vrc = CFGMR3GetValueName (pValue, szPropName, sizeof (szPropName));4697 if (RT_SUCCESS(vrc))4698 vrc = CFGMR3QueryString (pValues, szPropName, szPropValue,4699 sizeof (szPropValue));4700 if (RT_SUCCESS(vrc))4701 {4702 uint32_t fFlags = NILFLAG;4703 CFGMR3QueryU32 (pFlags, szPropName, &fFlags);4704 /* Skip transient properties unless we are saving state */4705 if (!(fFlags & TRANSIENT) ||4706 (mMachineState == MachineState_Saving))4707 {4708 writeFlags(fFlags, szPropFlags);4709 CFGMR3QueryU64 (pTimestamps, szPropName, &u64Timestamp);4710 Bstr(szPropName).cloneTo(&names[iProp]);4711 Bstr(szPropValue).cloneTo(&values[iProp]);4712 timestamps[iProp] = u64Timestamp;4713 Bstr(szPropFlags).cloneTo(&flags[iProp]);4714 ++iProp;4715 if (iProp >= cValues)4716 vrc = VERR_TOO_MUCH_DATA;4717 }4718 pValue = CFGMR3GetNextValue (pValue);4719 }4720 }4721 4722 if (RT_SUCCESS(vrc) || (VERR_TOO_MUCH_DATA == vrc))4723 {4724 /* PushGuestProperties() calls DiscardSettings(), which calls us back */4725 alock.leave();4726 mControl->PushGuestProperties (ComSafeArrayAsInParam (names),4727 ComSafeArrayAsInParam (values),4728 ComSafeArrayAsInParam (timestamps),4729 ComSafeArrayAsInParam (flags));4730 alock.enter();4731 }4732 4733 /* advance percent count */4734 if (aProgress)4735 aProgress->notifyProgress (99 * (++ step) / StepCount );4736 4737 # endif /* VBOX_WITH_GUEST_PROPS defined */4738 4732 4739 4733 #endif /* VBOX_WITH_HGCM */
Note:
See TracChangeset
for help on using the changeset viewer.