- Timestamp:
- Aug 1, 2011 5:22:10 PM (13 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h
r38235 r38269 47 47 typedef std::map< Utf8Str, VBOXGUESTCTRL_STREAM_PAIR >::const_iterator GuestCtrlStreamPairsIterConst; 48 48 49 /** 50 * Class representing a block of stream pairs (key=value). Each block in a raw guest 51 * output stream is separated by "\0\0", each pair is separated by "\0". The overall 52 * end of a guest stream is marked by "\0\0\0\0". 53 */ 54 class GuestProcessStreamBlock 55 { 56 public: 57 58 GuestProcessStreamBlock(); 59 60 virtual ~GuestProcessStreamBlock(); 61 62 public: 63 64 int AddKey(const char *pszKey); 65 66 void Clear(); 67 68 int GetInt64Ex(const char *pszKey, int64_t *piVal); 69 70 int64_t GetInt64(const char *pszKey); 71 72 size_t GetCount(); 73 74 const char* GetString(const char *pszKey); 75 76 int GetUInt32Ex(const char *pszKey, uint32_t *puVal); 77 78 uint32_t GetUInt32(const char *pszKey); 79 80 int SetValue(const char *pszKey, const char *pszValue); 81 82 protected: 83 84 GuestCtrlStreamPairs m_mapPairs; 85 }; 86 87 /** Vector containing multiple stream pair objects. */ 88 typedef std::vector< GuestProcessStreamBlock > GuestCtrlStreamObjects; 89 90 /** 91 * Class for parsing machine-readable guest process output by VBoxService' 92 * toolbox commands ("vbox_ls", "vbox_stat" etc). 93 */ 49 94 class GuestProcessStream 50 95 { … … 60 105 int AddData(const BYTE *pbData, size_t cbData); 61 106 62 void ClearPairs();63 64 107 void Destroy(); 65 66 int GetInt64Ex(const char *pszKey, int64_t *piVal);67 68 int64_t GetInt64(const char *pszKey);69 70 size_t GetNumPairs();71 108 72 109 uint32_t GetOffset(); 73 110 74 const char* GetString(const char *pszKey); 75 76 int GetUInt32Ex(const char *pszKey, uint32_t *puVal); 77 78 uint32_t GetUInt32(const char *pszKey); 79 80 int ParseBlock(); 111 int ParseBlock(GuestProcessStreamBlock &streamBlock); 81 112 82 113 protected: 83 114 84 /** The map containing one more more stream pairs. */85 GuestCtrlStreamPairs m_mapPairs;86 115 /** Currently allocated size of internal stream buffer. */ 87 116 uint32_t m_cbAllocated; -
trunk/src/VBox/Main/include/GuestImpl.h
r38235 r38269 87 87 STDMETHOD(GetFacilityStatus)(AdditionsFacilityType_T aType, LONG64 *aTimestamp, AdditionsFacilityStatus_T *aStatus); 88 88 STDMETHOD(GetAdditionsStatus)(AdditionsRunLevelType_T aLevel, BOOL *aActive); 89 STDMETHOD(SetCredentials)(IN_BSTR aUser Name, IN_BSTR aPassword,89 STDMETHOD(SetCredentials)(IN_BSTR aUsername, IN_BSTR aPassword, 90 90 IN_BSTR aDomain, BOOL aAllowInteractiveLogon); 91 91 // Process execution 92 92 STDMETHOD(ExecuteProcess)(IN_BSTR aCommand, ULONG aFlags, 93 93 ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment), 94 IN_BSTR aUser Name, IN_BSTR aPassword,94 IN_BSTR aUsername, IN_BSTR aPassword, 95 95 ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress); 96 96 STDMETHOD(GetProcessOutput)(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS, LONG64 aSize, ComSafeArrayOut(BYTE, aData)); … … 98 98 STDMETHOD(GetProcessStatus)(ULONG aPID, ULONG *aExitCode, ULONG *aFlags, ExecuteProcessStatus_T *aStatus); 99 99 // File copying 100 STDMETHOD(CopyFromGuest)(IN_BSTR aSource, IN_BSTR aDest, IN_BSTR aUser Name, IN_BSTR aPassword, ULONG aFlags, IProgress **aProgress);101 STDMETHOD(CopyToGuest)(IN_BSTR aSource, IN_BSTR aDest, IN_BSTR aUser Name, IN_BSTR aPassword, ULONG aFlags, IProgress **aProgress);100 STDMETHOD(CopyFromGuest)(IN_BSTR aSource, IN_BSTR aDest, IN_BSTR aUsername, IN_BSTR aPassword, ULONG aFlags, IProgress **aProgress); 101 STDMETHOD(CopyToGuest)(IN_BSTR aSource, IN_BSTR aDest, IN_BSTR aUsername, IN_BSTR aPassword, ULONG aFlags, IProgress **aProgress); 102 102 // Directory handling 103 103 STDMETHOD(DirectoryClose)(ULONG aHandle); 104 STDMETHOD(DirectoryCreate)(IN_BSTR aDirectory, IN_BSTR aUser Name, IN_BSTR aPassword, ULONG aMode, ULONG aFlags);104 STDMETHOD(DirectoryCreate)(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, ULONG aMode, ULONG aFlags); 105 105 STDMETHOD(DirectoryOpen)(IN_BSTR aDirectory, IN_BSTR aFilter, 106 ULONG aFlags, IN_BSTR aUser Name, IN_BSTR aPassword, ULONG *aHandle);106 ULONG aFlags, IN_BSTR aUsername, IN_BSTR aPassword, ULONG *aHandle); 107 107 STDMETHOD(DirectoryRead)(ULONG aHandle, IGuestDirEntry **aDirEntry); 108 108 // File handling 109 STDMETHOD(FileExists)(IN_BSTR aFile, IN_BSTR aUser Name, IN_BSTR aPassword, BOOL *aExists);110 STDMETHOD(FileQuerySize)(IN_BSTR aFile, IN_BSTR aUser Name, IN_BSTR aPassword, LONG64 *aSize);109 STDMETHOD(FileExists)(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists); 110 STDMETHOD(FileQuerySize)(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, LONG64 *aSize); 111 111 // Misc stuff 112 112 STDMETHOD(InternalGetStatistics)(ULONG *aCpuUser, ULONG *aCpuKernel, ULONG *aCpuIdle, … … 131 131 132 132 # ifdef VBOX_WITH_GUEST_CONTROL 133 HRESULT directoryCreateInternal(IN_BSTR aDirectory, IN_BSTR aUser Name, IN_BSTR aPassword,133 HRESULT directoryCreateInternal(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, 134 134 ULONG aMode, ULONG aFlags, int *pRC); 135 135 HRESULT directoryOpenInternal(IN_BSTR aDirectory, IN_BSTR aFilter, 136 136 ULONG aFlags, 137 IN_BSTR aUser Name, IN_BSTR aPassword,137 IN_BSTR aUsername, IN_BSTR aPassword, 138 138 ULONG *aHandle, int *pRC); 139 HRESULT executeAndWaitForTool(IN_BSTR aTool, IN_BSTR aDescription, 140 ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment), 141 IN_BSTR aUsername, IN_BSTR aPassword, 142 IProgress **aProgress, ULONG *aPID); 143 HRESULT executeCollectOutput(ULONG aPID, GuestCtrlStreamObjects &streamObjects); 139 144 HRESULT executeProcessInternal(IN_BSTR aCommand, ULONG aFlags, 140 145 ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment), 141 IN_BSTR aUser Name, IN_BSTR aPassword,146 IN_BSTR aUsername, IN_BSTR aPassword, 142 147 ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress, int *pRC); 143 HRESULT fileExistsInternal(IN_BSTR aFile, IN_BSTR aUser Name, IN_BSTR aPassword, BOOL *aExists, int *pRC);144 HRESULT fileQuerySizeInternal(IN_BSTR aFile, IN_BSTR aUser Name, IN_BSTR aPassword, LONG64 *aSize, int *pRC);148 HRESULT fileExistsInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists, int *pRC); 149 HRESULT fileQuerySizeInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, LONG64 *aSize, int *pRC); 145 150 146 151 // Guest control dispatcher. -
trunk/src/VBox/Main/src-client/GuestCtrlIO.cpp
r38235 r38269 28 28 29 29 /** @todo *NOT* thread safe yet! */ 30 /** @todo Add exception handling for STL stuff! */ 31 32 GuestProcessStreamBlock::GuestProcessStreamBlock() 33 { 34 35 } 36 37 GuestProcessStreamBlock::~GuestProcessStreamBlock() 38 { 39 Clear(); 40 } 41 42 /** 43 * Adds a key (if not existing yet). 44 * 45 * @return IPRT status code. 46 * @param pszKey Key name to add. 47 */ 48 int GuestProcessStreamBlock::AddKey(const char *pszKey) 49 { 50 AssertPtrReturn(pszKey, VERR_INVALID_POINTER); 51 /** @todo Add check for already existing keys! (VERR_ALREADY_EXISTS). */ 52 m_mapPairs[Utf8Str(pszKey)].pszValue = NULL; 53 54 return VINF_SUCCESS; 55 } 56 57 /** 58 * Destroys the currently stored stream pairs. 59 * 60 * @return IPRT status code. 61 */ 62 void GuestProcessStreamBlock::Clear() 63 { 64 for (GuestCtrlStreamPairsIter it = m_mapPairs.begin(); it != m_mapPairs.end(); it++) 65 { 66 if (it->second.pszValue) 67 RTMemFree(it->second.pszValue); 68 } 69 70 m_mapPairs.clear(); 71 } 72 73 /** 74 * Returns a 64-bit signed integer of a specified key. 75 * 76 * @return IPRT status code. VERR_NOT_FOUND if key was not found. 77 * @param pszKey Name of key to get the value for. 78 * @param piVal Pointer to value to return. 79 */ 80 int GuestProcessStreamBlock::GetInt64Ex(const char *pszKey, int64_t *piVal) 81 { 82 AssertPtrReturn(pszKey, VERR_INVALID_POINTER); 83 AssertPtrReturn(piVal, VERR_INVALID_POINTER); 84 const char *pszValue = GetString(pszKey); 85 if (pszValue) 86 { 87 *piVal = RTStrToInt64(pszValue); 88 return VINF_SUCCESS; 89 } 90 return VERR_NOT_FOUND; 91 } 92 93 /** 94 * Returns a 64-bit integer of a specified key. 95 * 96 * @return int64_t Value to return, 0 if not found / on failure. 97 * @param pszKey Name of key to get the value for. 98 */ 99 int64_t GuestProcessStreamBlock::GetInt64(const char *pszKey) 100 { 101 int64_t iVal; 102 if (RT_SUCCESS(GetInt64Ex(pszKey, &iVal))) 103 return iVal; 104 return 0; 105 } 106 107 /** 108 * Returns the current number of stream pairs. 109 * 110 * @return uint32_t Current number of stream pairs. 111 */ 112 size_t GuestProcessStreamBlock::GetCount() 113 { 114 return m_mapPairs.size(); 115 } 116 117 118 /** 119 * Returns a string value of a specified key. 120 * 121 * @return uint32_t Pointer to string to return, NULL if not found / on failure. 122 * @param pszKey Name of key to get the value for. 123 */ 124 const char* GuestProcessStreamBlock::GetString(const char *pszKey) 125 { 126 AssertPtrReturn(pszKey, NULL); 127 128 try 129 { 130 GuestCtrlStreamPairsIterConst itPairs = m_mapPairs.find(Utf8Str(pszKey)); 131 if (itPairs != m_mapPairs.end()) 132 return itPairs->second.pszValue; 133 } 134 catch (const std::exception &ex) 135 { 136 NOREF(ex); 137 } 138 return NULL; 139 } 140 141 /** 142 * Returns a 32-bit unsigned integer of a specified key. 143 * 144 * @return IPRT status code. VERR_NOT_FOUND if key was not found. 145 * @param pszKey Name of key to get the value for. 146 * @param puVal Pointer to value to return. 147 */ 148 int GuestProcessStreamBlock::GetUInt32Ex(const char *pszKey, uint32_t *puVal) 149 { 150 AssertPtrReturn(pszKey, VERR_INVALID_POINTER); 151 AssertPtrReturn(puVal, VERR_INVALID_POINTER); 152 const char *pszValue = GetString(pszKey); 153 if (pszValue) 154 { 155 *puVal = RTStrToUInt32(pszValue); 156 return VINF_SUCCESS; 157 } 158 return VERR_NOT_FOUND; 159 } 160 161 /** 162 * Returns a 32-bit unsigned integer of a specified key. 163 * 164 * @return uint32_t Value to return, 0 if not found / on failure. 165 * @param pszKey Name of key to get the value for. 166 */ 167 uint32_t GuestProcessStreamBlock::GetUInt32(const char *pszKey) 168 { 169 uint32_t uVal; 170 if (RT_SUCCESS(GetUInt32Ex(pszKey, &uVal))) 171 return uVal; 172 return 0; 173 } 174 175 /** 176 * Sets a value to a key or deletes a key by setting a NULL value. 177 * 178 * @return IPRT status code. 179 * @param pszKey Key name to process. 180 * @param pszValue Value to set. Set NULL for deleting the key. 181 */ 182 int GuestProcessStreamBlock::SetValue(const char *pszKey, const char *pszValue) 183 { 184 AssertPtrReturn(pszKey, VERR_INVALID_POINTER); 185 186 int rc = VINF_SUCCESS; 187 if (pszValue) 188 { 189 char *pszVal = RTStrDup(pszValue); 190 if (pszVal) 191 m_mapPairs[pszKey].pszValue = pszVal; 192 else 193 rc = VERR_NO_MEMORY; 194 } 195 else 196 { 197 GuestCtrlStreamPairsIter it = m_mapPairs.find(pszKey); 198 if (it != m_mapPairs.end()) 199 { 200 if (it->second.pszValue) 201 { 202 RTMemFree(it->second.pszValue); 203 it->second.pszValue = NULL; 204 } 205 m_mapPairs.erase(it); 206 } 207 } 208 return rc; 209 } 210 211 /////////////////////////////////////////////////////////////////////////////// 30 212 31 213 GuestProcessStream::GuestProcessStream() … … 115 297 116 298 /** 117 * Destroys the currently stored stream pairs. 118 * 119 * @return IPRT status code. 120 */ 121 void GuestProcessStream::ClearPairs() 122 { 123 for (GuestCtrlStreamPairsIter it = m_mapPairs.begin(); it != m_mapPairs.end(); it++) 124 { 125 if (it->second.pszValue) 126 RTMemFree(it->second.pszValue); 127 } 128 129 m_mapPairs.clear(); 130 } 131 132 /** 133 * Destroys the currently stored stream pairs and the internal 134 * data buffer. 299 * Destroys the the internal data buffer. 135 300 */ 136 301 void GuestProcessStream::Destroy() 137 302 { 138 ClearPairs();139 140 303 if (m_pbBuffer) 141 304 { … … 150 313 151 314 /** 152 * Returns a 64-bit signed integer of a specified key.153 *154 * @return IPRT status code. VERR_NOT_FOUND if key was not found.155 * @param pszKey Name of key to get the value for.156 * @param piVal Pointer to value to return.157 */158 int GuestProcessStream::GetInt64Ex(const char *pszKey, int64_t *piVal)159 {160 AssertPtrReturn(pszKey, VERR_INVALID_POINTER);161 AssertPtrReturn(piVal, VERR_INVALID_POINTER);162 const char *pszValue = GetString(pszKey);163 if (pszValue)164 {165 *piVal = RTStrToInt64(pszValue);166 return VINF_SUCCESS;167 }168 return VERR_NOT_FOUND;169 }170 171 /**172 * Returns a 64-bit integer of a specified key.173 *174 * @return int64_t Value to return, 0 if not found / on failure.175 * @param pszKey Name of key to get the value for.176 */177 int64_t GuestProcessStream::GetInt64(const char *pszKey)178 {179 int64_t iVal;180 if (RT_SUCCESS(GetInt64Ex(pszKey, &iVal)))181 return iVal;182 return 0;183 }184 185 /**186 * Returns the current number of stream pairs.187 *188 * @return uint32_t Current number of stream pairs.189 */190 size_t GuestProcessStream::GetNumPairs()191 {192 return m_mapPairs.size();193 }194 195 /**196 315 * Returns the current offset of the parser within 197 316 * the internal data buffer. … … 205 324 206 325 /** 207 * Returns a string value of a specified key.208 *209 * @return uint32_t Pointer to string to return, NULL if not found / on failure.210 * @param pszKey Name of key to get the value for.211 */212 const char* GuestProcessStream::GetString(const char *pszKey)213 {214 AssertPtrReturn(pszKey, NULL);215 216 try217 {218 GuestCtrlStreamPairsIterConst itPairs = m_mapPairs.find(Utf8Str(pszKey));219 if (itPairs != m_mapPairs.end())220 return itPairs->second.pszValue;221 }222 catch (const std::exception &ex)223 {224 NOREF(ex);225 }226 return NULL;227 }228 229 /**230 * Returns a 32-bit unsigned integer of a specified key.231 *232 * @return IPRT status code. VERR_NOT_FOUND if key was not found.233 * @param pszKey Name of key to get the value for.234 * @param puVal Pointer to value to return.235 */236 int GuestProcessStream::GetUInt32Ex(const char *pszKey, uint32_t *puVal)237 {238 AssertPtrReturn(pszKey, VERR_INVALID_POINTER);239 AssertPtrReturn(puVal, VERR_INVALID_POINTER);240 const char *pszValue = GetString(pszKey);241 if (pszValue)242 {243 *puVal = RTStrToUInt32(pszValue);244 return VINF_SUCCESS;245 }246 return VERR_NOT_FOUND;247 }248 249 /**250 * Returns a 32-bit unsigned integer of a specified key.251 *252 * @return uint32_t Value to return, 0 if not found / on failure.253 * @param pszKey Name of key to get the value for.254 */255 uint32_t GuestProcessStream::GetUInt32(const char *pszKey)256 {257 uint32_t uVal;258 if (RT_SUCCESS(GetUInt32Ex(pszKey, &uVal)))259 return uVal;260 return 0;261 }262 263 /**264 326 * Try to parse the next upcoming pair block within the internal 265 327 * buffer. Old pairs from a previously parsed block will be removed first! … … 267 329 * @return IPRT status code. 268 330 */ 269 int GuestProcessStream::ParseBlock( )331 int GuestProcessStream::ParseBlock(GuestProcessStreamBlock &streamBlock) 270 332 { 271 333 AssertPtrReturn(m_pbBuffer, VINF_SUCCESS); 272 334 AssertReturn(m_cbSize, VINF_SUCCESS); 273 335 AssertReturn(m_cbOffset <= m_cbSize, VERR_INVALID_PARAMETER); 274 275 /* Since we want to (try to) parse another block, clear276 * all pairs from a previously parsed block. */277 ClearPairs();278 336 279 337 int rc = VINF_SUCCESS; … … 329 387 memcpy(pszKey, pszStart, uKeyLen); 330 388 331 m_mapPairs[Utf8Str(pszKey)].pszValue = NULL;389 streamBlock.AddKey(pszKey); 332 390 333 391 /* Get value (if present). */ … … 343 401 memcpy(pszVal, pszSep + 1, uValLen); 344 402 345 m_mapPairs[Utf8Str(pszKey)].pszValue = pszVal; 403 streamBlock.SetValue(pszKey, pszVal); 404 RTMemFree(pszVal); 346 405 } 347 406 -
trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp
r38235 r38269 1094 1094 STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags, 1095 1095 ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment), 1096 IN_BSTR aUserName, IN_BSTR aPassword,1096 IN_BSTR Username, IN_BSTR aPassword, 1097 1097 ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress) 1098 1098 { … … 1109 1109 1110 1110 /* Do not allow anonymous executions (with system rights). */ 1111 if (RT_UNLIKELY(( aUserName) == NULL || *(aUserName) == '\0'))1111 if (RT_UNLIKELY((Username) == NULL || *(Username) == '\0')) 1112 1112 return setError(E_INVALIDARG, tr("No user name specified")); 1113 1113 1114 1114 LogRel(("Executing guest process \"%s\" as user \"%s\" ...\n", 1115 Utf8Str(aCommand).c_str(), Utf8Str( aUserName).c_str()));1115 Utf8Str(aCommand).c_str(), Utf8Str(Username).c_str())); 1116 1116 1117 1117 return executeProcessInternal(aCommand, aFlags, ComSafeArrayInArg(aArguments), 1118 1118 ComSafeArrayInArg(aEnvironment), 1119 aUserName, aPassword, aTimeoutMS, aPID, aProgress, NULL /* rc */);1119 Username, aPassword, aTimeoutMS, aPID, aProgress, NULL /* rc */); 1120 1120 #endif 1121 1121 } 1122 1122 1123 1123 #ifdef VBOX_WITH_GUEST_CONTROL 1124 /** 1125 * Executes and waits for an internal tool (that is, a tool which is integrated into 1126 * VBoxService, beginning with "vbox_" (e.g. "vbox_ls")). 1127 * 1128 * @return HRESULT 1129 * @param aTool Name of tool to execute. 1130 * @param aDescription Friendly description of the operation. 1131 * @param aFlags Execution flags. 1132 * @param Username Username to execute tool under. 1133 * @param aPassword The user's password. 1134 * @param aProgress Pointer which receives the tool's progress object. Optional. 1135 * @param aPID Pointer which receives the tool's PID. Optional. 1136 */ 1137 HRESULT Guest::executeAndWaitForTool(IN_BSTR aTool, IN_BSTR aDescription, 1138 ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment), 1139 IN_BSTR Username, IN_BSTR aPassword, 1140 IProgress **aProgress, ULONG *aPID) 1141 { 1142 ComPtr<IProgress> progressTool; 1143 ULONG uPID; 1144 1145 HRESULT rc = ExecuteProcess(aTool, 1146 ExecuteProcessFlag_Hidden, 1147 aArguments, aEnvironment, 1148 Username, aPassword, 1149 5 * 1000 /* Wait 5s for getting the process started. */, 1150 &uPID, progressTool.asOutParam()); 1151 if (SUCCEEDED(rc)) 1152 { 1153 /* Wait for process to exit ... */ 1154 rc = progressTool->WaitForCompletion(-1); 1155 if (FAILED(rc)) return rc; 1156 1157 BOOL fCompleted = FALSE; 1158 BOOL fCanceled = FALSE; 1159 progressTool->COMGETTER(Completed)(&fCompleted); 1160 if (!fCompleted) 1161 progressTool->COMGETTER(Canceled)(&fCanceled); 1162 1163 if (fCompleted) 1164 { 1165 ExecuteProcessStatus_T retStatus; 1166 ULONG uRetExitCode, uRetFlags; 1167 if (SUCCEEDED(rc)) 1168 { 1169 rc = GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus); 1170 if (SUCCEEDED(rc)) 1171 { 1172 if (!uRetExitCode) 1173 { 1174 rc = setError(VBOX_E_IPRT_ERROR, 1175 tr("Error %u occurred while %s"), 1176 uRetExitCode, Utf8Str(aDescription).c_str()); 1177 } 1178 else 1179 { 1180 if (aProgress) 1181 { 1182 /* Return the progress to the caller. */ 1183 progressTool.queryInterfaceTo(aProgress); 1184 } 1185 if (aPID) 1186 *aPID = uPID; 1187 } 1188 } 1189 } 1190 } 1191 else if (fCanceled) 1192 { 1193 rc = setError(VBOX_E_IPRT_ERROR, 1194 tr("%s was aborted"), aDescription); 1195 } 1196 else 1197 AssertReleaseMsgFailed(("Operation \"%s\" neither completed nor canceled!?\n", 1198 Utf8Str(aDescription).c_str())); 1199 } 1200 1201 return rc; 1202 } 1203 1204 HRESULT Guest::executeCollectOutput(ULONG aPID, GuestCtrlStreamObjects &streamObjects) 1205 { 1206 SafeArray<BYTE> aOutputData; 1207 ULONG cbOutputData = 0; 1208 1209 int rc = S_OK; 1210 GuestProcessStream guestStream; 1211 1212 for (;;) 1213 { 1214 rc = this->GetProcessOutput(aPID, ProcessOutputFlag_None, 1215 10 * 1000 /* Timeout in ms */, 1216 _64K, ComSafeArrayAsOutParam(aOutputData)); 1217 if ( SUCCEEDED(rc) 1218 && aOutputData.size()) 1219 { 1220 int vrc = guestStream.AddData(aOutputData.raw(), aOutputData.size()); 1221 if (RT_UNLIKELY(RT_FAILURE(vrc))) 1222 rc = setError(VBOX_E_IPRT_ERROR, 1223 tr("Error while adding guest output to stream buffer (%Rrc)"), vrc); 1224 } 1225 else /* No more output! */ 1226 break; 1227 } 1228 1229 if (SUCCEEDED(rc)) 1230 { 1231 GuestProcessStreamBlock curPairs; 1232 int vrc = guestStream.ParseBlock(curPairs); 1233 if ( RT_SUCCESS(vrc) 1234 || vrc == VERR_MORE_DATA) 1235 { 1236 /** @todo Catch exceptions! */ 1237 if (curPairs.GetCount()) 1238 streamObjects.push_back(curPairs); 1239 } 1240 else 1241 rc = setError(VBOX_E_IPRT_ERROR, 1242 tr("Error while parsing guest output (%Rrc)"), vrc); 1243 } 1244 1245 return rc; 1246 } 1247 1248 /** 1249 * Does the actual guest process execution, internal function. 1250 * 1251 * @return HRESULT 1252 * @param aCommand Command line to execute. 1253 * @param aFlags Execution flags. 1254 * @param Username Username to execute the process with. 1255 * @param aPassword The user's password. 1256 * @param aTimeoutMS Timeout (in ms) to wait for the execution operation. 1257 * @param aPID Pointer that receives the guest process' PID. 1258 * @param aProgress Pointer that receives the guest process' progress object. 1259 * @param pRC Pointer that receives the internal IPRT return code. Optional. 1260 */ 1124 1261 HRESULT Guest::executeProcessInternal(IN_BSTR aCommand, ULONG aFlags, 1125 1262 ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment), 1126 IN_BSTR aUserName, IN_BSTR aPassword,1263 IN_BSTR Username, IN_BSTR aPassword, 1127 1264 ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress, int *pRC) 1128 1265 { … … 1198 1335 } 1199 1336 1200 Utf8Str Utf8UserName( aUserName);1337 Utf8Str Utf8UserName(Username); 1201 1338 Utf8Str Utf8Password(aPassword); 1202 1339 if (RT_SUCCESS(vrc)) … … 1778 1915 1779 1916 STDMETHODIMP Guest::CopyFromGuest(IN_BSTR aSource, IN_BSTR aDest, 1780 IN_BSTR aUserName, IN_BSTR aPassword,1917 IN_BSTR Username, IN_BSTR aPassword, 1781 1918 ULONG aFlags, IProgress **aProgress) 1782 1919 { … … 1786 1923 CheckComArgStrNotEmptyOrNull(aSource); 1787 1924 CheckComArgStrNotEmptyOrNull(aDest); 1788 CheckComArgStrNotEmptyOrNull( aUserName);1925 CheckComArgStrNotEmptyOrNull(Username); 1789 1926 CheckComArgStrNotEmptyOrNull(aPassword); 1790 1927 CheckComArgOutPointerValid(aProgress); … … 1828 1965 task->strSource = (Utf8Str(aSource)); 1829 1966 task->strDest = (Utf8Str(aDest)); 1830 task->strUserName = (Utf8Str( aUserName));1967 task->strUserName = (Utf8Str(Username)); 1831 1968 task->strPassword = (Utf8Str(aPassword)); 1832 1969 task->uFlags = aFlags; … … 1853 1990 1854 1991 STDMETHODIMP Guest::CopyToGuest(IN_BSTR aSource, IN_BSTR aDest, 1855 IN_BSTR aUserName, IN_BSTR aPassword,1992 IN_BSTR Username, IN_BSTR aPassword, 1856 1993 ULONG aFlags, IProgress **aProgress) 1857 1994 { … … 1861 1998 CheckComArgStrNotEmptyOrNull(aSource); 1862 1999 CheckComArgStrNotEmptyOrNull(aDest); 1863 CheckComArgStrNotEmptyOrNull( aUserName);2000 CheckComArgStrNotEmptyOrNull(Username); 1864 2001 CheckComArgStrNotEmptyOrNull(aPassword); 1865 2002 CheckComArgOutPointerValid(aProgress); … … 1903 2040 task->strSource = (Utf8Str(aSource)); 1904 2041 task->strDest = (Utf8Str(aDest)); 1905 task->strUserName = (Utf8Str( aUserName));2042 task->strUserName = (Utf8Str(Username)); 1906 2043 task->strPassword = (Utf8Str(aPassword)); 1907 2044 task->uFlags = aFlags; -
trunk/src/VBox/Main/src-client/GuestCtrlImplDir.cpp
r38235 r38269 77 77 #ifdef VBOX_WITH_GUEST_CONTROL 78 78 HRESULT Guest::directoryCreateInternal(IN_BSTR aDirectory, 79 IN_BSTR aUser Name, IN_BSTR aPassword,79 IN_BSTR aUsername, IN_BSTR aPassword, 80 80 ULONG aMode, ULONG aFlags, int *pRC) 81 81 { … … 100 100 { 101 101 Utf8Str Utf8Directory(aDirectory); 102 Utf8Str Utf8UserName(aUserName);103 Utf8Str Utf8Password(aPassword);104 102 105 103 com::SafeArray<IN_BSTR> args; … … 121 119 args.push_back(Bstr(Utf8Directory).raw()); /* The directory we want to create. */ 122 120 123 /* 124 * Execute guest process. 125 */ 126 ComPtr<IProgress> progressExec; 127 ULONG uPID; 128 if (SUCCEEDED(rc)) 129 { 130 rc = ExecuteProcess(Bstr(VBOXSERVICE_TOOL_MKDIR).raw(), 131 ExecuteProcessFlag_Hidden, 132 ComSafeArrayAsInParam(args), 133 ComSafeArrayAsInParam(env), 134 Bstr(Utf8UserName).raw(), 135 Bstr(Utf8Password).raw(), 136 5 * 1000 /* Wait 5s for getting the process started. */, 137 &uPID, progressExec.asOutParam()); 138 } 139 140 if (SUCCEEDED(rc)) 141 { 142 /* Wait for process to exit ... */ 143 rc = progressExec->WaitForCompletion(-1); 144 if (FAILED(rc)) return rc; 145 146 BOOL fCompleted = FALSE; 147 BOOL fCanceled = FALSE; 148 progressExec->COMGETTER(Completed)(&fCompleted); 149 if (!fCompleted) 150 progressExec->COMGETTER(Canceled)(&fCanceled); 151 152 if (fCompleted) 153 { 154 ExecuteProcessStatus_T retStatus; 155 ULONG uRetExitCode, uRetFlags; 156 if (SUCCEEDED(rc)) 157 { 158 rc = GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus); 159 if (SUCCEEDED(rc) && uRetExitCode != 0) 160 { 161 rc = setError(VBOX_E_IPRT_ERROR, 162 tr("Error %u while creating guest directory"), uRetExitCode); 163 } 164 } 165 } 166 else if (fCanceled) 167 rc = setError(VBOX_E_IPRT_ERROR, 168 tr("Guest directory creation was aborted")); 169 else 170 AssertReleaseMsgFailed(("Guest directory creation neither completed nor canceled!?\n")); 171 } 121 rc = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_MKDIR).raw(), Bstr("Creating directory").raw(), 122 ComSafeArrayAsInParam(args), 123 ComSafeArrayAsInParam(env), 124 aUsername, aPassword, 125 NULL /* Progress */, NULL /* PID */); 172 126 } 173 127 catch (std::bad_alloc &) … … 180 134 /** 181 135 * Creates a new directory handle ID and returns it. Returns VERR_TOO_MUCH_DATA 182 * if no free handles left, otherwise VINF_SUCCESS .136 * if no free handles left, otherwise VINF_SUCCESS (or some other IPRT error). 183 137 * 184 138 * @return IPRT status code. … … 323 277 HRESULT Guest::directoryOpenInternal(IN_BSTR aDirectory, IN_BSTR aFilter, 324 278 ULONG aFlags, 325 IN_BSTR aUser Name, IN_BSTR aPassword,279 IN_BSTR aUsername, IN_BSTR aPassword, 326 280 ULONG *aHandle, int *pRC) 327 281 { … … 343 297 Utf8Str Utf8Directory(aDirectory); 344 298 Utf8Str Utf8Filter(aFilter); 345 Utf8Str Utf8UserName(aUserName);346 Utf8Str Utf8Password(aPassword);347 299 348 300 com::SafeArray<IN_BSTR> args; … … 378 330 args.push_back(Bstr(pszDirectoryFinal).raw()); /* The directory we want to open. */ 379 331 380 /*381 * Execute guest process.382 */383 ComPtr<IProgress> progressExec;384 332 ULONG uPID; 385 386 rc = ExecuteProcess(Bstr(VBOXSERVICE_TOOL_LS).raw(), 387 ExecuteProcessFlag_Hidden, 388 ComSafeArrayAsInParam(args), 389 ComSafeArrayAsInParam(env), 390 Bstr(Utf8UserName).raw(), 391 Bstr(Utf8Password).raw(), 392 30 * 1000 /* Wait 30s for getting the process started. */, 393 &uPID, progressExec.asOutParam()); 394 395 RTStrFree(pszDirectoryFinal); 396 333 rc = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_LS).raw(), Bstr("Opening directory").raw(), 334 ComSafeArrayAsInParam(args), 335 ComSafeArrayAsInParam(env), 336 aUsername, aPassword, 337 NULL /* Progress */, &uPID); 397 338 if (SUCCEEDED(rc)) 398 339 { 399 /* Wait for process to exit ... */ 400 rc = progressExec->WaitForCompletion(-1); 401 if (FAILED(rc)) return rc; 402 403 BOOL fCompleted = FALSE; 404 BOOL fCanceled = FALSE; 405 progressExec->COMGETTER(Completed)(&fCompleted); 406 if (!fCompleted) 407 progressExec->COMGETTER(Canceled)(&fCanceled); 408 409 if (fCompleted) 410 { 411 ExecuteProcessStatus_T retStatus; 412 ULONG uRetExitCode, uRetFlags; 413 if (SUCCEEDED(rc)) 414 { 415 rc = GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus); 416 if (SUCCEEDED(rc) && uRetExitCode != 0) 417 { 418 rc = setError(VBOX_E_IPRT_ERROR, 419 tr("Error %u while opening guest directory"), uRetExitCode); 420 } 421 } 422 } 423 else if (fCanceled) 340 /* Assign new directory handle ID. */ 341 int vrc = directoryCreateHandle(aHandle, uPID, 342 Utf8Directory.c_str(), 343 Utf8Filter.isEmpty() ? NULL : Utf8Filter.c_str(), 344 aFlags); 345 if (RT_FAILURE(vrc)) 424 346 rc = setError(VBOX_E_IPRT_ERROR, 425 tr("Guest directory opening was aborted")); 426 else 427 AssertReleaseMsgFailed(("Guest directory opening neither completed nor canceled!?\n")); 428 429 if (SUCCEEDED(rc)) 430 { 431 /* Assign new directory handle ID. */ 432 int vrc = directoryCreateHandle(aHandle, uPID, 433 Utf8Directory.c_str(), 434 Utf8Filter.isEmpty() ? NULL : Utf8Filter.c_str(), 435 aFlags); 436 if (RT_FAILURE(vrc)) 437 { 438 rc = setError(VBOX_E_IPRT_ERROR, 439 tr("Unable to create guest directory handle (%Rrc)"), vrc); 440 } 441 } 347 tr("Unable to create guest directory handle (%Rrc)"), vrc); 442 348 } 443 349 } -
trunk/src/VBox/Main/src-client/GuestCtrlImplFile.cpp
r38235 r38269 33 33 #endif 34 34 35 STDMETHODIMP Guest::FileExists(IN_BSTR aFile, IN_BSTR aUser Name, IN_BSTR aPassword, BOOL *aExists)35 STDMETHODIMP Guest::FileExists(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists) 36 36 { 37 37 #ifndef VBOX_WITH_GUEST_CONTROL … … 43 43 44 44 /* Do not allow anonymous executions (with system rights). */ 45 if (RT_UNLIKELY((aUser Name) == NULL || *(aUserName) == '\0'))45 if (RT_UNLIKELY((aUsername) == NULL || *(aUsername) == '\0')) 46 46 return setError(E_INVALIDARG, tr("No user name specified")); 47 47 48 48 return fileExistsInternal(aFile, 49 aUser Name, aPassword, aExists,49 aUsername, aPassword, aExists, 50 50 NULL /* rc */); 51 51 #endif … … 53 53 54 54 #ifdef VBOX_WITH_GUEST_CONTROL 55 HRESULT Guest::fileExistsInternal(IN_BSTR aFile, IN_BSTR aUser Name, IN_BSTR aPassword, BOOL *aExists, int *pRC)55 HRESULT Guest::fileExistsInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists, int *pRC) 56 56 { 57 57 using namespace guestControl; … … 66 66 { 67 67 Utf8Str Utf8File(aFile); 68 Utf8Str Utf8User Name(aUserName);68 Utf8Str Utf8Username(aUsername); 69 69 Utf8Str Utf8Password(aPassword); 70 70 … … 86 86 * Execute guest process. 87 87 */ 88 ComPtr<IProgress> progressExec; 89 ULONG uPID; 88 rc = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_STAT).raw(), Bstr("Checking for file existence").raw(), 89 ComSafeArrayAsInParam(args), 90 ComSafeArrayAsInParam(env), 91 aUsername, aPassword, 92 NULL /* Progress */, NULL /* PID */); 90 93 91 rc = ExecuteProcess(Bstr(VBOXSERVICE_TOOL_STAT).raw(), 92 ExecuteProcessFlag_Hidden, 93 ComSafeArrayAsInParam(args), 94 ComSafeArrayAsInParam(env), 95 Bstr(Utf8UserName).raw(), 96 Bstr(Utf8Password).raw(), 97 30 * 1000 /* Wait 30s for getting the process started. */, 98 &uPID, progressExec.asOutParam()); 99 100 if (SUCCEEDED(rc)) 101 { 102 /* Wait for process to exit ... */ 103 rc = progressExec->WaitForCompletion(-1); 104 if (FAILED(rc)) return rc; 105 106 BOOL fCompleted = FALSE; 107 BOOL fCanceled = FALSE; 108 progressExec->COMGETTER(Completed)(&fCompleted); 109 if (!fCompleted) 110 progressExec->COMGETTER(Canceled)(&fCanceled); 111 112 if (fCompleted) 113 { 114 ExecuteProcessStatus_T retStatus; 115 ULONG uRetExitCode, uRetFlags; 116 if (SUCCEEDED(rc)) 117 { 118 rc = GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus); 119 if (SUCCEEDED(rc)) 120 { 121 *aExists = uRetExitCode == 0 ? TRUE : FALSE; 122 } 123 else 124 rc = setError(VBOX_E_IPRT_ERROR, 125 tr("Error %u while checking for existence of file \"%s\""), 126 uRetExitCode, Utf8File.c_str()); 127 } 128 } 129 else if (fCanceled) 130 rc = setError(VBOX_E_IPRT_ERROR, 131 tr("Checking for file existence was aborted")); 132 else 133 AssertReleaseMsgFailed(("Checking for file existence neither completed nor canceled!?\n")); 134 } 94 /* If the call succeeded the file exists, otherwise it does not. */ 95 *aExists = SUCCEEDED(rc) ? TRUE : FALSE; 135 96 } 136 97 catch (std::bad_alloc &) … … 142 103 #endif /* VBOX_WITH_GUEST_CONTROL */ 143 104 144 STDMETHODIMP Guest::FileQuerySize(IN_BSTR aFile, IN_BSTR aUser Name, IN_BSTR aPassword, LONG64 *aSize)105 STDMETHODIMP Guest::FileQuerySize(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, LONG64 *aSize) 145 106 { 146 107 #ifndef VBOX_WITH_GUEST_CONTROL … … 152 113 153 114 /* Do not allow anonymous executions (with system rights). */ 154 if (RT_UNLIKELY((aUser Name) == NULL || *(aUserName) == '\0'))115 if (RT_UNLIKELY((aUsername) == NULL || *(aUsername) == '\0')) 155 116 return setError(E_INVALIDARG, tr("No user name specified")); 156 117 157 118 return fileQuerySizeInternal(aFile, 158 aUser Name, aPassword, aSize,119 aUsername, aPassword, aSize, 159 120 NULL /* rc */); 160 121 #endif … … 162 123 163 124 #ifdef VBOX_WITH_GUEST_CONTROL 164 HRESULT Guest::fileQuerySizeInternal(IN_BSTR aFile, IN_BSTR aUser Name, IN_BSTR aPassword, LONG64 *aSize, int *pRC)125 HRESULT Guest::fileQuerySizeInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, LONG64 *aSize, int *pRC) 165 126 { 166 127 using namespace guestControl; … … 175 136 { 176 137 Utf8Str Utf8File(aFile); 177 Utf8Str Utf8User Name(aUserName);138 Utf8Str Utf8Username(aUsername); 178 139 Utf8Str Utf8Password(aPassword); 179 140 … … 195 156 * Execute guest process. 196 157 */ 197 ComPtr<IProgress> progress Exec;158 ComPtr<IProgress> progressFileSize; 198 159 ULONG uPID; 199 160 200 rc = ExecuteProcess(Bstr(VBOXSERVICE_TOOL_STAT).raw(), 201 ExecuteProcessFlag_Hidden, 202 ComSafeArrayAsInParam(args), 203 ComSafeArrayAsInParam(env), 204 Bstr(Utf8UserName).raw(), 205 Bstr(Utf8Password).raw(), 206 30 * 1000 /* Wait 30s for getting the process started. */, 207 &uPID, progressExec.asOutParam()); 208 161 rc = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_STAT).raw(), Bstr("Querying file size").raw(), 162 ComSafeArrayAsInParam(args), 163 ComSafeArrayAsInParam(env), 164 aUsername, aPassword, 165 progressFileSize.asOutParam(), &uPID); 209 166 if (SUCCEEDED(rc)) 210 167 { 211 /* Wait for process to exit ... */ 212 rc = progressExec->WaitForCompletion(-1); 213 if (FAILED(rc)) return rc; 214 215 BOOL fCompleted = FALSE; 216 BOOL fCanceled = FALSE; 217 progressExec->COMGETTER(Completed)(&fCompleted); 218 if (!fCompleted) 219 progressExec->COMGETTER(Canceled)(&fCanceled); 220 221 if (fCompleted) 168 GuestCtrlStreamObjects streamObjs; 169 rc = executeCollectOutput(uPID, streamObjs); 170 if (SUCCEEDED(rc)) 222 171 { 223 ExecuteProcessStatus_T retStatus; 224 ULONG uRetExitCode, uRetFlags; 225 if (SUCCEEDED(rc)) 226 { 227 rc = GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus); 228 if (SUCCEEDED(rc)) 229 { 230 if (uRetExitCode == 0) 231 { 232 /* Get file size from output stream. */ 233 SafeArray<BYTE> aOutputData; 234 ULONG cbOutputData = 0; 235 236 GuestProcessStream guestStream; 237 int vrc = VINF_SUCCESS; 238 for (;;) 239 { 240 rc = this->GetProcessOutput(uPID, ProcessOutputFlag_None, 241 10 * 1000 /* Timeout in ms */, 242 _64K, ComSafeArrayAsOutParam(aOutputData)); 243 /** @todo Do stream header validation! */ 244 if ( SUCCEEDED(rc) 245 && aOutputData.size()) 246 { 247 vrc = guestStream.AddData(aOutputData.raw(), aOutputData.size()); 248 if (RT_UNLIKELY(RT_FAILURE(vrc))) 249 rc = setError(VBOX_E_IPRT_ERROR, 250 tr("Query file size: Error while adding guest output to stream buffer for file \"%s\" (%Rrc)"), 251 Utf8File.c_str(), vrc); 252 } 253 else /* No more output! */ 254 break; 255 } 256 257 if (SUCCEEDED(rc)) 258 { 259 vrc = guestStream.ParseBlock(); /* We only need one (the first) block. */ 260 if ( RT_SUCCESS(vrc) 261 || vrc == VERR_MORE_DATA) 262 { 263 int64_t iVal; 172 /** @todo */ 173 #if 0 174 int64_t iVal; 264 175 vrc = guestStream.GetInt64Ex("st_size", &iVal); 265 176 if (RT_SUCCESS(vrc)) … … 269 180 tr("Query file size: Unable to retrieve file size for file \"%s\" (%Rrc)"), 270 181 Utf8File.c_str(), vrc); 271 } 272 else 273 rc = setError(VBOX_E_IPRT_ERROR, 274 tr("Query file size: Error while parsing guest output for file \"%s\" (%Rrc)"), 275 Utf8File.c_str(), vrc); 276 } 277 } 278 else 279 rc = setError(VBOX_E_IPRT_ERROR, 280 tr("Query file size: Error querying file size for file \"%s\" (exit code %u)"), 281 Utf8File.c_str(), uRetExitCode); 282 } 283 } 182 #endif 284 183 } 285 else if (fCanceled)286 rc = setError(VBOX_E_IPRT_ERROR,287 tr("Query file size: Checking for file size was aborted"));288 else289 AssertReleaseMsgFailed(("Checking for file size neither completed nor canceled!?\n"));290 184 } 291 185 } -
trunk/src/VBox/Main/testcase/tstGuestCtrlParseBuffer.cpp
r38235 r38269 144 144 if (RT_SUCCESS(iResult)) 145 145 { 146 iResult = stream.ParseBlock(); 146 GuestProcessStreamBlock block; 147 iResult = stream.ParseBlock(block); 147 148 if (iResult != aTests[iTest].iResult) 148 149 { … … 150 151 iResult, aTests[iTest].iResult); 151 152 } 152 else if ( stream.GetNumPairs() != aTests[iTest].uMapElements)153 else if (block.GetCount() != aTests[iTest].uMapElements) 153 154 { 154 155 RTTestFailed(hTest, "\tMap has %u elements, expected %u", 155 stream.GetNumPairs(), aTests[iTest].uMapElements);156 block.GetCount(), aTests[iTest].uMapElements); 156 157 } 157 158 else if (stream.GetOffset() != aTests[iTest].uOffsetAfter) … … 192 193 do 193 194 { 194 iResult = stream.ParseBlock(); 195 GuestProcessStreamBlock block; 196 iResult = stream.ParseBlock(block); 195 197 RTTestIPrintf(RTTESTLVL_DEBUG, "\tReturned with %Rrc\n", iResult); 196 198 if ( iResult == VINF_SUCCESS … … 198 200 { 199 201 /* Only count block which have at least one pair. */ 200 if (stream.GetNumPairs()) 201 { 202 if (block.GetCount()) 202 203 uNumBlocks++; 203 stream.ClearPairs();204 }205 204 } 206 205 if (uNumBlocks > 32) 207 206 break; /* Give up if unreasonable big. */ 207 block.Clear(); 208 208 } while (iResult == VERR_MORE_DATA); 209 209
Note:
See TracChangeset
for help on using the changeset viewer.