- Timestamp:
- Aug 10, 2011 11:48:29 AM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 73430
- Location:
- trunk/src/VBox
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp
r38180 r38395 1359 1359 Assert(uStatus > INPUT_STS_UNDEFINED); 1360 1360 1361 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Input processed, uStatus=%u, uFlags=0x%x, cbWritten=%u\n",1362 uPID, u Status, uFlags, cbWritten);1361 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Input processed, CID=%u, uStatus=%u, uFlags=0x%x, cbWritten=%u\n", 1362 uPID, uContextID, uStatus, uFlags, cbWritten); 1363 1363 1364 1364 /* Note: Since the context ID is unique the request *has* to be completed here, … … 1401 1401 pBuf, _64K /* cbSize */, &cbRead); 1402 1402 if (RT_SUCCESS(rc)) 1403 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Got output, cbRead=%u, uHandle=%u, uFlags=%u\n",1404 uPID, cbRead, uHandleID, uFlags);1403 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Got output, CID=%u, cbRead=%u, uHandle=%u, uFlags=%u\n", 1404 uPID, uContextID, cbRead, uHandleID, uFlags); 1405 1405 else 1406 VBoxServiceError("ControlExec: [PID %u]: Failed to retrieve output, uHandle=%u, rc=%Rrc\n",1407 uPID, u HandleID, rc);1406 VBoxServiceError("ControlExec: [PID %u]: Failed to retrieve output, CID=%u, uHandle=%u, rc=%Rrc\n", 1407 uPID, uContextID, uHandleID, rc); 1408 1408 1409 1409 /* Note: Since the context ID is unique the request *has* to be completed here, -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
r38290 r38395 79 79 80 80 /** 81 * An entry for a source element, including an optional filter.81 * An entry for a source element, including an optional DOS-like wildcard (*,?). 82 82 */ 83 83 typedef struct SOURCEFILEENTRY … … 93 93 { 94 94 /* No file and no directory -- maybe a filter? */ 95 if (NULL != strpbrk(RTPathFilename(pszSource), "*?")) 95 char *pszFilename = RTPathFilename(pszSource); 96 if ( pszFilename 97 && strpbrk(pszFilename, "*?")) 96 98 { 97 99 /* Yep, get the actual filter part. */ … … 938 940 { 939 941 BOOL fDirExists = FALSE; 940 HRESULT hr = pContext->pGuest-> FileExists(Bstr(pszDir).raw(),941 Bstr(pContext->pszUsername).raw(),942 Bstr(pContext->pszPassword).raw(), &fDirExists);942 HRESULT hr = pContext->pGuest->DirectoryExists(Bstr(pszDir).raw(), 943 Bstr(pContext->pszUsername).raw(), 944 Bstr(pContext->pszPassword).raw(), &fDirExists); 943 945 if (FAILED(hr)) 944 946 rc = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest)); … … 1271 1273 case GuestDirEntryType_File: 1272 1274 { 1273 const char *pszName = Utf8Str(strName).c_str();1275 Utf8Str strFile(strName); 1274 1276 if ( !pszFilter 1275 || RTStrSimplePatternMatch(pszFilter, pszName))1277 || RTStrSimplePatternMatch(pszFilter, strFile.c_str())) 1276 1278 { 1277 1279 if (!fDirCreated) … … 1291 1293 if (RT_SUCCESS(rc)) 1292 1294 { 1293 Utf8Str strDir(strName);1294 1295 char *pszFileSource; 1295 1296 if (RTStrAPrintf(&pszFileSource, "%s/%s", 1296 szCurDir, str Dir.c_str()))1297 szCurDir, strFile.c_str())) 1297 1298 { 1298 1299 char *pszFileDest; … … 1307 1308 RTStrFree(pszFileSource); 1308 1309 } 1310 else 1311 rc = VERR_NO_MEMORY; 1309 1312 } 1310 1313 } … … 1315 1318 break; 1316 1319 } 1317 } 1318 1319 hr = pContext->pGuest->DirectoryClose(uDirHandle); 1320 if (FAILED(rc)) 1321 rc = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest)); 1320 1321 if (RT_FAILURE(rc)) 1322 break; 1323 } 1324 1325 if (FAILED(hr)) 1326 { 1327 if (hr != E_ABORT) 1328 rc = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest)); 1329 } 1330 1331 HRESULT hr2 = pContext->pGuest->DirectoryClose(uDirHandle); 1332 if (FAILED(hr2)) 1333 { 1334 int rc2 = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest)); 1335 if (RT_SUCCESS(rc)) 1336 rc = rc2; 1337 } 1338 else if (SUCCEEDED(hr)) 1339 hr = hr2; 1322 1340 } 1323 1341 … … 1549 1567 RTPrintf("Source: %s\n", pszSource); 1550 1568 1551 /* @todo Files with filter?? */1569 /** @todo Files with filter?? */ 1552 1570 bool fExists; 1553 1571 vrc = ctrlCopyFileExistsOnSource(pContext, pszSource, &fExists); -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r38186 r38395 8566 8566 <interface 8567 8567 name="IGuest" extends="$unknown" 8568 uuid=" ed109b6e-0578-4b17-8ace-52646789f1a0"8568 uuid="35f75ed7-df96-4988-b246-2c103555c95d" 8569 8569 wsmap="managed" 8570 8570 > … … 9009 9009 <desc> 9010 9010 <link to="DirectoryCreateFlag"/> flags. 9011 </desc> 9012 </param> 9013 </method> 9014 9015 <method name="directoryExists"> 9016 <desc> 9017 Checks if the specified directory exists and is a directory. 9018 9019 <result name="VBOX_E_IPRT_ERROR"> 9020 Error while looking up information. 9021 </result> 9022 9023 </desc> 9024 <param name="directory" type="wstring" dir="in"> 9025 <desc> 9026 Full path of directory to check. 9027 </desc> 9028 </param> 9029 <param name="userName" type="wstring" dir="in"> 9030 <desc> 9031 User name under which the lookup will be performed; the 9032 user has to exist and have the appropriate rights to access / read the 9033 desired directory. 9034 </desc> 9035 </param> 9036 <param name="password" type="wstring" dir="in"> 9037 <desc> 9038 Password of the user account specified. 9039 </desc> 9040 </param> 9041 <param name="exists" type="boolean" dir="return"> 9042 <desc> 9043 True if it's a directory, false if it isn't (or doesn't exist). 9011 9044 </desc> 9012 9045 </param> -
trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h
r38290 r38395 39 39 typedef struct VBOXGUESTCTRL_STREAMPAIR 40 40 { 41 char *pszValue; 41 VBOXGUESTCTRL_STREAMPAIR(const char *pszValue) 42 : mValue(pszValue) {} 43 44 Utf8Str mValue; 42 45 } VBOXGUESTCTRL_STREAMPAIR, *PVBOXGUESTCTRL_STREAM_PAIR; 43 46 … … 58 61 GuestProcessStreamBlock(); 59 62 63 //GuestProcessStreamBlock(GuestProcessStreamBlock &); 64 60 65 virtual ~GuestProcessStreamBlock(); 61 66 62 67 public: 63 64 int AddKey(const char *pszKey);65 68 66 69 void Clear(); … … 85 88 }; 86 89 87 /** Vector containing multiple stream pair objects. */ 88 typedef std::vector< GuestProcessStreamBlock > GuestCtrlStreamObjects; 90 /** Vector containing multiple allocated stream pair objects. */ 91 typedef std::vector< GuestProcessStreamBlock* > GuestCtrlStreamObjects; 92 typedef std::vector< GuestProcessStreamBlock* >::iterator GuestCtrlStreamObjectsIter; 93 typedef std::vector< GuestProcessStreamBlock* >::const_iterator GuestCtrlStreamObjectsIterConst; 89 94 90 95 /** … … 110 115 111 116 int ParseBlock(GuestProcessStreamBlock &streamBlock); 117 118 public: 119 120 static void FreeBlock(GuestProcessStreamBlock *pStreamBlock); 112 121 113 122 protected: -
trunk/src/VBox/Main/include/GuestImpl.h
r38290 r38395 27 27 #include "HGCM.h" 28 28 #ifdef VBOX_WITH_GUEST_CONTROL 29 # include <iprt/fs.h> 29 30 # include <VBox/HostServices/GuestControlSvc.h> 30 31 using namespace guestControl; … … 103 104 STDMETHOD(DirectoryClose)(ULONG aHandle); 104 105 STDMETHOD(DirectoryCreate)(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, ULONG aMode, ULONG aFlags); 106 STDMETHOD(DirectoryExists)(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists); 105 107 STDMETHOD(DirectoryOpen)(IN_BSTR aDirectory, IN_BSTR aFilter, 106 108 ULONG aFlags, IN_BSTR aUsername, IN_BSTR aPassword, ULONG *aHandle); … … 131 133 132 134 # ifdef VBOX_WITH_GUEST_CONTROL 135 // Internal guest directory functions 136 int directoryCreateHandle(ULONG *puHandle, ULONG uPID, IN_BSTR aDirectory, IN_BSTR aFilter, ULONG uFlags); 133 137 HRESULT directoryCreateInternal(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, 134 138 ULONG aMode, ULONG aFlags, int *pRC); 139 void directoryDestroyHandle(uint32_t uHandle); 140 HRESULT directoryExistsInternal(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists); 141 uint32_t directoryGetPID(uint32_t uHandle); 142 int directoryGetNextEntry(uint32_t uHandle, GuestProcessStreamBlock &streamBlock); 143 bool directoryHandleExists(uint32_t uHandle); 135 144 HRESULT directoryOpenInternal(IN_BSTR aDirectory, IN_BSTR aFilter, 136 145 ULONG aFlags, 137 146 IN_BSTR aUsername, IN_BSTR aPassword, 138 147 ULONG *aHandle, int *pRC); 148 HRESULT directoryQueryInfoInternal(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, PRTFSOBJINFO aObjInfo, RTFSOBJATTRADD enmAddAttribs, int *pRC); 149 // Internal guest execution functions 139 150 HRESULT executeAndWaitForTool(IN_BSTR aTool, IN_BSTR aDescription, 140 151 ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment), … … 146 157 ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress, int *pRC); 147 158 HRESULT executeProcessResult(const char *pszCommand, const char *pszUser, ULONG ulTimeout, PCALLBACKDATAEXECSTATUS pExecStatus, ULONG *puPID); 148 HRESULT executeStreamCollectBlock(ULONG aPID, 149 GuestProcessStream &stream, GuestProcessStreamBlock &streamBlock); 150 HRESULT executeStreamCollectOutput(ULONG aPID, GuestCtrlStreamObjects &streamObjects); 159 HRESULT executeStreamQueryFsObjInfo(IN_BSTR aObjName,GuestProcessStreamBlock *pStreamBlock, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttribs); 160 int executeStreamDrain(ULONG aPID, GuestProcessStream &stream); 161 void executeStreamFree(GuestCtrlStreamObjects &streamObjects); 162 void executeStreamFreeBlock(GuestProcessStreamBlock *pBlock); 163 int executeStreamGetNextBlock(ULONG aPID, GuestProcessStream &stream, GuestProcessStreamBlock &streamBlock); 164 HRESULT executeStreamParse(ULONG aPID, GuestCtrlStreamObjects &streamObjects); 151 165 HRESULT executeWaitForStatusChange(ULONG uPID, ULONG uTimeoutMS, ExecuteProcessStatus_T *pRetStatus, ULONG *puRetExitCode); 152 HRESULT fileExistsInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists, int *pRC); 153 HRESULT fileQuerySizeInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, LONG64 *aSize, int *pRC); 166 // Internal guest file functions 167 HRESULT fileExistsInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists); 168 HRESULT fileQueryInfoInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, PRTFSOBJINFO aObjInfo, RTFSOBJATTRADD enmAddAttribs, int *pRC); 169 HRESULT fileQuerySizeInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, LONG64 *aSize); 154 170 155 171 // Guest control dispatcher. … … 188 204 int callbackGetUserData(uint32_t uContextID, eVBoxGuestCtrlCallbackType *pEnmType, void **ppvData, size_t *pcbData); 189 205 void* callbackGetUserDataMutableRaw(uint32_t uContextID, size_t *pcbData); 206 int callbackInit(PVBOXGUESTCTRL_CALLBACK pCallback, eVBoxGuestCtrlCallbackType enmType, ComPtr<Progress> pProgress); 190 207 bool callbackIsCanceled(uint32_t uContextID); 191 208 bool callbackIsComplete(uint32_t uContextID); … … 219 236 typedef struct VBOXGUESTCTRL_DIRECTORY 220 237 { 221 char *mpszDirectory;222 char *mpszFilter;238 Bstr mDirectory; 239 Bstr mFilter; 223 240 ULONG mFlags; 224 241 /** Associated PID of started vbox_ls tool. */ 225 uint32_tmPID;242 ULONG mPID; 226 243 GuestProcessStream mStream; 227 244 #if 0 … … 237 254 typedef std::map< uint32_t, VBOXGUESTCTRL_DIRECTORY >::const_iterator GuestDirectoryMapIterConst; 238 255 239 int directoryCreateHandle(ULONG *puHandle, ULONG uPID, const char *pszDirectory, const char *pszFilter, ULONG uFlags);240 void directoryDestroyHandle(uint32_t uHandle);241 uint32_t directoryGetPID(uint32_t uHandle);242 int directoryGetNextEntry(uint32_t uHandle, GuestProcessStreamBlock &streamBlock);243 bool directoryHandleExists(uint32_t uHandle);244 245 256 // Utility functions. 246 257 int prepareExecuteEnv(const char *pszEnv, void **ppvList, uint32_t *pcbList, uint32_t *pcEnv); -
trunk/src/VBox/Main/src-client/GuestCtrlIO.cpp
r38269 r38395 35 35 } 36 36 37 /* 38 GuestProcessStreamBlock::GuestProcessStreamBlock(const GuestProcessStreamBlock &otherBlock) 39 { 40 for (GuestCtrlStreamPairsIter it = otherBlock.m_mapPairs.begin(); 41 it != otherBlock.end(); it++) 42 { 43 m_mapPairs[it->first] = new 44 if (it->second.pszValue) 45 { 46 RTMemFree(it->second.pszValue); 47 it->second.pszValue = NULL; 48 } 49 } 50 }*/ 51 37 52 GuestProcessStreamBlock::~GuestProcessStreamBlock() 38 53 { … … 41 56 42 57 /** 43 * Adds a key (if not existing yet).58 * Destroys the currently stored stream pairs. 44 59 * 45 60 * @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 61 */ 62 62 void GuestProcessStreamBlock::Clear() 63 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 64 m_mapPairs.clear(); 71 65 } … … 115 109 } 116 110 117 118 111 /** 119 112 * Returns a string value of a specified key. … … 130 123 GuestCtrlStreamPairsIterConst itPairs = m_mapPairs.find(Utf8Str(pszKey)); 131 124 if (itPairs != m_mapPairs.end()) 132 return itPairs->second. pszValue;125 return itPairs->second.mValue.c_str(); 133 126 } 134 127 catch (const std::exception &ex) … … 185 178 186 179 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 } 180 try 181 { 182 Utf8Str Utf8Key(pszKey); 183 184 /* Take a shortcut and prevent crashes on some funny versions 185 * of STL if map is empty initially. */ 186 if (!m_mapPairs.empty()) 187 { 188 GuestCtrlStreamPairsIter it = m_mapPairs.find(Utf8Key); 189 if (it != m_mapPairs.end()) 190 m_mapPairs.erase(it); 191 } 192 193 if (pszValue) 194 { 195 m_mapPairs.insert( 196 std::pair<Utf8Str, VBOXGUESTCTRL_STREAMPAIR>(Utf8Key, VBOXGUESTCTRL_STREAMPAIR(pszValue))); 197 } 198 } 199 catch (const std::exception &ex) 200 { 201 NOREF(ex); 207 202 } 208 203 return rc; … … 324 319 325 320 /** 326 * Try to parse the next upcoming pair block within the internal 327 * buffer. Old pairs from a previously parsed block will be removed first! 328 * 329 * @return IPRT status code. 321 * Tries to parse the next upcoming pair block within the internal 322 * buffer. 323 * 324 * Returns VERR_NO_DATA is no data is in internal buffer or buffer has been 325 * completely parsed already. 326 * 327 * Returns VERR_MORE_DATA if current block was parsed (with zero or more pairs 328 * stored in stream block) but still contains incomplete (unterminated) 329 * data. 330 * 331 * Returns VINF_SUCCESS if current block was parsed until the next upcoming 332 * block (with zero or more pairs stored in stream block). 333 * 334 * @return IPRT status code. 335 * @param streamBlock Reference to guest stream block to fill. 336 * 330 337 */ 331 338 int GuestProcessStream::ParseBlock(GuestProcessStreamBlock &streamBlock) 332 339 { 333 AssertPtrReturn(m_pbBuffer, VINF_SUCCESS); 334 AssertReturn(m_cbSize, VINF_SUCCESS); 340 if ( !m_pbBuffer 341 || !m_cbSize) 342 { 343 return VERR_NO_DATA; 344 } 345 335 346 AssertReturn(m_cbOffset <= m_cbSize, VERR_INVALID_PARAMETER); 347 if (m_cbOffset == m_cbSize) 348 return VERR_NO_DATA; 336 349 337 350 int rc = VINF_SUCCESS; 338 351 339 size_t uCur = m_cbOffset; 340 for (;uCur < m_cbSize;) 341 { 342 const char *pszStart = (char*)&m_pbBuffer[uCur]; 343 const char *pszEnd = pszStart; 344 345 /* Search end of current pair (key=value\0). */ 346 while (uCur++ < m_cbSize) 347 { 348 if (*pszEnd == '\0') 352 char *pszOff = (char*)&m_pbBuffer[m_cbOffset]; 353 char *pszStart = pszOff; 354 while (*pszStart) 355 { 356 size_t pairLen = strlen(pszStart); 357 if ((pszStart - pszOff) + pairLen + 1 >= m_cbSize) 358 { 359 rc = VERR_MORE_DATA; 360 break; 361 } 362 else 363 { 364 char *pszSep = strchr(pszStart, '='); 365 char *pszVal = NULL; 366 if (pszSep) 367 pszVal = pszSep + 1; 368 if (!pszSep || !pszVal) 369 { 370 rc = VERR_MORE_DATA; 349 371 break; 350 pszEnd++;351 }352 353 size_t uPairLen = pszEnd - pszStart;354 if (uPairLen)355 {356 const char *pszSep = pszStart;357 while ( *pszSep != '='358 && pszSep != pszEnd)359 {360 pszSep++;361 372 } 362 373 363 /* No separator found (or incomplete key=value pair)? */ 364 if ( pszSep == pszStart 365 || pszSep == pszEnd) 366 { 367 m_cbOffset = uCur - uPairLen - 1; 368 rc = VERR_MORE_DATA; 369 } 370 374 /* Terminate the separator so that we can 375 * use pszStart as our key from now on. */ 376 *pszSep = '\0'; 377 378 rc = streamBlock.SetValue(pszStart, pszVal); 371 379 if (RT_FAILURE(rc)) 372 break; 373 374 size_t uKeyLen = pszSep - pszStart; 375 size_t uValLen = pszEnd - (pszSep + 1); 376 377 /* Get key (if present). */ 378 if (uKeyLen) 379 { 380 Assert(pszSep > pszStart); 381 char *pszKey = (char*)RTMemAllocZ(uKeyLen + 1); 382 if (!pszKey) 383 { 384 rc = VERR_NO_MEMORY; 385 break; 386 } 387 memcpy(pszKey, pszStart, uKeyLen); 388 389 streamBlock.AddKey(pszKey); 390 391 /* Get value (if present). */ 392 if (uValLen) 393 { 394 Assert(pszEnd > pszSep); 395 char *pszVal = (char*)RTMemAllocZ(uValLen + 1); 396 if (!pszVal) 397 { 398 rc = VERR_NO_MEMORY; 399 break; 400 } 401 memcpy(pszVal, pszSep + 1, uValLen); 402 403 streamBlock.SetValue(pszKey, pszVal); 404 RTMemFree(pszVal); 405 } 406 407 RTMemFree(pszKey); 408 409 m_cbOffset += uCur - m_cbOffset; 410 } 411 } 412 else /* No pair detected, check for a new block. */ 413 { 414 do 415 { 416 if (*pszEnd == '\0') 417 { 418 m_cbOffset = uCur; 419 rc = VERR_MORE_DATA; 420 break; 421 } 422 pszEnd++; 423 } while (++uCur < m_cbSize); 424 } 425 426 if (RT_FAILURE(rc)) 427 break; 428 } 429 430 RT_CLAMP(m_cbOffset, 0, m_cbSize); 380 return rc; 381 } 382 383 /* Next pair. */ 384 pszStart += pairLen + 1; 385 } 386 387 /* If we did not do any movement but we have stuff left 388 * in our buffer just skip the current termination so that 389 * we can try next time. */ 390 uint32_t uDistance = (pszStart - pszOff); 391 if ( !uDistance 392 && *pszStart == '\0' 393 && m_cbOffset < m_cbSize) 394 { 395 uDistance++; 396 } 397 m_cbOffset += uDistance; 431 398 432 399 return rc; 433 400 } 434 401 402 void GuestProcessStream::FreeBlock(GuestProcessStreamBlock *pStreamBlock) 403 { 404 if (pStreamBlock) 405 { 406 pStreamBlock->Clear(); 407 delete pStreamBlock; 408 pStreamBlock = NULL; 409 } 410 } 411 -
trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp
r38294 r38395 108 108 * 109 109 * @return IPRT status code. 110 * @param pCallback 110 111 * @param puContextID 111 * @param pCallbackData112 112 */ 113 int Guest::callbackAdd(const PVBOXGUESTCTRL_CALLBACK pCallback Data, uint32_t *puContextID)114 { 115 AssertPtrReturn(pCallback Data, VERR_INVALID_PARAMETER);116 AssertPtrReturn(puContextID, VERR_INVALID_PARAMETER);113 int Guest::callbackAdd(const PVBOXGUESTCTRL_CALLBACK pCallback, uint32_t *puContextID) 114 { 115 AssertPtrReturn(pCallback, VERR_INVALID_PARAMETER); 116 /* puContextID is optional. */ 117 117 118 118 int rc; … … 142 142 143 143 /* Add callback with new context ID to our callback map. */ 144 mCallbackMap[uNewContextID] = *pCallback Data;144 mCallbackMap[uNewContextID] = *pCallback; 145 145 Assert(mCallbackMap.size()); 146 146 147 147 /* Report back new context ID. */ 148 *puContextID = uNewContextID; 148 if (puContextID) 149 *puContextID = uNewContextID; 149 150 } 150 151 … … 247 248 248 249 return NULL; 250 } 251 252 int Guest::callbackInit(PVBOXGUESTCTRL_CALLBACK pCallback, eVBoxGuestCtrlCallbackType enmType, 253 ComPtr<Progress> pProgress) 254 { 255 AssertPtrReturn(pCallback, VERR_INVALID_POINTER); 256 /* Everything else is optional. */ 257 258 int rc = VINF_SUCCESS; 259 switch (enmType) 260 { 261 case VBOXGUESTCTRLCALLBACKTYPE_EXEC_START: 262 { 263 PCALLBACKDATAEXECSTATUS pData = (PCALLBACKDATAEXECSTATUS)RTMemAlloc(sizeof(CALLBACKDATAEXECSTATUS)); 264 AssertPtrReturn(pData, VERR_NO_MEMORY); 265 RT_BZERO(pData, sizeof(CALLBACKDATAEXECSTATUS)); 266 pCallback->cbData = sizeof(CALLBACKDATAEXECSTATUS); 267 pCallback->pvData = pData; 268 break; 269 } 270 271 case VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT: 272 { 273 break; 274 } 275 276 case VBOXGUESTCTRLCALLBACKTYPE_EXEC_INPUT_STATUS: 277 { 278 279 break; 280 } 281 282 default: 283 rc = VERR_INVALID_PARAMETER; 284 break; 285 } 286 287 if (RT_SUCCESS(rc)) 288 { 289 /* Init/set common stuff. */ 290 pCallback->mType = enmType; 291 pCallback->pProgress = pProgress; 292 } 293 294 return rc; 249 295 } 250 296 … … 475 521 } 476 522 523 /** 524 * Waits for a callback (using its context ID) to complete. 525 * 526 * @return IPRT status code. 527 * @param uContextID Context ID to wait for. 528 * @param lStage Stage to wait for. Specify -1 if no staging is present/required. 529 * Specifying a stage is only needed if there's a multi operation progress 530 * object to wait for. 531 * @param lTimeout Timeout (in ms) to wait for. 532 */ 477 533 int Guest::callbackWaitForCompletion(uint32_t uContextID, LONG lStage, LONG lTimeout) 478 534 { … … 615 671 616 672 uint32_t uContextID = pData->hdr.u32ContextID; 673 Assert(uContextID); 617 674 618 675 /* Scope write locks as much as possible. */ … … 630 687 } 631 688 else 632 AssertReleaseMsgFailed(("Process status (PID=%u ) does not have allocated callback data!\n",633 pData->u32PID ));689 AssertReleaseMsgFailed(("Process status (PID=%u, CID=%u) does not have allocated callback data!\n", 690 pData->u32PID, uContextID)); 634 691 } 635 692 … … 813 870 } 814 871 else 815 AssertReleaseMsgFailed(("Process output status (PID=%u ) does not have allocated callback data!\n",816 pData->u32PID ));872 AssertReleaseMsgFailed(("Process output status (PID=%u, CID=%u) does not have allocated callback data!\n", 873 pData->u32PID, uContextID)); 817 874 } 818 875 … … 854 911 } 855 912 else 856 AssertReleaseMsgFailed(("Process input status (PID=%u ) does not have allocated callback data!\n",857 pData->u32PID ));913 AssertReleaseMsgFailed(("Process input status (PID=%u, CID=%u) does not have allocated callback data!\n", 914 pData->u32PID, uContextID)); 858 915 } 859 916 … … 1025 1082 ULONG uPID; 1026 1083 1027 HRESULT rc = this->ExecuteProcess(aTool,1028 1029 1030 1031 1032 1033 1084 HRESULT rc = ExecuteProcess(aTool, 1085 ExecuteProcessFlag_Hidden, 1086 ComSafeArrayInArg(aArguments), 1087 ComSafeArrayInArg(aEnvironment), 1088 aUsername, aPassword, 1089 5 * 1000 /* Wait 5s for getting the process started. */, 1090 &uPID, progressTool.asOutParam()); 1034 1091 if (SUCCEEDED(rc)) 1035 1092 { … … 1053 1110 if (SUCCEEDED(rc)) 1054 1111 { 1055 if ( !uRetExitCode)1112 if (uRetExitCode != 0) /* Not equal 0 means some error occured. */ 1056 1113 { 1114 /** @todo IPRT exit code to string! */ 1057 1115 rc = setError(VBOX_E_IPRT_ERROR, 1058 tr(" Error %u occurred while %s"),1059 uRetExitCode, Utf8Str(aDescription).c_str());1116 tr("%s: Error %u occured"), 1117 Utf8Str(aDescription).c_str(), uRetExitCode); 1060 1118 } 1061 else 1119 else /* Return code 0, success. */ 1062 1120 { 1063 1121 if (aProgress) … … 1078 1136 } 1079 1137 else 1080 AssertReleaseMsgFailed((" Operation \"%s\"neither completed nor canceled!?\n",1138 AssertReleaseMsgFailed(("%s: Operation neither completed nor canceled!?\n", 1081 1139 Utf8Str(aDescription).c_str())); 1082 1140 } … … 1171 1229 1172 1230 /** 1173 * Gets the next stream block from a formerly processed guest stream. Will return 1174 * E_UNEXPECTED if not enough guest stream data was read yet, otherwise S_OK or an appropriate 1175 * error. 1231 * TODO 1176 1232 * 1177 1233 * @return HRESULT 1178 * @param aPID PID of process to get the next stream block from. 1179 * @param stream Reference to an already filled guest process stream. 1180 * @param streamBlock Reference to a stream block which receives the parsed data. 1234 * @param aObjName 1235 * @param pStreamBlock 1236 * @param pObjInfo 1237 * @param enmAddAttribs 1181 1238 */ 1182 HRESULT Guest::executeStreamCollectBlock(ULONG aPID, 1183 GuestProcessStream &stream, GuestProcessStreamBlock &streamBlock) 1184 { 1239 HRESULT Guest::executeStreamQueryFsObjInfo(IN_BSTR aObjName, 1240 GuestProcessStreamBlock *pStreamBlock, 1241 PRTFSOBJINFO pObjInfo, 1242 RTFSOBJATTRADD enmAddAttribs) 1243 { 1244 AssertPtrReturn(pStreamBlock, E_INVALIDARG); 1245 1185 1246 HRESULT rc = S_OK; 1186 1187 SafeArray<BYTE> aOutputData; 1188 ULONG cbOutputData = 0; 1189 int vrc; 1247 Utf8Str Utf8ObjName(aObjName); 1248 1249 int64_t iVal; 1250 int vrc = pStreamBlock->GetInt64Ex("st_size", &iVal); 1251 if (RT_SUCCESS(vrc)) 1252 pObjInfo->cbObject = iVal; 1253 else 1254 rc = setError(VBOX_E_IPRT_ERROR, 1255 tr("Unable to retrieve size for \"%s\" (%Rrc)"), 1256 Utf8ObjName.c_str(), vrc); 1257 /** @todo Add more stuff! */ 1258 return rc; 1259 } 1260 1261 /** 1262 * Tries to drain the guest's output (from stdout) and fill it into 1263 * a guest process stream object for later usage. 1264 * 1265 * @return IPRT status code. 1266 * @param aPID PID of process to get the output from. 1267 * @param stream Reference to guest process stream to fill. 1268 */ 1269 int Guest::executeStreamDrain(ULONG aPID, GuestProcessStream &stream) 1270 { 1271 AssertReturn(aPID, VERR_INVALID_PARAMETER); 1272 1273 /** @todo Should we try to drain the stream harder? */ 1274 1275 int rc = VINF_SUCCESS; 1190 1276 for (;;) 1191 1277 { 1192 rc = this->GetProcessOutput(aPID, ProcessOutputFlag_None, 1193 10 * 1000 /* Timeout in ms */, 1194 _64K, ComSafeArrayAsOutParam(aOutputData)); 1195 if ( SUCCEEDED(rc) 1278 SafeArray<BYTE> aOutputData; 1279 HRESULT hr = GetProcessOutput(aPID, ProcessOutputFlag_None /* Stdout */, 1280 10 * 1000 /* Timeout in ms */, 1281 _64K, ComSafeArrayAsOutParam(aOutputData)); 1282 if ( SUCCEEDED(hr) 1196 1283 && aOutputData.size()) 1197 1284 { 1198 vrc = stream.AddData(aOutputData.raw(), aOutputData.size()); 1199 if (RT_UNLIKELY(RT_FAILURE(vrc))) 1200 { 1201 rc = setError(VBOX_E_IPRT_ERROR, 1202 tr("Error while adding guest output to stream buffer (%Rrc)"), vrc); 1285 rc = stream.AddData(aOutputData.raw(), aOutputData.size()); 1286 if (RT_UNLIKELY(RT_FAILURE(rc))) 1203 1287 break; 1204 } 1205 else 1206 { 1207 /* Try to parse the stream output we gathered until now. If we still need more 1208 * data the parsing routine will tell us and we just do another poll round. */ 1209 vrc = stream.ParseBlock(streamBlock); 1210 if (RT_SUCCESS(vrc)) 1211 { 1212 /* Yay, we're done! */ 1213 break; 1214 } 1215 else if (vrc == VERR_MORE_DATA) 1216 { 1217 /* We need another poll round. */ 1218 continue; 1219 } 1220 else 1221 rc = setError(VBOX_E_IPRT_ERROR, 1222 tr("Error while parsing guest output (%Rrc)"), vrc); 1223 } 1224 } 1225 else /* No more output! */ 1226 { 1227 if (vrc == VERR_MORE_DATA) 1228 rc = E_UNEXPECTED; /** @todo Find a better rc! */ 1288 } 1289 else /* No more output and/or error! */ 1229 1290 break; 1230 } 1231 } 1291 } 1292 1293 return rc; 1294 } 1295 1296 /** 1297 * Frees a guest stream objects vector. 1298 * 1299 * @param streamObjects Vector to free. 1300 */ 1301 void Guest::executeStreamFree(GuestCtrlStreamObjects &streamObjects) 1302 { 1303 for (GuestCtrlStreamObjectsIter it = streamObjects.begin(); 1304 it != streamObjects.end(); it++) 1305 { 1306 executeStreamFreeBlock(*it); 1307 } 1308 streamObjects.clear(); 1309 } 1310 1311 /** 1312 * Frees a guest stream block. Pure convenience function for 1313 * GuestProcessStream::FreeBlock(). 1314 * 1315 * @return IPRT status code. 1316 * @param pBlock 1317 */ 1318 void Guest::executeStreamFreeBlock(GuestProcessStreamBlock *pBlock) 1319 { 1320 GuestProcessStream::FreeBlock(pBlock); 1321 } 1322 1323 /** 1324 * Tries to get the next upcoming value block from a started guest process 1325 * by first draining its output and then processing the received guest stream. 1326 * 1327 * @return IPRT status code. 1328 * @param aPID PID of process to get/parse the output from. 1329 * @param stream Reference to process stream object to use. 1330 * @param streamBlock Reference that receives the next stream block data. 1331 * 1332 */ 1333 int Guest::executeStreamGetNextBlock(ULONG aPID, GuestProcessStream &stream, 1334 GuestProcessStreamBlock &streamBlock) 1335 { 1336 int rc = executeStreamDrain(aPID, stream); 1337 if (RT_SUCCESS(rc)) 1338 rc = stream.ParseBlock(streamBlock); 1232 1339 1233 1340 return rc; … … 1244 1351 * storing the parsed data. 1245 1352 */ 1246 HRESULT Guest::executeStreamCollectOutput(ULONG aPID, GuestCtrlStreamObjects &streamObjects) 1247 { 1248 HRESULT rc = S_OK; 1249 1250 SafeArray<BYTE> aOutputData; 1251 ULONG cbOutputData = 0; 1353 HRESULT Guest::executeStreamParse(ULONG aPID, GuestCtrlStreamObjects &streamObjects) 1354 { 1252 1355 GuestProcessStream guestStream; 1253 1254 for (;;) 1255 { 1256 rc = this->GetProcessOutput(aPID, ProcessOutputFlag_None, 1257 10 * 1000 /* Timeout in ms */, 1258 _64K, ComSafeArrayAsOutParam(aOutputData)); 1259 if ( SUCCEEDED(rc) 1260 && aOutputData.size()) 1261 { 1262 int vrc = guestStream.AddData(aOutputData.raw(), aOutputData.size()); 1263 if (RT_UNLIKELY(RT_FAILURE(vrc))) 1264 { 1265 rc = setError(VBOX_E_IPRT_ERROR, 1266 tr("Error while adding guest output to stream buffer (%Rrc)"), vrc); 1356 HRESULT hr = executeStreamDrain(aPID, guestStream); 1357 if (SUCCEEDED(hr)) 1358 { 1359 for (;;) 1360 { 1361 /* Try to parse the stream output we gathered until now. If we still need more 1362 * data the parsing routine will tell us and we just do another poll round. */ 1363 GuestProcessStreamBlock *pCurBlock = (GuestProcessStreamBlock*) 1364 RTMemAlloc(sizeof(GuestProcessStreamBlock)); 1365 if (!pCurBlock) 1366 { 1367 hr = setError(VBOX_E_IPRT_ERROR, 1368 tr("No memory for allocating stream block")); 1267 1369 break; 1268 1370 } 1269 } 1270 else /* No more output! */ 1271 break; 1272 } 1273 1274 if (SUCCEEDED(rc)) 1275 { 1276 for (;;) 1277 { 1278 GuestProcessStreamBlock curBlock; 1279 rc = executeStreamCollectBlock(aPID, 1280 guestStream, curBlock); 1281 if (SUCCEEDED(rc)) 1282 1283 { 1284 if (curBlock.GetCount()) 1285 streamObjects.push_back(curBlock); 1371 int vrc = guestStream.ParseBlock(*pCurBlock); 1372 if (RT_SUCCESS(vrc)) 1373 { 1374 if (pCurBlock->GetCount()) 1375 { 1376 streamObjects.push_back(pCurBlock); 1377 } 1286 1378 else 1379 { 1380 GuestProcessStream::FreeBlock(pCurBlock); 1287 1381 break; /* No more data. */ 1288 }1289 else1290 {1291 rc= setError(VBOX_E_IPRT_ERROR,1292 tr("Error while parsing guest stream block"));1293 break;1294 1295 } 1296 }1297 1298 return rc;1382 } 1383 } 1384 else /* Everything else would be an error! */ 1385 hr = setError(VBOX_E_IPRT_ERROR, 1386 tr("Error while parsing guest output (%Rrc)"), vrc); 1387 } 1388 } 1389 1390 /** @todo Add check if there now are any sream objects at all! */ 1391 1392 return hr; 1299 1393 } 1300 1394 … … 1471 1565 if (RT_SUCCESS(vrc)) 1472 1566 { 1473 /* Allocate payload. */1474 PCALLBACKDATAEXECSTATUS pStatus = (PCALLBACKDATAEXECSTATUS)RTMemAlloc(sizeof(CALLBACKDATAEXECSTATUS));1475 AssertReturn(pStatus, VBOX_E_IPRT_ERROR);1476 RT_ZERO(*pStatus);1477 1478 /* Create callback. */1479 1567 VBOXGUESTCTRL_CALLBACK callback; 1480 callback.mType = VBOXGUESTCTRLCALLBACKTYPE_EXEC_START; 1481 callback.cbData = sizeof(CALLBACKDATAEXECSTATUS); 1482 callback.pvData = pStatus; 1483 callback.pProgress = pProgress; 1484 1485 vrc = callbackAdd(&callback, &uContextID); 1568 vrc = callbackInit(&callback, VBOXGUESTCTRLCALLBACKTYPE_EXEC_START, pProgress); 1569 if (RT_SUCCESS(vrc)) 1570 { 1571 /* Allocate and assign payload. */ 1572 callback.cbData = sizeof(CALLBACKDATAEXECSTATUS); 1573 PCALLBACKDATAEXECSTATUS pData = (PCALLBACKDATAEXECSTATUS)RTMemAlloc(callback.cbData); 1574 AssertReturn(pData, E_OUTOFMEMORY); 1575 RT_BZERO(pData, callback.cbData); 1576 callback.pvData = pData; 1577 } 1578 1579 if (RT_SUCCESS(vrc)) 1580 vrc = callbackAdd(&callback, &uContextID); 1581 1486 1582 if (RT_SUCCESS(vrc)) 1487 1583 { … … 1669 1765 aTimeoutMS = UINT32_MAX; 1670 1766 1671 /* Construct callback data. */1672 1767 VBOXGUESTCTRL_CALLBACK callback; 1673 callback.mType = VBOXGUESTCTRLCALLBACKTYPE_EXEC_INPUT_STATUS; 1674 callback.cbData = sizeof(CALLBACKDATAEXECINSTATUS); 1675 1676 PCALLBACKDATAEXECINSTATUS pStatus = (PCALLBACKDATAEXECINSTATUS)RTMemAlloc(callback.cbData); 1677 AssertReturn(pStatus, VBOX_E_IPRT_ERROR); 1678 RT_ZERO(*pStatus); 1679 1680 /* Save PID + output flags for later use. */ 1681 pStatus->u32PID = aPID; 1682 pStatus->u32Flags = aFlags; 1683 1684 callback.pvData = pStatus; 1685 callback.pProgress = pProgress; 1686 1687 /* Add the callback. */ 1688 vrc = callbackAdd(&callback, &uContextID); 1768 vrc = callbackInit(&callback, VBOXGUESTCTRLCALLBACKTYPE_EXEC_INPUT_STATUS, pProgress); 1769 if (RT_SUCCESS(vrc)) 1770 { 1771 callback.cbData = sizeof(CALLBACKDATAEXECINSTATUS); 1772 PCALLBACKDATAEXECINSTATUS pData = (PCALLBACKDATAEXECINSTATUS)RTMemAlloc(callback.cbData); 1773 AssertReturn(pData, E_OUTOFMEMORY); 1774 RT_BZERO(pData, callback.cbData); 1775 callback.pvData = pData; 1776 1777 /* Save PID + output flags for later use. */ 1778 pData->u32PID = aPID; 1779 pData->u32Flags = aFlags; 1780 } 1781 1782 if (RT_SUCCESS(vrc)) 1783 vrc = callbackAdd(&callback, &uContextID); 1784 1689 1785 if (RT_SUCCESS(vrc)) 1690 1786 { … … 1825 1921 if (RT_FAILURE(vrc)) 1826 1922 rc = setError(VBOX_E_IPRT_ERROR, 1827 Guest::tr("Cannot get output from non-existent process (PID %u)"), aPID);1923 Guest::tr("Cannot get output from non-existent guest process (PID %u)"), aPID); 1828 1924 1829 1925 if (SUCCEEDED(rc)) … … 1842 1938 { 1843 1939 rc = pProgress->init(static_cast<IGuest*>(this), 1844 Bstr(tr(" Setting input forprocess")).raw(),1940 Bstr(tr("Getting output for guest process")).raw(), 1845 1941 TRUE /* Cancelable */); 1846 1942 } … … 1857 1953 uHandleID = OUTPUT_HANDLE_ID_STDERR; 1858 1954 1859 /* Construct callback data. */1860 1955 VBOXGUESTCTRL_CALLBACK callback; 1861 callback.mType = VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT; 1862 callback.cbData = sizeof(CALLBACKDATAEXECOUT); 1863 1864 PCALLBACKDATAEXECOUT pStatus = (PCALLBACKDATAEXECOUT)RTMemAlloc(callback.cbData); 1865 AssertReturn(pStatus, VBOX_E_IPRT_ERROR); 1866 RT_ZERO(*pStatus); 1867 1868 /* Save PID + output flags for later use. */ 1869 pStatus->u32PID = aPID; 1870 pStatus->u32Flags = aFlags; 1871 1872 callback.pvData = pStatus; 1873 callback.pProgress = pProgress; 1874 1875 /* Add the callback. */ 1876 vrc = callbackAdd(&callback, &uContextID); 1956 vrc = callbackInit(&callback, VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT, pProgress); 1957 if (RT_SUCCESS(vrc)) 1958 { 1959 callback.cbData = sizeof(CALLBACKDATAEXECOUT); 1960 PCALLBACKDATAEXECOUT pData = (PCALLBACKDATAEXECOUT)RTMemAlloc(callback.cbData); 1961 AssertReturn(pData, E_OUTOFMEMORY); 1962 RT_BZERO(pData, callback.cbData); 1963 callback.pvData = pData; 1964 1965 /* Save PID + output flags for later use. */ 1966 pData->u32PID = aPID; 1967 pData->u32Flags = aFlags; 1968 } 1969 1970 if (RT_SUCCESS(vrc)) 1971 vrc = callbackAdd(&callback, &uContextID); 1972 1877 1973 if (RT_SUCCESS(vrc)) 1878 1974 { … … 1916 2012 PCALLBACKDATAEXECOUT pExecOut = NULL; 1917 2013 1918 1919 * Wait for the first stage (=0) to complete (that is starting the process).2014 /* 2015 * Wait for the first output callback notification to arrive. 1920 2016 */ 1921 vrc = callbackWaitForCompletion(uContextID, 0 /* Stage*/, aTimeoutMS);2017 vrc = callbackWaitForCompletion(uContextID, -1 /* No staging */, aTimeoutMS); 1922 2018 if (RT_SUCCESS(vrc)) 1923 2019 { … … 1961 2057 rc = handleErrorHGCM(vrc); 1962 2058 1963 if (SUCCEEDED(rc))1964 {1965 1966 }1967 1968 2059 /* The callback isn't needed anymore -- just was kept locally. */ 1969 2060 callbackDestroy(uContextID); -
trunk/src/VBox/Main/src-client/GuestCtrlImplDir.cpp
r38290 r38395 138 138 * 139 139 * @return IPRT status code. 140 * @param puHandle Pointer where the handle gets stored to. 140 * @param puHandle Pointer where the handle gets stored to. Optional. 141 141 * @param uPID PID of guest process running the associated "vbox_ls". 142 * @param pszDirectoryDirectory the handle is assigned to.143 * @param pszFilterDirectory filter. Optional.142 * @param aDirectory Directory the handle is assigned to. 143 * @param aFilter Directory filter. Optional. 144 144 * @param uFlags Directory open flags. 145 145 * 146 146 */ 147 147 int Guest::directoryCreateHandle(ULONG *puHandle, ULONG uPID, 148 const char *pszDirectory, const char *pszFilter, ULONG uFlags) 149 { 150 AssertPtrReturn(puHandle, VERR_INVALID_POINTER); 151 AssertPtrReturn(pszDirectory, VERR_INVALID_POINTER); 152 /* pszFilter is optional. */ 148 IN_BSTR aDirectory, IN_BSTR aFilter, ULONG uFlags) 149 { 150 AssertReturn(uPID, VERR_INVALID_PARAMETER); 151 CheckComArgStrNotEmptyOrNull(aDirectory); 152 /* aFilter is optional. */ 153 /* uFlags are optional. */ 153 154 154 155 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); … … 160 161 uint32_t uHandleTry = ASMAtomicIncU32(&mNextDirectoryID); 161 162 GuestDirectoryMapIter it = mGuestDirectoryMap.find(uHandleTry); 162 if (it == mGuestDirectoryMap.end()) 163 { 163 if (it == mGuestDirectoryMap.end()) /* We found a free slot ... */ 164 { 165 mGuestDirectoryMap[uHandleTry].mDirectory = aDirectory; 166 mGuestDirectoryMap[uHandleTry].mFilter = aFilter; 167 mGuestDirectoryMap[uHandleTry].mPID = uPID; 168 mGuestDirectoryMap[uHandleTry].mFlags = uFlags; 169 Assert(mGuestDirectoryMap.size()); 170 164 171 rc = VINF_SUCCESS; 165 if (!RTStrAPrintf(&mGuestDirectoryMap[uHandleTry].mpszDirectory, pszDirectory)) 166 rc = VERR_NO_MEMORY; 167 else 168 { 169 /* Filter is optional. */ 170 if (pszFilter) 171 { 172 if (!RTStrAPrintf(&mGuestDirectoryMap[uHandleTry].mpszFilter, pszFilter)) 173 rc = VERR_NO_MEMORY; 174 } 175 176 if (RT_SUCCESS(rc)) 177 { 178 mGuestDirectoryMap[uHandleTry].mPID = uPID; 179 mGuestDirectoryMap[uHandleTry].mFlags = uFlags; 180 *puHandle = uHandleTry; 181 182 break; 183 } 184 } 185 186 if (RT_FAILURE(rc)) 187 break; 188 189 Assert(mGuestDirectoryMap.size()); 172 173 if (puHandle) 174 *puHandle = uHandleTry; 175 break; 190 176 } 191 177 } … … 208 194 if (it != mGuestDirectoryMap.end()) 209 195 { 210 RTStrFree(it->second.mpszDirectory);211 RTStrFree(it->second.mpszFilter);212 213 196 /* Destroy raw guest stream buffer - not used 214 197 * anymore. */ … … 220 203 } 221 204 205 STDMETHODIMP Guest::DirectoryExists(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists) 206 { 207 #ifndef VBOX_WITH_GUEST_CONTROL 208 ReturnComNotImplemented(); 209 #else /* VBOX_WITH_GUEST_CONTROL */ 210 using namespace guestControl; 211 212 CheckComArgStrNotEmptyOrNull(aDirectory); 213 214 /* Do not allow anonymous executions (with system rights). */ 215 if (RT_UNLIKELY((aUsername) == NULL || *(aUsername) == '\0')) 216 return setError(E_INVALIDARG, tr("No user name specified")); 217 218 return directoryExistsInternal(aDirectory, 219 aUsername, aPassword, aExists); 220 #endif 221 } 222 223 #ifdef VBOX_WITH_GUEST_CONTROL 224 HRESULT Guest::directoryExistsInternal(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists) 225 { 226 using namespace guestControl; 227 228 CheckComArgStrNotEmptyOrNull(aDirectory); 229 230 AutoCaller autoCaller(this); 231 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 232 233 RTFSOBJINFO objInfo; 234 int rc; 235 HRESULT hr = directoryQueryInfoInternal(aDirectory, 236 aUsername, aPassword, 237 &objInfo, RTFSOBJATTRADD_NOTHING, &rc); 238 if (SUCCEEDED(hr)) 239 { 240 switch (rc) 241 { 242 case VINF_SUCCESS: 243 *aExists = TRUE; 244 break; 245 246 case VERR_FILE_NOT_FOUND: 247 *aExists = FALSE; 248 break; 249 250 case VERR_NOT_FOUND: 251 rc = setError(VBOX_E_IPRT_ERROR, 252 Guest::tr("Unable to query directory existence")); 253 break; 254 255 default: 256 AssertReleaseMsgFailed(("directoryExistsInternal: Unknown return value (%Rrc)\n", rc)); 257 break; 258 } 259 } 260 return hr; 261 } 262 #endif 263 222 264 /** 223 265 * Gets the associated PID from a directory handle. 224 266 * 225 * @return uint32_t Associated PID, 0 if handle not found/invalid.226 * @param uHandle Directory handle to get PID for.267 * @return uint32_t Associated PID, 0 if handle not found/invalid. 268 * @param uHandle Directory handle to get PID for. 227 269 */ 228 270 uint32_t Guest::directoryGetPID(uint32_t uHandle) … … 237 279 } 238 280 281 /** 282 * Returns the next directory entry of an open guest directory. 283 * Returns VERR_NO_MORE_FILES if no more entries available. 284 * 285 * @return IPRT status code. 286 * @param uHandle Directory handle to get entry for. 287 * @param streamBlock Reference that receives the next stream block data. 288 */ 239 289 int Guest::directoryGetNextEntry(uint32_t uHandle, GuestProcessStreamBlock &streamBlock) 240 290 { 241 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 291 // LOCK DOES NOT WORK HERE!? 292 //AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 242 293 243 294 GuestDirectoryMapIter it = mGuestDirectoryMap.find(uHandle); 244 295 if (it != mGuestDirectoryMap.end()) 245 296 { 246 HRESULT hr = executeStreamCollectBlock(it->second.mPID, 247 it->second.mStream, streamBlock); 248 if (FAILED(hr)) 249 return VERR_INVALID_PARAMETER; /** @todo Find better rc! */ 250 251 return VINF_SUCCESS; 297 return executeStreamGetNextBlock(it->second.mPID, 298 it->second.mStream, streamBlock); 252 299 } 253 300 … … 259 306 * or not. 260 307 * 261 * @return bool True if handle exists, false if not.262 * @param uHandle Directory handle to check.308 * @return bool True if handle exists, false if not. 309 * @param uHandle Directory handle to check. 263 310 */ 264 311 bool Guest::directoryHandleExists(uint32_t uHandle) … … 315 362 return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags); 316 363 317 HRESULT rc= S_OK;364 HRESULT hr = S_OK; 318 365 try 319 366 { … … 354 401 355 402 ULONG uPID; 356 rc = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_LS).raw(), Bstr("Opening directory").raw(), 403 /** @todo Don't wait for tool to finish! Might take a lot of time! */ 404 hr = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_LS).raw(), Bstr("Opening directory").raw(), 357 405 ComSafeArrayAsInParam(args), 358 406 ComSafeArrayAsInParam(env), 359 407 aUsername, aPassword, 360 408 NULL /* Progress */, &uPID); 361 if (SUCCEEDED( rc))409 if (SUCCEEDED(hr)) 362 410 { 363 411 /* Assign new directory handle ID. */ 364 int vrc = directoryCreateHandle(aHandle, uPID, 365 Utf8Directory.c_str(), 366 Utf8Filter.isEmpty() ? NULL : Utf8Filter.c_str(), 367 aFlags); 368 if (RT_FAILURE(vrc)) 369 rc = setError(VBOX_E_IPRT_ERROR, 412 ULONG uHandleNew; 413 int vrc = directoryCreateHandle(&uHandleNew, uPID, 414 aDirectory, aFilter, aFlags); 415 if (RT_SUCCESS(vrc)) 416 { 417 *aHandle = uHandleNew; 418 } 419 else 420 hr = setError(VBOX_E_IPRT_ERROR, 370 421 tr("Unable to create guest directory handle (%Rrc)"), vrc); 371 422 } … … 373 424 catch (std::bad_alloc &) 374 425 { 375 rc = E_OUTOFMEMORY; 376 } 377 return rc; 426 hr = E_OUTOFMEMORY; 427 } 428 return hr; 429 } 430 431 HRESULT Guest::directoryQueryInfoInternal(IN_BSTR aDirectory, 432 IN_BSTR aUsername, IN_BSTR aPassword, 433 PRTFSOBJINFO aObjInfo, RTFSOBJATTRADD enmAddAttribs, 434 int *pRC) 435 { 436 using namespace guestControl; 437 438 /** @todo Search directory cache first? */ 439 440 CheckComArgStrNotEmptyOrNull(aDirectory); 441 /* aUsername is optional. */ 442 /* aPassword is optional. */ 443 /* aObjInfo is optional. */ 444 445 AutoCaller autoCaller(this); 446 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 447 448 HRESULT hr = S_OK; 449 try 450 { 451 Utf8Str Utf8Dir(aDirectory); 452 Utf8Str Utf8Username(aUsername); 453 Utf8Str Utf8Password(aPassword); 454 455 com::SafeArray<IN_BSTR> args; 456 com::SafeArray<IN_BSTR> env; 457 458 /* 459 * Prepare tool command line. 460 */ 461 462 /* We need to get output which is machine-readable in form 463 * of "key=value\0..key=value\0\0". */ 464 args.push_back(Bstr("--machinereadable").raw()); 465 466 /* Only the actual file name to chekc is needed for now. */ 467 args.push_back(Bstr(Utf8Dir).raw()); 468 469 /* 470 * Execute guest process. 471 */ 472 ULONG uPID; 473 hr = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_STAT).raw(), Bstr("Querying directory information").raw(), 474 ComSafeArrayAsInParam(args), 475 ComSafeArrayAsInParam(env), 476 aUsername, aPassword, 477 NULL /* Progress */, &uPID); 478 if (SUCCEEDED(hr)) 479 { 480 GuestCtrlStreamObjects streamObjs; 481 hr = executeStreamParse(uPID, streamObjs); 482 if (SUCCEEDED(hr)) 483 { 484 int rc = VINF_SUCCESS; 485 486 GuestProcessStreamBlock *pBlock = streamObjs[0]; 487 AssertPtr(pBlock); 488 const char *pszFsType = pBlock->GetString("ftype"); 489 if (!pszFsType) /* Attribute missing? */ 490 rc = VERR_NOT_FOUND; 491 if ( RT_SUCCESS(rc) 492 && strcmp(pszFsType, "d")) /* Directory? */ 493 { 494 rc = VERR_FILE_NOT_FOUND; 495 } 496 if ( RT_SUCCESS(rc) 497 && aObjInfo) /* Do we want object details? */ 498 { 499 hr = executeStreamQueryFsObjInfo(aDirectory, pBlock, 500 aObjInfo, enmAddAttribs); 501 } 502 503 executeStreamFree(streamObjs); 504 505 if (pRC) 506 *pRC = rc; 507 } 508 } 509 } 510 catch (std::bad_alloc &) 511 { 512 hr = E_OUTOFMEMORY; 513 } 514 return hr; 378 515 } 379 516 #endif /* VBOX_WITH_GUEST_CONTROL */ … … 391 528 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 392 529 393 HRESULT rc= S_OK;530 HRESULT hr = S_OK; 394 531 try 395 532 { 396 533 GuestProcessStreamBlock streamBlock; 397 int vrc = directoryGetNextEntry(aHandle, streamBlock);398 if (RT_SUCCESS( vrc))534 int rc = directoryGetNextEntry(aHandle, streamBlock); 535 if (RT_SUCCESS(rc)) 399 536 { 400 537 ComObjPtr <GuestDirEntry> pDirEntry; 401 rc= pDirEntry.createObject();402 ComAssertComRC( rc);403 404 rc= pDirEntry->init(this, streamBlock);405 if (SUCCEEDED( rc))538 hr = pDirEntry.createObject(); 539 ComAssertComRC(hr); 540 541 hr = pDirEntry->init(this, streamBlock); 542 if (SUCCEEDED(hr)) 406 543 { 407 544 pDirEntry.queryInterfaceTo(aDirEntry); 408 545 } 409 546 else 410 rc= setError(VBOX_E_IPRT_ERROR,547 hr = setError(VBOX_E_IPRT_ERROR, 411 548 Guest::tr("Unable to init guest directory entry")); 412 549 } 550 else if (rc == VERR_NO_MORE_FILES) 551 { 552 /* No more directory entries to read. */ 553 hr = E_ABORT; /** @todo Find/define a better rc! */ 554 } 413 555 else 414 rc= setError(VBOX_E_IPRT_ERROR,415 Guest::tr(" Directory handle is invalid"));556 hr = setError(VBOX_E_IPRT_ERROR, 557 Guest::tr("Failed getting next directory entry (%Rrc)"), rc); 416 558 } 417 559 catch (std::bad_alloc &) 418 560 { 419 rc= E_OUTOFMEMORY;420 } 421 return rc;422 #endif 423 } 424 561 hr = E_OUTOFMEMORY; 562 } 563 return hr; 564 #endif 565 } 566 -
trunk/src/VBox/Main/src-client/GuestCtrlImplFile.cpp
r38290 r38395 47 47 48 48 return fileExistsInternal(aFile, 49 aUsername, aPassword, aExists, 50 NULL /* rc */); 49 aUsername, aPassword, aExists); 51 50 #endif 52 51 } 53 52 54 53 #ifdef VBOX_WITH_GUEST_CONTROL 55 HRESULT Guest::fileExistsInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists , int *pRC)54 HRESULT Guest::fileExistsInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists) 56 55 { 57 56 using namespace guestControl; … … 62 61 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 63 62 64 HRESULT rc = S_OK; 63 RTFSOBJINFO objInfo; 64 int rc; 65 HRESULT hr = fileQueryInfoInternal(aFile, 66 aUsername, aPassword, 67 &objInfo, RTFSOBJATTRADD_NOTHING, &rc); 68 if (SUCCEEDED(hr)) 69 { 70 switch (rc) 71 { 72 case VINF_SUCCESS: 73 *aExists = TRUE; 74 break; 75 76 case VERR_FILE_NOT_FOUND: 77 *aExists = FALSE; 78 break; 79 80 case VERR_NOT_FOUND: 81 rc = setError(VBOX_E_IPRT_ERROR, 82 Guest::tr("Unable to query file existence")); 83 break; 84 85 default: 86 AssertReleaseMsgFailed(("fileExistsInternal: Unknown return value (%Rrc)\n", rc)); 87 break; 88 } 89 } 90 return hr; 91 } 92 93 HRESULT Guest::fileQueryInfoInternal(IN_BSTR aFile, 94 IN_BSTR aUsername, IN_BSTR aPassword, 95 PRTFSOBJINFO aObjInfo, RTFSOBJATTRADD enmAddAttribs, 96 int *pRC) 97 { 98 using namespace guestControl; 99 100 /* aUsername is optional. */ 101 /* aPassword is optional. */ 102 /* aObjInfo is optional. */ 103 104 HRESULT hr; 65 105 try 66 106 { … … 86 126 * Execute guest process. 87 127 */ 88 rc = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_STAT).raw(), Bstr("Checking for file existence").raw(), 128 ULONG uPID; 129 hr = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_STAT).raw(), Bstr("Querying file information").raw(), 89 130 ComSafeArrayAsInParam(args), 90 131 ComSafeArrayAsInParam(env), 91 132 aUsername, aPassword, 92 NULL /* Progress */, NULL /* PID */); 93 94 /* If the call succeeded the file exists, otherwise it does not. */ 95 *aExists = SUCCEEDED(rc) ? TRUE : FALSE; 133 NULL /* Progress */, &uPID); 134 if (SUCCEEDED(hr)) 135 { 136 GuestCtrlStreamObjects streamObjs; 137 hr = executeStreamParse(uPID, streamObjs); 138 if (SUCCEEDED(hr)) 139 { 140 int rc = VINF_SUCCESS; 141 142 GuestProcessStreamBlock *pBlock = streamObjs[0]; 143 AssertPtr(pBlock); 144 const char *pszFsType = pBlock->GetString("ftype"); 145 if (!pszFsType) /* Attribute missing? */ 146 rc = VERR_NOT_FOUND; 147 if ( RT_SUCCESS(rc) 148 && strcmp(pszFsType, "-")) /* Regular file? */ 149 { 150 rc = VERR_FILE_NOT_FOUND; 151 } 152 if ( RT_SUCCESS(rc) 153 && aObjInfo) /* Do we want object details? */ 154 { 155 hr = executeStreamQueryFsObjInfo(aFile, pBlock, 156 aObjInfo, enmAddAttribs); 157 } 158 159 executeStreamFree(streamObjs); 160 161 if (pRC) 162 *pRC = rc; 163 } 164 } 96 165 } 97 166 catch (std::bad_alloc &) 98 167 { 99 rc = E_OUTOFMEMORY; 100 } 101 return rc; 168 hr = E_OUTOFMEMORY; 169 } 170 171 return hr; 102 172 } 103 173 #endif /* VBOX_WITH_GUEST_CONTROL */ … … 116 186 return setError(E_INVALIDARG, tr("No user name specified")); 117 187 118 return fileQuerySizeInternal(aFile,119 aUsername, aPassword, aSize,120 NULL /* rc */);121 #endif122 }123 124 #ifdef VBOX_WITH_GUEST_CONTROL125 HRESULT Guest::fileQuerySizeInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, LONG64 *aSize, int *pRC)126 {127 using namespace guestControl;128 129 CheckComArgStrNotEmptyOrNull(aFile);130 131 188 AutoCaller autoCaller(this); 132 189 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 133 190 134 HRESULT rc = S_OK; 135 try 136 { 137 Utf8Str Utf8File(aFile); 138 Utf8Str Utf8Username(aUsername); 139 Utf8Str Utf8Password(aPassword); 140 141 com::SafeArray<IN_BSTR> args; 142 com::SafeArray<IN_BSTR> env; 143 144 /* 145 * Prepare tool command line. 146 */ 147 148 /* We need to get output which is machine-readable in form 149 * of "key=value\0..key=value\0\0". */ 150 args.push_back(Bstr("--machinereadable").raw()); 151 152 /* Only the actual file name to chekc is needed for now. */ 153 args.push_back(Bstr(Utf8File).raw()); 154 155 /* 156 * Execute guest process. 157 */ 158 ComPtr<IProgress> progressFileSize; 159 ULONG uPID; 160 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); 166 if (SUCCEEDED(rc)) 191 return fileQuerySizeInternal(aFile, 192 aUsername, aPassword, aSize); 193 #endif 194 } 195 196 #ifdef VBOX_WITH_GUEST_CONTROL 197 HRESULT Guest::fileQuerySizeInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, LONG64 *aSize) 198 { 199 using namespace guestControl; 200 201 CheckComArgStrNotEmptyOrNull(aFile); 202 203 int rc; 204 RTFSOBJINFO objInfo; 205 HRESULT hr = fileQueryInfoInternal(aFile, 206 aUsername, aPassword, 207 &objInfo, RTFSOBJATTRADD_NOTHING, &rc); 208 if (SUCCEEDED(hr)) 209 { 210 switch (rc) 167 211 { 168 GuestCtrlStreamObjects streamObjs; 169 rc = executeStreamCollectOutput(uPID, streamObjs); 170 if (SUCCEEDED(rc)) 171 { 172 /** @todo */ 173 #if 0 174 int64_t iVal; 175 vrc = guestStream.GetInt64Ex("st_size", &iVal); 176 if (RT_SUCCESS(vrc)) 177 *aSize = iVal; 178 else 179 rc = setError(VBOX_E_IPRT_ERROR, 180 tr("Query file size: Unable to retrieve file size for file \"%s\" (%Rrc)"), 181 Utf8File.c_str(), vrc); 182 #endif 183 } 212 case VINF_SUCCESS: 213 *aSize = objInfo.cbObject; 214 break; 215 216 case VERR_FILE_NOT_FOUND: 217 rc = setError(VBOX_E_IPRT_ERROR, 218 Guest::tr("File not found")); 219 break; 220 221 case VERR_NOT_FOUND: 222 rc = setError(VBOX_E_IPRT_ERROR, 223 Guest::tr("Unable to query file size")); 224 break; 225 226 default: 227 AssertReleaseMsgFailed(("fileExistsInternal: Unknown return value (%Rrc)\n", rc)); 228 break; 184 229 } 185 230 } 186 catch (std::bad_alloc &)187 {188 rc = E_OUTOFMEMORY;189 }190 231 return rc; 191 232 } -
trunk/src/VBox/Main/src-client/GuestDirEntryImpl.cpp
r38296 r38395 59 59 60 60 mData.mNodeId = streamBlock.GetInt64("node_id"); 61 mData.mName = BstrFmt("%s", streamBlock.GetString("name")); 61 const char *pszName = streamBlock.GetString("name"); 62 if (pszName) 63 mData.mName = BstrFmt("%s", pszName); 62 64 mData.mType = GuestDirEntry::fileTypeToEntryType(streamBlock.GetString("ftype")); 63 65 -
trunk/src/VBox/Main/testcase/tstGuestCtrlParseBuffer.cpp
r38269 r38395 58 58 } aTests[] = 59 59 { 60 /* 61 * Single object parsing. 62 * An object is represented by one or multiple key=value pairs which are 63 * separated by a single "\0". If this termination is missing it will be assumed 64 * that we need to collect more data to do a successful parsing. 65 */ 66 60 67 /* Invalid stuff. */ 61 68 { NULL, 0, 0, 0, 0, VERR_INVALID_POINTER }, … … 66 73 { "foo=bar2", 0, 50, 50, 0, VERR_INVALID_PARAMETER }, 67 74 /* Empty buffers. */ 68 { "", 1, 0, 1, 0, VERR_MORE_DATA }, 69 { "\0", 1, 0, 1, 0, VERR_MORE_DATA }, 70 /* Incomplete buffer (missing components). */ 71 { szUnterm1, 5, 0, 0, 0, VERR_MORE_DATA }, 72 { "foo1", sizeof("foo1"), 0, 0, 0, VERR_MORE_DATA }, 73 { "=bar\0", sizeof("=bar"), 0, 0, 0, VERR_MORE_DATA }, 74 /* Last sequence is incomplete -- new offset should point to it. */ 75 { "hug=sub\0incomplete", sizeof("hug=sub\0incomplete"), 0, sizeof("hug=sub"), 1, VERR_MORE_DATA }, 76 { "boo=hoo\0baz=boo\0qwer", sizeof("boo=hoo\0baz=boo\0qwer"), 0, sizeof("boo=hoo\0baz=boo"), 2, VERR_MORE_DATA }, 77 /* Parsing good stuff. */ 78 { "novalue=", sizeof("novalue="), 0, sizeof("novalue="), 1, VINF_SUCCESS }, 79 { szUnterm2, 8, 0, sizeof(szUnterm2), 1, VINF_SUCCESS }, 80 { "foo2=", sizeof("foo2="), 0, sizeof("foo2="), 1, VINF_SUCCESS }, 81 { "har=hor", sizeof("har=hor"), 0, sizeof("har=hor"), 1, VINF_SUCCESS }, 82 { "foo=bar\0baz=boo", sizeof("foo=bar\0baz=boo"), 0, sizeof("foo=bar\0baz=boo"), 2, VINF_SUCCESS }, 83 /* Parsing until a different block (two terminations, returning offset to next block). */ 84 { "off=rab\0a=b\0\0\0\0", sizeof("off=rab\0a=b\0\0\0"), 0, 13, 2, VERR_MORE_DATA }, 85 { "off=rab\0\0zab=oob", sizeof("off=rab\0\0zab=oob"), 0, 9, 1, VERR_MORE_DATA }, 86 { "\0\0\0\0off=rab\0zab=oob\0\0", sizeof("\0\0\0\0off=rab\0zab=oob\0\0"), 0, 1, 0, VERR_MORE_DATA }, 87 { "o2=r2\0z3=o3\0\0f3=g3", sizeof("o2=r2\0z3=o3\0\0f3=g3"), 0, 13, 2, VERR_MORE_DATA } 75 { "", 1, 0, 1, 0, VINF_SUCCESS }, 76 { "\0", 1, 0, 1, 0, VINF_SUCCESS }, 77 /* Unterminated values (missing "\0"). */ 78 { "test1", sizeof("test1"), 0, 0, 0, VERR_MORE_DATA }, 79 { "test2=", sizeof("test2="), 0, 0, 0, VERR_MORE_DATA }, 80 { "test3=test3", sizeof("test3=test3"), 0, 0, 0, VERR_MORE_DATA }, 81 { "test4=test4\0t41", sizeof("test4=test4\0t41"), 0, sizeof("test4=test4\0") - 1, 1, VERR_MORE_DATA }, 82 { "test5=test5\0t51=t51", sizeof("test5=test5\0t51=t51"), 0, sizeof("test5=test5\0") - 1, 1, VERR_MORE_DATA }, 83 /* Next block unterminated. */ 84 { "t51=t51\0t52=t52\0\0t53=t53", sizeof("t51=t51\0t52=t52\0\0t53=t53"), 0, sizeof("t51=t51\0t52=t52\0") - 1, 2, VINF_SUCCESS }, 85 { "test6=test6\0\0t61=t61", sizeof("test6=test6\0\0t61=t61"), 0, sizeof("test6=test6\0") - 1, 1, VINF_SUCCESS }, 86 /* Good stuff. */ 87 { "test61=\0test611=test611\0", sizeof("test61=\0test611=test611\0"), 0, sizeof("test61=\0test611=test611\0") - 1, 2, VINF_SUCCESS }, 88 { "test7=test7\0\0", sizeof("test7=test7\0\0"), 0, sizeof("test7=test7\0") - 1, 1, VINF_SUCCESS }, 89 { "test8=test8\0t81=t81\0\0", sizeof("test8=test8\0t81=t81\0\0"), 0, sizeof("test8=test8\0t81=t81\0") - 1, 2, VINF_SUCCESS }, 90 /* Good stuff, but with a second block -- should be *not* taken into account since 91 * we're only interested in parsing/handling the first object. */ 92 { "t9=t9\0t91=t91\0\0t92=t92\0\0", sizeof("t9=t9\0t91=t91\0\0t92=t92\0\0"), 0, sizeof("t9=t9\0t91=t91\0") - 1, 2, VINF_SUCCESS } 88 93 }; 89 94 … … 98 103 } aTests2[] = 99 104 { 100 { "\0\0\0\0", sizeof("\0\0\0\0"), 0, VINF_SUCCESS }, 101 { "off=rab\0\0zab=oob", sizeof("off=rab\0\0zab=oob"), 2, VINF_SUCCESS }, 102 { "\0\0\0soo=foo\0goo=loo\0\0zab=oob", sizeof("\0\0\0soo=foo\0goo=loo\0\0zab=oob"), 2, VINF_SUCCESS }, 103 { "qoo=uoo\0\0\0\0asdf=\0\0", sizeof("qoo=uoo\0\0\0\0asdf=\0\0"), 2, VINF_SUCCESS }, 104 { "foo=bar\0\0\0\0\0\0", sizeof("foo=bar\0\0\0\0\0\0"), 1, VINF_SUCCESS }, 105 { "qwer=cvbnr\0\0\0gui=uig\0\0\0", sizeof("qwer=cvbnr\0\0\0gui=uig\0\0\0"), 2, VINF_SUCCESS } 105 /* No blocks. */ 106 { "\0\0\0\0", sizeof("\0\0\0\0"), 0, VERR_NO_DATA }, 107 /* Good stuff. */ 108 { "\0b1=b1\0\0", sizeof("\0b1=b1\0\0"), 1, VERR_NO_DATA }, 109 { "b1=b1\0\0", sizeof("b1=b1\0\0"), 1, VERR_NO_DATA }, 110 { "b1=b1\0b2=b2\0\0", sizeof("b1=b1\0b2=b2\0\0"), 1, VERR_NO_DATA }, 111 { "b1=b1\0b2=b2\0\0\0", sizeof("b1=b1\0b2=b2\0\0\0"), 1, VERR_NO_DATA } 106 112 }; 107 113 … … 136 142 for (iTest; iTest < RT_ELEMENTS(aTests); iTest++) 137 143 { 138 uint32_t uOffset = aTests[iTest].uOffsetStart;139 140 144 RTTestIPrintf(RTTESTLVL_DEBUG, "=> Test #%u\n", iTest); 141 145 … … 144 148 if (RT_SUCCESS(iResult)) 145 149 { 146 GuestProcessStreamBlock block;147 iResult = stream.ParseBlock( block);150 GuestProcessStreamBlock curBlock; 151 iResult = stream.ParseBlock(curBlock); 148 152 if (iResult != aTests[iTest].iResult) 149 153 { … … 151 155 iResult, aTests[iTest].iResult); 152 156 } 153 else if (block.GetCount() != aTests[iTest].uMapElements)154 {155 RTTestFailed(hTest, "\tMap has %u elements, expected %u",156 block.GetCount(), aTests[iTest].uMapElements);157 }158 157 else if (stream.GetOffset() != aTests[iTest].uOffsetAfter) 159 158 { … … 163 162 else if (iResult == VERR_MORE_DATA) 164 163 { 165 RTTestIPrintf(RTTESTLVL_DEBUG, "\tMore data (Offset: %u)\n", uOffset); 166 167 /* There is remaining data left in the buffer (which needs to be merged 168 * with a following buffer) -- print it. */ 169 size_t uToWrite = aTests[iTest].cbData - uOffset; 170 if (uToWrite) 164 RTTestIPrintf(RTTESTLVL_DEBUG, "\tMore data (Offset: %u)\n", stream.GetOffset()); 165 } 166 167 if ( ( RT_SUCCESS(iResult) 168 || iResult == VERR_MORE_DATA)) 169 { 170 if (curBlock.GetCount() != aTests[iTest].uMapElements) 171 171 { 172 const char *pszRemaining = aTests[iTest].pbData; 173 RTTestIPrintf(RTTESTLVL_DEBUG, "\tRemaining (%u):\n", uToWrite); 174 RTStrmWriteEx(g_pStdOut, &aTests[iTest].pbData[uOffset], uToWrite - 1, NULL); 175 RTTestIPrintf(RTTESTLVL_DEBUG, "\n"); 172 RTTestFailed(hTest, "\tMap has %u elements, expected %u", 173 curBlock.GetCount(), aTests[iTest].uMapElements); 176 174 } 175 } 176 177 /* There is remaining data left in the buffer (which needs to be merged 178 * with a following buffer) -- print it. */ 179 uint32_t uOffset = stream.GetOffset(); 180 size_t uToWrite = aTests[iTest].cbData - uOffset; 181 if (uToWrite) 182 { 183 const char *pszRemaining = aTests[iTest].pbData; 184 RTTestIPrintf(RTTESTLVL_DEBUG, "\tRemaining (%u):\n", uToWrite); 185 RTStrmWriteEx(g_pStdOut, &aTests[iTest].pbData[uOffset], uToWrite - 1, NULL); 177 186 } 178 187 } … … 181 190 RTTestIPrintf(RTTESTLVL_INFO, "Doing block tests ...\n"); 182 191 183 for (unsigned iTest = 0; iTest < RT_ELEMENTS(aTests2); iTest++) 192 iTest = 0; 193 for (iTest; iTest < RT_ELEMENTS(aTests2); iTest++) 184 194 { 185 195 RTTestIPrintf(RTTESTLVL_DEBUG, "=> Block test #%u\n", iTest); … … 190 200 { 191 201 uint32_t uNumBlocks = 0; 192 202 uint8_t uSafeCouunter = 0; 193 203 do 194 204 { 195 GuestProcessStreamBlock block;196 iResult = stream.ParseBlock( block);205 GuestProcessStreamBlock curBlock; 206 iResult = stream.ParseBlock(curBlock); 197 207 RTTestIPrintf(RTTESTLVL_DEBUG, "\tReturned with %Rrc\n", iResult); 198 if ( iResult == VINF_SUCCESS 199 || iResult == VERR_MORE_DATA) 208 if (RT_SUCCESS(iResult)) 200 209 { 201 210 /* Only count block which have at least one pair. */ 202 if ( block.GetCount())211 if (curBlock.GetCount()) 203 212 uNumBlocks++; 204 213 } 205 if (uNumBlocks > 32) 206 break; /* Give up if unreasonable big. */ 207 block.Clear(); 208 } while (iResult == VERR_MORE_DATA); 214 if (uSafeCouunter++ > 32) 215 break; 216 } while (RT_SUCCESS(iResult)); 209 217 210 218 if (iResult != aTests2[iTest].iResult)
Note:
See TracChangeset
for help on using the changeset viewer.