Changeset 75824 in vbox
- Timestamp:
- Nov 29, 2018 10:12:53 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/GuestHost/GuestControl.h
r71517 r75824 2 2 /** @file 3 3 * Guest Control - Common Guest and Host Code. 4 * 5 * @todo r=bird: Just merge this with GuestControlSvc.h! 4 6 */ 5 7 … … 124 126 #define PATHRENAME_FLAG_NO_SYMLINKS RT_BIT(1) 125 127 /** Mask of valid flags. */ 126 #define PATHRENAME_FLAG_VALID_MASK UINT32_C(0x0000000 2)128 #define PATHRENAME_FLAG_VALID_MASK UINT32_C(0x00000003) 127 129 /** @} */ 128 130 -
trunk/include/VBox/HostServices/GuestControlSvc.h
r75801 r75824 153 153 * Gets the current status of a running process, e.g. 154 154 * new data on stdout/stderr, process terminated etc. 155 * * Note:Legacy (VBox < 4.3) command.155 * @note Legacy (VBox < 4.3) command. 156 156 */ 157 157 HOST_EXEC_GET_OUTPUT = 102, … … 371 371 /** Skip message. 372 372 * 373 * This skips the current message, replying to the sender with 374 * VERR_NOT_SUPPORTED if appropriate. No parameters. 373 * This skips the current message, replying to the main backend as best it can. 374 * Takes between zero and two parameters. The first parameter is the 32-bit 375 * VBox status code to pass onto Main when skipping the command, defaults to 376 * VERR_NOT_SUPPORTED. The second parameter is the 32-bit message ID of the 377 * command to skip, by default whatever is first in the queue is removed. This 378 * is also the case if UINT32_MAX is specified. 375 379 * 376 380 * @retval VINF_SUCCESS on success. 377 381 * @retval VERR_NOT_FOUND if no message pending. 382 * @retval VERR_MISMATCH if the specified message ID didn't match. 378 383 * @retval VERR_INVALID_CLIENT_ID 379 384 * @retval VERR_WRONG_PARAMETER_COUNT … … 615 620 616 621 /** 617 * Guest file seeking types. Has to 618 * match FileSeekType in Main. 622 * Guest file seeking types. Has to match FileSeekType in Main. 623 * 624 * @note This is not compatible with RTFileSeek, which is an unncessary pain. 619 625 */ 620 626 enum GUEST_FILE_SEEKTYPE -
trunk/include/VBox/VBoxGuestLib.h
r75807 r75824 752 752 * Use a union for the HGCM stuff then. */ 753 753 754 /** IN: HGCM client ID to use for 755 * communication. */ 754 /** IN: HGCM client ID to use for communication. */ 756 755 uint32_t uClientID; 757 /** IN/OUT: Context ID to retrieve 758 * or to use. */ 756 /** IN/OUT: Context ID to retrieve or to use. */ 759 757 uint32_t uContextID; 760 758 /** IN: Protocol version to use. */ … … 773 771 VBGLR3DECL(int) VbglR3GuestCtrlMsgReplyEx(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, uint32_t uType, 774 772 void *pvPayload, uint32_t cbPayload); 775 VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t idClient );773 VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t idClient, int rcSkip, uint32_t idMsg); 776 774 VBGLR3DECL(int) VbglR3GuestCtrlMsgSkipOld(uint32_t uClientId); 777 775 VBGLR3DECL(int) VbglR3GuestCtrlMsgPeekWait(uint32_t idClient, uint32_t *pidMsg, uint32_t *pcParameters); -
trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibGuestCtrl.cpp
r75807 r75824 427 427 * @return IPRT status code. 428 428 * @param idClient The client ID returned by VbglR3GuestCtrlConnect(). 429 */ 430 VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t idClient) 429 * @param rcSkip The status code to pass back to Main when skipping. 430 * @param idMsg The message ID to skip, pass UINT32_MAX to pass any. 431 */ 432 VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t idClient, int rcSkip, uint32_t idMsg) 431 433 { 432 434 if (vbglR3GuestCtrlSupportsPeekGetCancel(idClient)) 433 435 { 434 VBGLIOCHGCMCALL Hdr; 435 VBGL_HGCM_HDR_INIT(&Hdr, idClient, GUEST_MSG_SKIP, 0); 436 return VbglR3HGCMCall(&Hdr, sizeof(Hdr)); 436 struct 437 { 438 VBGLIOCHGCMCALL Hdr; 439 HGCMFunctionParameter rcSkip; 440 HGCMFunctionParameter idMsg; 441 } Msg; 442 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_SKIP, 2); 443 VbglHGCMParmUInt32Set(&Msg.rcSkip, (uint32_t)rcSkip); 444 VbglHGCMParmUInt32Set(&Msg.idMsg, idMsg); 445 return VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg)); 437 446 } 438 447 … … 624 633 *pidSession = VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(pCtx->uContextID); 625 634 } 626 /* Try get the context ID so we can inform the host about this message retrival failure. */627 else if (Msg.context.u.value32 != HOST_SESSION_CREATE)628 Msg.context.GetUInt32(&pCtx->uContextID);629 635 630 636 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel); … … 666 672 667 673 /** 668 * Retrieves a HOST_ SESSION_CLOSE message.674 * Retrieves a HOST_PATH_RENAME message. 669 675 */ 670 676 VBGLR3DECL(int) VbglR3GuestCtrlPathGetRename(PVBGLR3GUESTCTRLCMDCTX pCtx, … … 698 704 Msg.flags.GetUInt32(pfFlags); 699 705 } 706 700 707 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel); 701 708 return rc; … … 913 920 } 914 921 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel); 915 return rc; 922 923 if ( rc != VERR_TOO_MUCH_DATA 924 || g_fVbglR3GuestCtrlHavePeekGetCancel) 925 return rc; 926 return VERR_BUFFER_OVERFLOW; 916 927 } 917 928 … … 1129 1140 } 1130 1141 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel); 1131 return rc; 1142 1143 if ( rc != VERR_TOO_MUCH_DATA 1144 || g_fVbglR3GuestCtrlHavePeekGetCancel) 1145 return rc; 1146 return VERR_BUFFER_OVERFLOW; 1132 1147 } 1133 1148 … … 1167 1182 } 1168 1183 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel); 1169 return rc; 1184 1185 if ( rc != VERR_TOO_MUCH_DATA 1186 || g_fVbglR3GuestCtrlHavePeekGetCancel) 1187 return rc; 1188 return VERR_BUFFER_OVERFLOW; 1170 1189 } 1171 1190 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp
r75807 r75824 306 306 if (VbglR3GuestCtrlSupportsOptimizations(g_idControlSvcClient)) 307 307 { 308 rc = VbglR3GuestCtrlMsgSkip(g_idControlSvcClient );308 rc = VbglR3GuestCtrlMsgSkip(g_idControlSvcClient, VERR_NOT_SUPPORTED, idMsg); 309 309 VGSvcVerbose(1, "Skipped unexpected message idMsg=%RU32 (%s), cParms=%RU32 (rc=%Rrc)\n", 310 310 idMsg, GstCtrlHostFnName((eHostFn)idMsg), cParms, rc); … … 421 421 } 422 422 } 423 /*424 * If we cannot retrieve the message, make sure to skip the command.425 *426 * Note! If we totally failed to get any valid context ID, the host will427 * not see the notification and be stuck till it times out.428 */429 423 else 430 424 { 431 VGSvcError("Error fetching guest session parameters: %Rrc\n", rc); 432 VbglR3GuestCtrlSessionNotify(pHostCtx, GUEST_SESSION_NOTIFYTYPE_ERROR, rc); 433 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID); 425 VGSvcError("Error fetching parameters for opening guest session: %Rrc\n", rc); 426 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 434 427 } 435 428 VGSvcVerbose(3, "Opening a new guest session returned rc=%Rrc\n", rc); … … 442 435 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 443 436 444 uint32_t uSessionID;437 uint32_t idSession; 445 438 uint32_t fFlags; 446 int rc = VbglR3GuestCtrlSessionGetClose(pHostCtx, &fFlags, & uSessionID);439 int rc = VbglR3GuestCtrlSessionGetClose(pHostCtx, &fFlags, &idSession); 447 440 if (RT_SUCCESS(rc)) 448 441 { … … 452 445 RTListForEach(&g_lstControlSessionThreads, pThread, VBOXSERVICECTRLSESSIONTHREAD, Node) 453 446 { 454 if (pThread->StartupInfo.uSessionID == uSessionID)447 if (pThread->StartupInfo.uSessionID == idSession) 455 448 { 456 449 rc = VGSvcGstCtrlSessionThreadDestroy(pThread, fFlags); … … 458 451 } 459 452 } 460 #if 0 453 454 #if 0 /** @todo A bit of a mess here as this message goes to both to this process (master) and the session process. */ 461 455 if (RT_FAILURE(rc)) 462 456 { … … 473 467 } 474 468 #endif 475 VGSvcVerbose(2, "Closing guest session %RU32 returned rc=%Rrc\n", uSessionID, rc);469 VGSvcVerbose(2, "Closing guest session %RU32 returned rc=%Rrc\n", idSession, rc); 476 470 } 477 471 else 478 VGSvcError("Closing guest session %RU32 failed with rc=%Rrc\n", uSessionID, rc); 472 { 473 VGSvcError("Error fetching parameters for closing guest session: %Rrc\n", rc); 474 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 475 } 479 476 return rc; 480 477 } -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp
r75807 r75824 62 62 63 63 64 /** 65 * Helper that grows the scratch buffer. 66 * @returns Success indicator. 67 */ 68 static bool vgsvcGstCtrlSessionGrowScratchBuf(void **ppvScratchBuf, uint32_t *pcbScratchBuf, uint32_t cbMinBuf) 69 { 70 uint32_t cbNew = *pcbScratchBuf * 2; 71 if ( cbNew <= VMMDEV_MAX_HGCM_DATA_SIZE 72 && cbMinBuf <= VMMDEV_MAX_HGCM_DATA_SIZE) 73 { 74 while (cbMinBuf > cbNew) 75 cbNew *= 2; 76 void *pvNew = RTMemRealloc(*ppvScratchBuf, cbNew); 77 if (pvNew) 78 { 79 *ppvScratchBuf = pvNew; 80 *pcbScratchBuf = cbNew; 81 return true; 82 } 83 } 84 return false; 85 } 86 87 64 88 65 89 static int vgsvcGstCtrlSessionFileDestroy(PVBOXSERVICECTRLFILE pFile) … … 102 126 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 103 127 104 char szDir[RTPATH_MAX];105 uint32_t fFlags = 0;106 107 int rc = VbglR3GuestCtrlDirGetRemove(pHostCtx,108 /* Directory to remove.*/109 szDir, sizeof(szDir),110 /* Flags of type DIRREMOVE_FLAG_. */111 &fFlags);112 if (RT_SUCCESS(rc))113 {114 AssertReturn(!(fFlags & ~DIRREMOVE_FLAG_VALID_MASK), VERR_INVALID_PARAMETER);128 /* 129 * Retrieve the message. 130 */ 131 char szDir[RTPATH_MAX]; 132 uint32_t fFlags; /* DIRREMOVE_FLAG_XXX */ 133 int rc = VbglR3GuestCtrlDirGetRemove(pHostCtx, szDir, sizeof(szDir), &fFlags); 134 if (RT_SUCCESS(rc)) 135 { 136 /* 137 * Do some validating before executing the job. 138 */ 115 139 if (!(fFlags & ~DIRREMOVE_FLAG_VALID_MASK)) 116 140 { … … 120 144 if (fFlags & DIRREMOVE_FLAG_CONTENT_ONLY) 121 145 fFlagsRemRec |= RTDIRRMREC_F_CONTENT_ONLY; 122 123 146 rc = RTDirRemoveRecursive(szDir, fFlagsRemRec); 147 VGSvcVerbose(4, "[Dir %s]: rmdir /s (%#x) -> rc=%Rrc\n", szDir, fFlags, rc); 124 148 } 125 else /* Only delete directory if not empty. */ 149 else 150 { 151 /* Only delete directory if not empty. */ 126 152 rc = RTDirRemove(szDir); 153 VGSvcVerbose(4, "[Dir %s]: rmdir (%#x), rc=%Rrc\n", szDir, fFlags, rc); 154 } 127 155 } 128 156 else 157 { 158 VGSvcError("[Dir %s]: Unsupported flags: %#x (all %#x)\n", szDir, (fFlags & ~DIRREMOVE_FLAG_VALID_MASK), fFlags); 129 159 rc = VERR_NOT_SUPPORTED; 130 131 VGSvcVerbose(4, "[Dir %s]: Removing with fFlags=0x%x, rc=%Rrc\n", szDir, fFlags, rc); 132 133 /* Report back in any case. */ 160 } 161 162 /* 163 * Report result back to host. 164 */ 134 165 int rc2 = VbglR3GuestCtrlMsgReply(pHostCtx, rc); 135 166 if (RT_FAILURE(rc2)) 167 { 136 168 VGSvcError("[Dir %s]: Failed to report removing status, rc=%Rrc\n", szDir, rc2); 137 if (RT_SUCCESS(rc)) 138 rc = rc2; 139 } 140 141 #ifdef DEBUG 142 VGSvcVerbose(4, "Removing directory '%s' returned rc=%Rrc\n", szDir, rc); 143 #endif 169 if (RT_SUCCESS(rc)) 170 rc = rc2; 171 } 172 } 173 else 174 { 175 VGSvcError("Error fetching parameters for rmdir operation: %Rrc\n", rc); 176 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 177 } 178 179 VGSvcVerbose(6, "Removing directory '%s' returned rc=%Rrc\n", szDir, rc); 144 180 return rc; 145 181 } … … 151 187 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 152 188 153 char szFile[RTPATH_MAX]; 154 char szAccess[64]; 155 char szDisposition[64]; 156 char szSharing[64]; 189 /* 190 * Retrieve the message. 191 */ 192 char szFile[RTPATH_MAX]; 193 char szAccess[64]; 194 char szDisposition[64]; 195 char szSharing[64]; 157 196 uint32_t uCreationMode = 0; 158 uint64_t offOpen = 0; 159 uint32_t uHandle = 0; 160 197 uint64_t offOpen = 0; 198 uint32_t uHandle = 0; 161 199 int rc = VbglR3GuestCtrlFileGetOpen(pHostCtx, 162 200 /* File to open. */ … … 179 217 if (pFile) 180 218 { 181 if (!strlen(szFile)) 182 rc = VERR_INVALID_PARAMETER; 183 184 if (RT_SUCCESS(rc)) 219 pFile->hFile = NIL_RTFILE; /* Not zero or NULL! */ 220 if (szFile[0]) 185 221 { 186 222 RTStrCopy(pFile->szName, sizeof(pFile->szName), szFile); 187 223 224 /** @todo 225 * Implement szSharing! 226 */ 188 227 uint64_t fFlags; 189 228 rc = RTFileModeToFlagsEx(szAccess, szDisposition, NULL /* pszSharing, not used yet */, &fFlags); 190 229 VGSvcVerbose(4, "[File %s] Opening with fFlags=0x%x, rc=%Rrc\n", pFile->szName, fFlags, rc); 191 192 230 if (RT_SUCCESS(rc)) 231 { 193 232 rc = RTFileOpen(&pFile->hFile, pFile->szName, fFlags); 194 if ( RT_SUCCESS(rc) 195 && offOpen) 196 { 197 /* Seeking is optional. However, the whole operation 198 * will fail if we don't succeed seeking to the wanted position. */ 199 rc = RTFileSeek(pFile->hFile, (int64_t)offOpen, RTFILE_SEEK_BEGIN, NULL /* Current offset */); 200 if (RT_FAILURE(rc)) 201 VGSvcError("[File %s] Seeking to offset %RU64 failed; rc=%Rrc\n", pFile->szName, offOpen, rc); 233 if (RT_SUCCESS(rc)) 234 { 235 /* Seeking is optional. However, the whole operation 236 * will fail if we don't succeed seeking to the wanted position. */ 237 if (offOpen) 238 rc = RTFileSeek(pFile->hFile, (int64_t)offOpen, RTFILE_SEEK_BEGIN, NULL /* Current offset */); 239 if (RT_SUCCESS(rc)) 240 { 241 /* 242 * Succeeded! 243 */ 244 uHandle = VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pHostCtx->uContextID); 245 pFile->uHandle = uHandle; 246 RTListAppend(&pSession->lstFiles, &pFile->Node); 247 VGSvcVerbose(2, "[File %s] Opened (ID=%RU32)\n", pFile->szName, pFile->uHandle); 248 } 249 else 250 VGSvcError("[File %s] Seeking to offset %RU64 failed: rc=%Rrc\n", pFile->szName, offOpen, rc); 251 } 252 else 253 VGSvcError("[File %s] Opening failed with rc=%Rrc\n", pFile->szName, rc); 202 254 } 203 else if (RT_FAILURE(rc))204 VGSvcError("[File %s] Opening failed with rc=%Rrc\n", pFile->szName, rc);205 255 } 206 207 if (RT_SUCCESS(rc)) 256 else 208 257 { 209 uHandle = VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pHostCtx->uContextID); 210 pFile->uHandle = uHandle; 211 212 RTListAppend(&pSession->lstFiles, &pFile->Node); 213 214 VGSvcVerbose(2, "[File %s] Opened (ID=%RU32)\n", pFile->szName, pFile->uHandle); 258 VGSvcError("[File %s] empty filename!\n"); 259 rc = VERR_INVALID_NAME; 215 260 } 216 261 262 /* clean up if we failed. */ 217 263 if (RT_FAILURE(rc)) 218 264 { 219 if (pFile->hFile )265 if (pFile->hFile != NIL_RTFILE) 220 266 RTFileClose(pFile->hFile); 221 267 RTMemFree(pFile); … … 225 271 rc = VERR_NO_MEMORY; 226 272 227 /* Report back in any case. */ 273 /* 274 * Report result back to host. 275 */ 228 276 int rc2 = VbglR3GuestCtrlFileCbOpen(pHostCtx, rc, uHandle); 229 277 if (RT_FAILURE(rc2)) 278 { 230 279 VGSvcError("[File %s]: Failed to report file open status, rc=%Rrc\n", szFile, rc2); 231 if (RT_SUCCESS(rc)) 232 rc = rc2; 280 if (RT_SUCCESS(rc)) 281 rc = rc2; 282 } 283 } 284 else 285 { 286 VGSvcError("Error fetching parameters for open file operation: %Rrc\n", rc); 287 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 233 288 } 234 289 … … 244 299 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 245 300 301 /* 302 * Retrieve the message. 303 */ 246 304 uint32_t uHandle = 0; 247 305 int rc = VbglR3GuestCtrlFileGetClose(pHostCtx, &uHandle /* File handle to close */); … … 252 310 { 253 311 VGSvcVerbose(2, "[File %s] Closing (handle=%RU32)\n", pFile ? pFile->szName : "<Not found>", uHandle); 254 255 312 rc = vgsvcGstCtrlSessionFileDestroy(pFile); 256 313 } 257 314 else 315 { 316 VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle); 258 317 rc = VERR_NOT_FOUND; 259 260 /* Report back in any case. */ 318 } 319 320 /* 321 * Report result back to host. 322 */ 261 323 int rc2 = VbglR3GuestCtrlFileCbClose(pHostCtx, rc); 262 324 if (RT_FAILURE(rc2)) 325 { 263 326 VGSvcError("Failed to report file close status, rc=%Rrc\n", rc2); 264 if (RT_SUCCESS(rc)) 265 rc = rc2; 266 } 267 327 if (RT_SUCCESS(rc)) 328 rc = rc2; 329 } 330 } 331 else 332 { 333 VGSvcError("Error fetching parameters for close file operation: %Rrc\n", rc); 334 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 335 } 268 336 return rc; 269 337 } … … 271 339 272 340 static int vgsvcGstCtrlSessionHandleFileRead(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx, 273 void * pvScratchBuf, size_tcbScratchBuf)341 void **ppvScratchBuf, uint32_t *pcbScratchBuf) 274 342 { 275 343 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 276 344 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 277 345 346 /* 347 * Retrieve the request. 348 */ 278 349 uint32_t uHandle = 0; 279 350 uint32_t cbToRead; … … 281 352 if (RT_SUCCESS(rc)) 282 353 { 283 void *pvDataRead = pvScratchBuf; 354 /* 355 * Locate the file and do the reading. 356 * 357 * If the request is larger than our scratch buffer, try grow it - just 358 * ignore failure as the host better respect our buffer limits. 359 */ 284 360 size_t cbRead = 0; 285 286 361 PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle); 287 362 if (pFile) 288 363 { 289 if (cbToRead) 290 { 291 if (cbToRead > cbScratchBuf) 292 { 293 pvDataRead = RTMemAlloc(cbToRead); 294 if (!pvDataRead) 295 rc = VERR_NO_MEMORY; 296 } 297 298 if (RT_LIKELY(RT_SUCCESS(rc))) 299 rc = RTFileRead(pFile->hFile, pvDataRead, cbToRead, &cbRead); 300 } 301 else 302 rc = VERR_BUFFER_UNDERFLOW; 364 if (*pcbScratchBuf < cbToRead) 365 vgsvcGstCtrlSessionGrowScratchBuf(ppvScratchBuf, pcbScratchBuf, cbToRead); 366 367 rc = RTFileRead(pFile->hFile, *ppvScratchBuf, RT_MIN(cbToRead, *pcbScratchBuf), &cbRead); 368 VGSvcVerbose(5, "[File %s] Read %zu/%RU32 bytes, rc=%Rrc\n", pFile->szName, cbRead, cbToRead, rc); 303 369 } 304 370 else 371 { 372 VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle); 305 373 rc = VERR_NOT_FOUND; 306 307 VGSvcVerbose(4, "[File %s] Read %zu/%RU32 bytes, rc=%Rrc\n", pFile ? pFile->szName : "<Not found>", cbRead, cbToRead, rc); 308 309 /* Report back in any case. */ 310 int rc2 = VbglR3GuestCtrlFileCbRead(pHostCtx, rc, pvDataRead, (uint32_t)cbRead); 311 if ( cbToRead > cbScratchBuf 312 && pvDataRead) 313 RTMemFree(pvDataRead); 314 374 } 375 376 /* 377 * Report result and data back to the host. 378 */ 379 int rc2 = VbglR3GuestCtrlFileCbRead(pHostCtx, rc, *ppvScratchBuf, (uint32_t)cbRead); 315 380 if (RT_FAILURE(rc2)) 381 { 316 382 VGSvcError("Failed to report file read status, rc=%Rrc\n", rc2); 317 if (RT_SUCCESS(rc)) 318 rc = rc2; 319 } 320 383 if (RT_SUCCESS(rc)) 384 rc = rc2; 385 } 386 } 387 else 388 { 389 VGSvcError("Error fetching parameters for file read operation: %Rrc\n", rc); 390 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 391 } 321 392 return rc; 322 393 } … … 324 395 325 396 static int vgsvcGstCtrlSessionHandleFileReadAt(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx, 326 void * pvScratchBuf, size_tcbScratchBuf)397 void **ppvScratchBuf, uint32_t *pcbScratchBuf) 327 398 { 328 399 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 329 400 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 330 401 402 /* 403 * Retrieve the request. 404 */ 331 405 uint32_t uHandle = 0; 332 406 uint32_t cbToRead; … … 335 409 if (RT_SUCCESS(rc)) 336 410 { 337 void *pvDataRead = pvScratchBuf; 411 /* 412 * Locate the file and do the reading. 413 * 414 * If the request is larger than our scratch buffer, try grow it - just 415 * ignore failure as the host better respect our buffer limits. 416 */ 338 417 size_t cbRead = 0; 339 340 418 PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle); 341 419 if (pFile) 342 420 { 343 if (cbToRead) 344 { 345 if (cbToRead > cbScratchBuf) 346 { 347 pvDataRead = RTMemAlloc(cbToRead); 348 if (!pvDataRead) 349 rc = VERR_NO_MEMORY; 350 } 351 352 if (RT_SUCCESS(rc)) 353 rc = RTFileReadAt(pFile->hFile, (RTFOFF)offReadAt, pvDataRead, cbToRead, &cbRead); 354 355 VGSvcVerbose(4, "[File %s] Read %zu bytes @ %RU64, rc=%Rrc\n", 356 pFile ? pFile->szName : "<Not found>", cbRead, offReadAt, rc); 357 } 358 else 359 rc = VERR_BUFFER_UNDERFLOW; 421 if (*pcbScratchBuf < cbToRead) 422 vgsvcGstCtrlSessionGrowScratchBuf(ppvScratchBuf, pcbScratchBuf, cbToRead); 423 424 rc = RTFileReadAt(pFile->hFile, (RTFOFF)offReadAt, *ppvScratchBuf, RT_MIN(cbToRead, *pcbScratchBuf), &cbRead); 425 VGSvcVerbose(5, "[File %s] Read %zu bytes @ %RU64, rc=%Rrc\n", pFile->szName, cbRead, offReadAt, rc); 360 426 } 361 427 else 428 { 429 VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle); 362 430 rc = VERR_NOT_FOUND; 363 364 /* Report back in any case. */ 365 int rc2 = VbglR3GuestCtrlFileCbRead(pHostCtx, rc, pvDataRead, (uint32_t)cbRead); 366 if ( cbToRead > cbScratchBuf 367 && pvDataRead) 368 RTMemFree(pvDataRead); 369 431 } 432 433 /* 434 * Report result and data back to the host. 435 */ 436 int rc2 = VbglR3GuestCtrlFileCbRead(pHostCtx, rc, *ppvScratchBuf, (uint32_t)cbRead); 370 437 if (RT_FAILURE(rc2)) 371 VGSvcError("Failed to report file read status, rc=%Rrc\n", rc2); 372 if (RT_SUCCESS(rc)) 373 rc = rc2; 374 } 375 438 { 439 VGSvcError("Failed to report file read at status, rc=%Rrc\n", rc2); 440 if (RT_SUCCESS(rc)) 441 rc = rc2; 442 } 443 } 444 else 445 { 446 VGSvcError("Error fetching parameters for file read at operation: %Rrc\n", rc); 447 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 448 } 376 449 return rc; 377 450 } … … 379 452 380 453 static int vgsvcGstCtrlSessionHandleFileWrite(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx, 381 void * pvScratchBuf, size_tcbScratchBuf)454 void **ppvScratchBuf, uint32_t *pcbScratchBuf) 382 455 { 383 456 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 384 457 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 385 AssertPtrReturn(pvScratchBuf, VERR_INVALID_POINTER); 386 AssertPtrReturn(cbScratchBuf, VERR_INVALID_PARAMETER); 387 458 459 /* 460 * Retrieve the request and data to write. 461 */ 388 462 uint32_t uHandle = 0; 389 463 uint32_t cbToWrite; 390 int rc = VbglR3GuestCtrlFileGetWrite(pHostCtx, &uHandle, pvScratchBuf, (uint32_t)cbScratchBuf, &cbToWrite); 391 if (RT_SUCCESS(rc)) 392 { 393 /* Make sure that we only write up to cbScratchBuf bytes. */ 394 if (cbToWrite > (uint32_t)cbScratchBuf) 395 cbToWrite = (uint32_t)cbScratchBuf; 396 464 int rc = VbglR3GuestCtrlFileGetWrite(pHostCtx, &uHandle, *ppvScratchBuf, *pcbScratchBuf, &cbToWrite); 465 if ( rc == VERR_BUFFER_OVERFLOW 466 && vgsvcGstCtrlSessionGrowScratchBuf(ppvScratchBuf, pcbScratchBuf, cbToWrite)) 467 rc = VbglR3GuestCtrlFileGetWrite(pHostCtx, &uHandle, *ppvScratchBuf, *pcbScratchBuf, &cbToWrite); 468 if (RT_SUCCESS(rc)) 469 { 470 /* 471 * Locate the file and do the writing. 472 */ 397 473 size_t cbWritten = 0; 398 474 PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle); 399 475 if (pFile) 400 476 { 401 rc = RTFileWrite(pFile->hFile, pvScratchBuf, cbToWrite, &cbWritten); 402 #ifdef DEBUG 403 VGSvcVerbose(4, "[File %s] Writing pvScratchBuf=%p, cbToWrite=%RU32, cbWritten=%zu, rc=%Rrc\n", 404 pFile->szName, pvScratchBuf, cbToWrite, cbWritten, rc); 405 #endif 477 rc = RTFileWrite(pFile->hFile, *ppvScratchBuf, RT_MIN(cbToWrite, *pcbScratchBuf), &cbWritten); 478 VGSvcVerbose(5, "[File %s] Writing %p LB %RU32 => %Rrc, cbWritten=%zu\n", 479 pFile->szName, *ppvScratchBuf, RT_MIN(cbToWrite, *pcbScratchBuf), rc, cbWritten); 406 480 } 407 481 else 482 { 483 VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle); 408 484 rc = VERR_NOT_FOUND; 409 410 /* Report back in any case. */ 485 } 486 487 /* 488 * Report result back to host. 489 */ 411 490 int rc2 = VbglR3GuestCtrlFileCbWrite(pHostCtx, rc, (uint32_t)cbWritten); 412 491 if (RT_FAILURE(rc2)) 492 { 413 493 VGSvcError("Failed to report file write status, rc=%Rrc\n", rc2); 414 if (RT_SUCCESS(rc)) 415 rc = rc2; 416 } 417 494 if (RT_SUCCESS(rc)) 495 rc = rc2; 496 } 497 } 498 else 499 { 500 VGSvcError("Error fetching parameters for file write operation: %Rrc\n", rc); 501 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 502 } 418 503 return rc; 419 504 } … … 421 506 422 507 static int vgsvcGstCtrlSessionHandleFileWriteAt(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx, 423 void * pvScratchBuf, size_tcbScratchBuf)508 void **ppvScratchBuf, uint32_t *pcbScratchBuf) 424 509 { 425 510 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 426 511 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 427 AssertPtrReturn(pvScratchBuf, VERR_INVALID_POINTER); 428 AssertPtrReturn(cbScratchBuf, VERR_INVALID_PARAMETER); 429 512 513 /* 514 * Retrieve the request and data to write. 515 */ 430 516 uint32_t uHandle = 0; 431 517 uint32_t cbToWrite; 432 518 uint64_t offWriteAt; 433 434 int rc = VbglR3GuestCtrlFileGetWriteAt(pHostCtx, &uHandle, pvScratchBuf, (uint32_t)cbScratchBuf, &cbToWrite, &offWriteAt); 435 if (RT_SUCCESS(rc)) 436 { 519 int rc = VbglR3GuestCtrlFileGetWriteAt(pHostCtx, &uHandle, *ppvScratchBuf, *pcbScratchBuf, &cbToWrite, &offWriteAt); 520 if ( rc == VERR_BUFFER_OVERFLOW 521 && vgsvcGstCtrlSessionGrowScratchBuf(ppvScratchBuf, pcbScratchBuf, cbToWrite)) 522 rc = VbglR3GuestCtrlFileGetWriteAt(pHostCtx, &uHandle, *ppvScratchBuf, *pcbScratchBuf, &cbToWrite, &offWriteAt); 523 if (RT_SUCCESS(rc)) 524 { 525 /* 526 * Locate the file and do the writing. 527 */ 437 528 size_t cbWritten = 0; 438 529 PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle); 439 530 if (pFile) 440 531 { 441 rc = RTFileWriteAt(pFile->hFile, (RTFOFF)offWriteAt, pvScratchBuf, cbToWrite, &cbWritten); 442 #ifdef DEBUG 443 VGSvcVerbose(4, "[File %s] Writing offWriteAt=%RI64, pvScratchBuf=%p, cbToWrite=%RU32, cbWritten=%zu, rc=%Rrc\n", 444 pFile->szName, offWriteAt, pvScratchBuf, cbToWrite, cbWritten, rc); 445 #endif 532 rc = RTFileWriteAt(pFile->hFile, (RTFOFF)offWriteAt, *ppvScratchBuf, RT_MIN(cbToWrite, *pcbScratchBuf), &cbWritten); 533 VGSvcVerbose(5, "[File %s] Writing %p LB %RU32 @ %RU64 => %Rrc, cbWritten=%zu\n", 534 pFile->szName, *ppvScratchBuf, RT_MIN(cbToWrite, *pcbScratchBuf), offWriteAt, rc, cbWritten); 446 535 } 447 536 else 537 { 538 VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle); 448 539 rc = VERR_NOT_FOUND; 449 450 /* Report back in any case. */ 540 } 541 542 /* 543 * Report result back to host. 544 */ 451 545 int rc2 = VbglR3GuestCtrlFileCbWrite(pHostCtx, rc, (uint32_t)cbWritten); 452 546 if (RT_FAILURE(rc2)) 547 { 453 548 VGSvcError("Failed to report file write status, rc=%Rrc\n", rc2); 454 if (RT_SUCCESS(rc)) 455 rc = rc2; 456 } 457 549 if (RT_SUCCESS(rc)) 550 rc = rc2; 551 } 552 } 553 else 554 { 555 VGSvcError("Error fetching parameters for file write at operation: %Rrc\n", rc); 556 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 557 } 458 558 return rc; 459 559 } … … 465 565 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 466 566 567 /* 568 * Retrieve the request. 569 */ 467 570 uint32_t uHandle = 0; 468 571 uint32_t uSeekMethod; … … 472 575 { 473 576 uint64_t offActual = 0; 577 578 /* 579 * Validate and convert the seek method to IPRT speak. 580 */ 581 static const uint8_t s_abMethods[GUEST_FILE_SEEKTYPE_END + 1] = 582 { 583 UINT8_MAX, RTFILE_SEEK_BEGIN, UINT8_MAX, UINT8_MAX, RTFILE_SEEK_CURRENT, 584 UINT8_MAX, UINT8_MAX, UINT8_MAX, GUEST_FILE_SEEKTYPE_END 585 }; 586 if ( uSeekMethod < RT_ELEMENTS(s_abMethods) 587 && s_abMethods[uSeekMethod] != UINT8_MAX) 588 { 589 /* 590 * Locate the file and do the seek. 591 */ 592 PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle); 593 if (pFile) 594 { 595 rc = RTFileSeek(pFile->hFile, (int64_t)offSeek, s_abMethods[uSeekMethod], &offActual); 596 VGSvcVerbose(5, "[File %s]: Seeking to offSeek=%RI64, uSeekMethodIPRT=%u, rc=%Rrc\n", 597 pFile->szName, offSeek, s_abMethods[uSeekMethod], rc); 598 } 599 else 600 { 601 VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle); 602 rc = VERR_NOT_FOUND; 603 } 604 } 605 else 606 { 607 VGSvcError("Invalid seek method: %#x\n", uSeekMethod); 608 rc = VERR_NOT_SUPPORTED; 609 } 610 611 /* 612 * Report result back to host. 613 */ 614 int rc2 = VbglR3GuestCtrlFileCbSeek(pHostCtx, rc, offActual); 615 if (RT_FAILURE(rc2)) 616 { 617 VGSvcError("Failed to report file seek status, rc=%Rrc\n", rc2); 618 if (RT_SUCCESS(rc)) 619 rc = rc2; 620 } 621 } 622 else 623 { 624 VGSvcError("Error fetching parameters for file seek operation: %Rrc\n", rc); 625 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 626 } 627 return rc; 628 } 629 630 631 static int vgsvcGstCtrlSessionHandleFileTell(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx) 632 { 633 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 634 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 635 636 /* 637 * Retrieve the request. 638 */ 639 uint32_t uHandle = 0; 640 int rc = VbglR3GuestCtrlFileGetTell(pHostCtx, &uHandle); 641 if (RT_SUCCESS(rc)) 642 { 643 /* 644 * Locate the file and ask for the current position. 645 */ 646 uint64_t offCurrent = 0; 474 647 PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle); 475 648 if (pFile) 476 649 { 477 unsigned uSeekMethodIprt; 478 switch (uSeekMethod) 479 { 480 case GUEST_FILE_SEEKTYPE_BEGIN: 481 uSeekMethodIprt = RTFILE_SEEK_BEGIN; 482 break; 483 484 case GUEST_FILE_SEEKTYPE_CURRENT: 485 uSeekMethodIprt = RTFILE_SEEK_CURRENT; 486 break; 487 488 case GUEST_FILE_SEEKTYPE_END: 489 uSeekMethodIprt = RTFILE_SEEK_END; 490 break; 491 492 default: 493 rc = VERR_NOT_SUPPORTED; 494 uSeekMethodIprt = RTFILE_SEEK_BEGIN; /* Shut up MSC */ 495 break; 496 } 497 650 offCurrent = RTFileTell(pFile->hFile); 651 VGSvcVerbose(5, "[File %s]: Telling offCurrent=%RU64\n", pFile->szName, offCurrent); 652 } 653 else 654 { 655 VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle); 656 rc = VERR_NOT_FOUND; 657 } 658 659 /* 660 * Report result back to host. 661 */ 662 int rc2 = VbglR3GuestCtrlFileCbTell(pHostCtx, rc, offCurrent); 663 if (RT_FAILURE(rc2)) 664 { 665 VGSvcError("Failed to report file tell status, rc=%Rrc\n", rc2); 498 666 if (RT_SUCCESS(rc)) 499 { 500 rc = RTFileSeek(pFile->hFile, (int64_t)offSeek, uSeekMethodIprt, &offActual); 501 #ifdef DEBUG 502 VGSvcVerbose(4, "[File %s]: Seeking to offSeek=%RI64, uSeekMethodIPRT=%RU16, rc=%Rrc\n", 503 pFile->szName, offSeek, uSeekMethodIprt, rc); 504 #endif 505 } 506 } 507 else 508 rc = VERR_NOT_FOUND; 509 510 /* Report back in any case. */ 511 int rc2 = VbglR3GuestCtrlFileCbSeek(pHostCtx, rc, offActual); 512 if (RT_FAILURE(rc2)) 513 VGSvcError("Failed to report file seek status, rc=%Rrc\n", rc2); 514 if (RT_SUCCESS(rc)) 515 rc = rc2; 516 } 517 518 return rc; 519 } 520 521 522 static int vgsvcGstCtrlSessionHandleFileTell(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx) 667 rc = rc2; 668 } 669 } 670 else 671 { 672 VGSvcError("Error fetching parameters for file tell operation: %Rrc\n", rc); 673 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 674 } 675 return rc; 676 } 677 678 679 static int vgsvcGstCtrlSessionHandlePathRename(PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx) 523 680 { 524 681 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 525 682 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 526 683 527 uint32_t uHandle = 0; 528 int rc = VbglR3GuestCtrlFileGetTell(pHostCtx, &uHandle); 529 if (RT_SUCCESS(rc)) 530 { 531 uint64_t uOffCurrent = 0; 532 PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle); 533 if (pFile) 534 { 535 uOffCurrent = RTFileTell(pFile->hFile); 536 #ifdef DEBUG 537 VGSvcVerbose(4, "[File %s]: Telling uOffCurrent=%RU64\n", pFile->szName, uOffCurrent); 538 #endif 684 /* 685 * Retrieve the request. 686 */ 687 char szSource[RTPATH_MAX]; 688 char szDest[RTPATH_MAX]; 689 uint32_t fFlags = 0; /* PATHRENAME_FLAG_XXX */ 690 int rc = VbglR3GuestCtrlPathGetRename(pHostCtx, szSource, sizeof(szSource), szDest, sizeof(szDest), &fFlags); 691 if (RT_SUCCESS(rc)) 692 { 693 /* 694 * Validate the flags (kudos for using the same as IPRT), then do the renaming. 695 */ 696 AssertCompile(PATHRENAME_FLAG_NO_REPLACE == RTPATHRENAME_FLAGS_NO_REPLACE); 697 AssertCompile(PATHRENAME_FLAG_REPLACE == RTPATHRENAME_FLAGS_REPLACE); 698 AssertCompile(PATHRENAME_FLAG_NO_SYMLINKS == RTPATHRENAME_FLAGS_NO_SYMLINKS); 699 AssertCompile(PATHRENAME_FLAG_VALID_MASK == (RTPATHRENAME_FLAGS_NO_REPLACE | RTPATHRENAME_FLAGS_REPLACE | RTPATHRENAME_FLAGS_NO_SYMLINKS)); 700 if (!(fFlags & ~PATHRENAME_FLAG_VALID_MASK)) 701 { 702 VGSvcVerbose(4, "Renaming '%s' to '%s', fFlags=%#x, rc=%Rrc\n", szSource, szDest, fFlags, rc); 703 rc = RTPathRename(szSource, szDest, fFlags); 539 704 } 540 705 else 541 rc = VERR_NOT_FOUND; 542 543 /* Report back in any case. */ 544 int rc2 = VbglR3GuestCtrlFileCbTell(pHostCtx, rc, uOffCurrent); 545 if (RT_FAILURE(rc2)) 546 VGSvcError("Failed to report file tell status, rc=%Rrc\n", rc2); 547 if (RT_SUCCESS(rc)) 548 rc = rc2; 549 } 550 551 return rc; 552 } 553 554 555 static int vgsvcGstCtrlSessionHandlePathRename(PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx) 556 { 557 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 558 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 559 560 char szSource[RTPATH_MAX]; 561 char szDest[RTPATH_MAX]; 562 uint32_t fFlags = 0; 563 564 int rc = VbglR3GuestCtrlPathGetRename(pHostCtx, 565 szSource, sizeof(szSource), 566 szDest, sizeof(szDest), 567 /* Flags of type PATHRENAME_FLAG_. */ 568 &fFlags); 569 if (RT_SUCCESS(rc)) 570 { 571 if (fFlags & ~PATHRENAME_FLAG_VALID_MASK) 706 { 707 VGSvcError("Invalid rename flags: %#x\n", fFlags); 572 708 rc = VERR_NOT_SUPPORTED; 573 574 VGSvcVerbose(4, "Renaming '%s' to '%s', fFlags=0x%x, rc=%Rrc\n", szSource, szDest, fFlags, rc); 575 576 if (RT_SUCCESS(rc)) 577 { 578 unsigned fPathRenameFlags = 0; 579 580 if (fFlags & PATHRENAME_FLAG_NO_REPLACE) 581 fPathRenameFlags |= RTPATHRENAME_FLAGS_NO_REPLACE; 582 583 if (fFlags & PATHRENAME_FLAG_REPLACE) 584 fPathRenameFlags |= RTPATHRENAME_FLAGS_REPLACE; 585 586 if (fFlags & PATHRENAME_FLAG_NO_SYMLINKS) 587 fPathRenameFlags |= RTPATHRENAME_FLAGS_NO_SYMLINKS; 588 589 rc = RTPathRename(szSource, szDest, fPathRenameFlags); 590 } 591 592 /* Report back in any case. */ 709 } 710 711 /* 712 * Report result back to host. 713 */ 593 714 int rc2 = VbglR3GuestCtrlMsgReply(pHostCtx, rc); 594 715 if (RT_FAILURE(rc2)) 716 { 595 717 VGSvcError("Failed to report renaming status, rc=%Rrc\n", rc2); 596 if (RT_SUCCESS(rc)) 597 rc = rc2; 598 } 599 600 #ifdef DEBUG 601 VGSvcVerbose(4, "Renaming '%s' to '%s' returned rc=%Rrc\n", szSource, szDest, rc); 602 #endif 718 if (RT_SUCCESS(rc)) 719 rc = rc2; 720 } 721 } 722 else 723 { 724 VGSvcError("Error fetching parameters for rename operation: %Rrc\n", rc); 725 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 726 } 727 VGSvcVerbose(5, "Renaming '%s' to '%s' returned rc=%Rrc\n", szSource, szDest, rc); 603 728 return rc; 604 729 } … … 617 742 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 618 743 744 /* 745 * Retrieve the request. 746 */ 619 747 int rc = VbglR3GuestCtrlPathGetUserDocuments(pHostCtx); 620 748 if (RT_SUCCESS(rc)) 621 749 { 750 /* 751 * Get the path and pass it back to the host.. 752 */ 622 753 char szPath[RTPATH_MAX]; 623 754 rc = RTPathUserDocuments(szPath, sizeof(szPath)); 624 625 755 #ifdef DEBUG 626 756 VGSvcVerbose(2, "User documents is '%s', rc=%Rrc\n", szPath, rc); 627 757 #endif 628 /* Report back in any case. */ 629 int rc2 = VbglR3GuestCtrlMsgReplyEx(pHostCtx, rc, 0 /* Type */, 630 szPath, (uint32_t)strlen(szPath) + 1 /* Include terminating zero */);758 759 int rc2 = VbglR3GuestCtrlMsgReplyEx(pHostCtx, rc, 0 /* Type */, szPath, 760 RT_SUCCESS(rc) ? (uint32_t)strlen(szPath) + 1 /* Include terminating zero */ : 0); 631 761 if (RT_FAILURE(rc2)) 762 { 632 763 VGSvcError("Failed to report user documents, rc=%Rrc\n", rc2); 633 if (RT_SUCCESS(rc)) 634 rc = rc2; 635 } 636 764 if (RT_SUCCESS(rc)) 765 rc = rc2; 766 } 767 } 768 else 769 { 770 VGSvcError("Error fetching parameters for user documents path request: %Rrc\n", rc); 771 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 772 } 637 773 return rc; 638 774 } … … 651 787 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 652 788 789 /* 790 * Retrieve the request. 791 */ 653 792 int rc = VbglR3GuestCtrlPathGetUserHome(pHostCtx); 654 793 if (RT_SUCCESS(rc)) 655 794 { 795 /* 796 * Get the path and pass it back to the host.. 797 */ 656 798 char szPath[RTPATH_MAX]; 657 799 rc = RTPathUserHome(szPath, sizeof(szPath)); … … 661 803 #endif 662 804 /* Report back in any case. */ 663 int rc2 = VbglR3GuestCtrlMsgReplyEx(pHostCtx, rc, 0 /* Type */, 664 szPath, (uint32_t)strlen(szPath) + 1 /* Include terminating zero */);805 int rc2 = VbglR3GuestCtrlMsgReplyEx(pHostCtx, rc, 0 /* Type */, szPath, 806 RT_SUCCESS(rc) ?(uint32_t)strlen(szPath) + 1 /* Include terminating zero */ : 0); 665 807 if (RT_FAILURE(rc2)) 808 { 666 809 VGSvcError("Failed to report user home, rc=%Rrc\n", rc2); 667 if (RT_SUCCESS(rc)) 668 rc = rc2; 669 } 670 810 if (RT_SUCCESS(rc)) 811 rc = rc2; 812 } 813 } 814 else 815 { 816 VGSvcError("Error fetching parameters for user home directory path request: %Rrc\n", rc); 817 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 818 } 671 819 return rc; 672 820 } … … 685 833 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 686 834 687 int rc = VINF_SUCCESS; 688 bool fStartAllowed = false; /* Flag indicating whether starting a process is allowed or not. */ 689 690 switch (pHostCtx->uProtocol) 691 { 692 case 1: /* Guest Additions < 4.3. */ 693 if (pHostCtx->uNumParms != 11) 694 rc = VERR_NOT_SUPPORTED; 695 break; 696 697 case 2: /* Guest Additions >= 4.3. */ 698 if (pHostCtx->uNumParms != 12) 699 rc = VERR_NOT_SUPPORTED; 700 break; 701 702 default: 703 rc = VERR_NOT_SUPPORTED; 704 break; 705 } 706 707 if (RT_SUCCESS(rc)) 708 { 709 VBOXSERVICECTRLPROCSTARTUPINFO startupInfo; 710 RT_ZERO(startupInfo); 711 712 /* Initialize maximum environment block size -- needed as input 713 * parameter to retrieve the stuff from the host. On output this then 714 * will contain the actual block size. */ 715 startupInfo.cbEnv = sizeof(startupInfo.szEnv); 716 717 rc = VbglR3GuestCtrlProcGetStart(pHostCtx, 835 /** @todo this hardcoded stuff needs redoing. */ 836 837 /* Initialize maximum environment block size -- needed as input 838 * parameter to retrieve the stuff from the host. On output this then 839 * will contain the actual block size. */ 840 VBOXSERVICECTRLPROCSTARTUPINFO startupInfo; 841 RT_ZERO(startupInfo); 842 startupInfo.cbEnv = sizeof(startupInfo.szEnv); 843 844 int rc = VbglR3GuestCtrlProcGetStart(pHostCtx, 718 845 /* Command */ 719 846 startupInfo.szCmd, sizeof(startupInfo.szCmd), … … 735 862 /* Process affinity */ 736 863 startupInfo.uAffinity, sizeof(startupInfo.uAffinity), &startupInfo.uNumAffinity); 864 if (RT_SUCCESS(rc)) 865 { 866 VGSvcVerbose(3, "Request to start process szCmd=%s, fFlags=0x%x, szArgs=%s, szEnv=%s, uTimeout=%RU32\n", 867 startupInfo.szCmd, startupInfo.uFlags, 868 startupInfo.uNumArgs ? startupInfo.szArgs : "<None>", 869 startupInfo.uNumEnvVars ? startupInfo.szEnv : "<None>", 870 startupInfo.uTimeLimitMS); 871 872 bool fStartAllowed = false; /* Flag indicating whether starting a process is allowed or not. */ 873 rc = VGSvcGstCtrlSessionProcessStartAllowed(pSession, &fStartAllowed); 737 874 if (RT_SUCCESS(rc)) 738 875 { 739 VGSvcVerbose(3, "Request to start process szCmd=%s, fFlags=0x%x, szArgs=%s, szEnv=%s, uTimeout=%RU32\n", 740 startupInfo.szCmd, startupInfo.uFlags, 741 startupInfo.uNumArgs ? startupInfo.szArgs : "<None>", 742 startupInfo.uNumEnvVars ? startupInfo.szEnv : "<None>", 743 startupInfo.uTimeLimitMS); 744 745 rc = VGSvcGstCtrlSessionProcessStartAllowed(pSession, &fStartAllowed); 746 if (RT_SUCCESS(rc)) 747 { 748 if (fStartAllowed) 749 rc = VGSvcGstCtrlProcessStart(pSession, &startupInfo, pHostCtx->uContextID); 750 else 751 rc = VERR_MAX_PROCS_REACHED; /* Maximum number of processes reached. */ 752 } 753 } 754 } 755 756 /* In case of an error we need to notify the host to not wait forever for our response. */ 757 if (RT_FAILURE(rc)) 758 { 759 VGSvcError("Starting process failed with rc=%Rrc, protocol=%RU32, parameters=%RU32\n", 760 rc, pHostCtx->uProtocol, pHostCtx->uNumParms); 761 762 /* Don't report back if we didn't supply sufficient buffer for getting 763 * the actual command -- we don't have the matching context ID. */ 764 if (rc != VERR_TOO_MUCH_DATA) 765 { 766 /* 767 * Note: The context ID can be 0 because we mabye weren't able to fetch the command 768 * from the host. The host in case has to deal with that! 769 */ 770 int rc2 = VbglR3GuestCtrlProcCbStatus(pHostCtx, 0 /* PID, invalid */, 771 PROC_STS_ERROR, rc, 772 NULL /* pvData */, 0 /* cbData */); 876 if (fStartAllowed) 877 rc = VGSvcGstCtrlProcessStart(pSession, &startupInfo, pHostCtx->uContextID); 878 else 879 rc = VERR_MAX_PROCS_REACHED; /* Maximum number of processes reached. */ 880 } 881 882 /* We're responsible for signaling errors to the host (it will wait for ever otherwise). */ 883 if (RT_FAILURE(rc)) 884 { 885 VGSvcError("Starting process failed with rc=%Rrc, protocol=%RU32, parameters=%RU32\n", 886 rc, pHostCtx->uProtocol, pHostCtx->uNumParms); 887 int rc2 = VbglR3GuestCtrlProcCbStatus(pHostCtx, 0 /*nil-PID*/, PROC_STS_ERROR, rc, NULL /*pvData*/, 0 /*cbData*/); 773 888 if (RT_FAILURE(rc2)) 774 889 VGSvcError("Error sending start process status to host, rc=%Rrc\n", rc2); 775 890 } 776 891 } 777 892 else 893 { 894 VGSvcError("Failed to retrieve parameters for process start: %Rrc (cParms=%u)\n", rc, pHostCtx->uNumParms); 895 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 896 } 778 897 return rc; 779 898 } … … 786 905 * @param pSession The session which is in charge. 787 906 * @param pHostCtx The host context to use. 788 * @param p vScratchBuf The scratch buffer.789 * @param cbScratchBufThe scratch buffer size for retrieving the input907 * @param ppvScratchBuf The scratch buffer, we may grow it. 908 * @param pcbScratchBuf The scratch buffer size for retrieving the input 790 909 * data. 791 910 */ 792 911 static int vgsvcGstCtrlSessionHandleProcInput(PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx, 793 void * pvScratchBuf, size_tcbScratchBuf)912 void **ppvScratchBuf, uint32_t *pcbScratchBuf) 794 913 { 795 914 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 796 915 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 797 AssertPtrReturn(cbScratchBuf, VERR_INVALID_PARAMETER); 798 AssertPtrReturn(pvScratchBuf, VERR_INVALID_POINTER); 799 916 917 /* 918 * Retrieve the data from the host. 919 */ 800 920 uint32_t uPID; 801 921 uint32_t fFlags; 802 uint32_t cbSize; 803 804 #if 0 /* unused */ 805 uint32_t uStatus = INPUT_STS_UNDEFINED; /* Status sent back to the host. */ 806 uint32_t cbWritten = 0; /* Number of bytes written to the guest. */ 807 #endif 808 809 /* 810 * Ask the host for the input data. 811 */ 812 int rc = VbglR3GuestCtrlProcGetInput(pHostCtx, &uPID, &fFlags, 813 pvScratchBuf, (uint32_t)cbScratchBuf, &cbSize); 814 if (RT_FAILURE(rc)) 815 VGSvcError("Failed to retrieve process input command for PID=%RU32, rc=%Rrc\n", uPID, rc); 816 else if (cbSize > cbScratchBuf) 817 { 818 VGSvcError("Too much process input received, rejecting: uPID=%RU32, cbSize=%RU32, cbScratchBuf=%RU32\n", 819 uPID, cbSize, cbScratchBuf); 820 rc = VERR_TOO_MUCH_DATA; 821 } 822 else 823 { 824 /* 825 * Is this the last input block we need to deliver? Then let the pipe know ... 826 */ 827 bool fPendingClose = false; 922 uint32_t cbInput; 923 int rc = VbglR3GuestCtrlProcGetInput(pHostCtx, &uPID, &fFlags, *ppvScratchBuf, *pcbScratchBuf, &cbInput); 924 if ( rc == VERR_BUFFER_OVERFLOW 925 && vgsvcGstCtrlSessionGrowScratchBuf(ppvScratchBuf, pcbScratchBuf, cbInput)) 926 rc = VbglR3GuestCtrlProcGetInput(pHostCtx, &uPID, &fFlags, *ppvScratchBuf, *pcbScratchBuf, &cbInput); 927 if (RT_SUCCESS(rc)) 928 { 828 929 if (fFlags & INPUT_FLAG_EOF) 829 { 830 fPendingClose = true; 831 #ifdef DEBUG 832 VGSvcVerbose(4, "Got last process input block for PID=%RU32 (%RU32 bytes) ...\n", uPID, cbSize); 833 #endif 834 } 835 930 VGSvcVerbose(4, "Got last process input block for PID=%RU32 (%RU32 bytes) ...\n", uPID, cbInput); 931 932 /* 933 * Locate the process and feed it. 934 */ 836 935 PVBOXSERVICECTRLPROCESS pProcess = VGSvcGstCtrlSessionRetainProcess(pSession, uPID); 837 936 if (pProcess) 838 937 { 839 rc = VGSvcGstCtrlProcessHandleInput(pProcess, pHostCtx, fPendingClose, pvScratchBuf, cbSize); 938 rc = VGSvcGstCtrlProcessHandleInput(pProcess, pHostCtx, RT_BOOL(fFlags & INPUT_FLAG_EOF), 939 *ppvScratchBuf, RT_MIN(cbInput, *pcbScratchBuf)); 840 940 if (RT_FAILURE(rc)) 841 941 VGSvcError("Error handling input command for PID=%RU32, rc=%Rrc\n", uPID, rc); … … 843 943 } 844 944 else 845 rc = VERR_NOT_FOUND; 846 } 847 848 #ifdef DEBUG 849 VGSvcVerbose(4, "Setting input for PID=%RU32 resulted in rc=%Rrc\n", uPID, rc); 850 #endif 945 { 946 VGSvcError("Could not find PID %u for feeding %u bytes to it.\n", uPID, cbInput); 947 rc = VERR_PROCESS_NOT_FOUND; 948 VbglR3GuestCtrlProcCbStatusInput(pHostCtx, uPID, INPUT_STS_ERROR, rc, 0); 949 } 950 } 951 else 952 { 953 VGSvcError("Failed to retrieve parameters for process input: %Rrc (scratch %u bytes)\n", rc, *pcbScratchBuf); 954 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 955 } 956 957 VGSvcVerbose(6, "Feeding input to PID=%RU32 resulted in rc=%Rrc\n", uPID, rc); 851 958 return rc; 852 959 } … … 865 972 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 866 973 974 /* 975 * Retrieve the request. 976 */ 867 977 uint32_t uPID; 868 978 uint32_t uHandleID; 869 979 uint32_t fFlags; 870 871 980 int rc = VbglR3GuestCtrlProcGetOutput(pHostCtx, &uPID, &uHandleID, &fFlags); 872 981 #ifdef DEBUG_andy … … 876 985 if (RT_SUCCESS(rc)) 877 986 { 987 /* 988 * Locate the process and hand it the output request. 989 */ 878 990 PVBOXSERVICECTRLPROCESS pProcess = VGSvcGstCtrlSessionRetainProcess(pSession, uPID); 879 991 if (pProcess) … … 885 997 } 886 998 else 887 rc = VERR_NOT_FOUND; 999 { 1000 VGSvcError("Could not find PID %u for draining handle %u (%#x).\n", uPID, uHandleID, uHandleID); 1001 rc = VERR_PROCESS_NOT_FOUND; 1002 /** @todo r=bird: 1003 * 1004 * No way to report status status code for output requests? 1005 * 1006 */ 1007 } 1008 } 1009 else 1010 { 1011 VGSvcError("Error fetching parameters for process output request: %Rrc\n", rc); 1012 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 888 1013 } 889 1014 … … 907 1032 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 908 1033 1034 /* 1035 * Retrieve the request. 1036 */ 909 1037 uint32_t uPID; 910 1038 int rc = VbglR3GuestCtrlProcGetTerminate(pHostCtx, &uPID); 911 1039 if (RT_SUCCESS(rc)) 912 1040 { 1041 /* 1042 * Locate the process and terminate it. 1043 */ 913 1044 PVBOXSERVICECTRLPROCESS pProcess = VGSvcGstCtrlSessionRetainProcess(pSession, uPID); 914 1045 if (pProcess) … … 919 1050 } 920 1051 else 921 rc = VERR_NOT_FOUND; 922 } 923 1052 { 1053 VGSvcError("Could not find PID %u for termination.\n", uPID); 1054 rc = VERR_PROCESS_NOT_FOUND; 1055 /** @todo r=bird: 1056 * 1057 * No way to report status status code for output requests? 1058 * 1059 */ 1060 } 1061 } 1062 else 1063 { 1064 VGSvcError("Error fetching parameters for process termination request: %Rrc\n", rc); 1065 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 1066 } 924 1067 #ifdef DEBUG_andy 925 1068 VGSvcVerbose(4, "Terminating PID=%RU32 resulted in rc=%Rrc\n", uPID, rc); … … 934 1077 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 935 1078 1079 /* 1080 * Retrieve the request. 1081 */ 936 1082 uint32_t uPID; 937 uint32_t uWaitFlags; uint32_t uTimeoutMS;938 1083 uint32_t uWaitFlags; 1084 uint32_t uTimeoutMS; 939 1085 int rc = VbglR3GuestCtrlProcGetWaitFor(pHostCtx, &uPID, &uWaitFlags, &uTimeoutMS); 940 1086 if (RT_SUCCESS(rc)) 941 1087 { 1088 /* 1089 * Locate the process and the realize that this call makes no sense 1090 * since we'll notify the host when a process terminates anyway and 1091 * hopefully don't need any additional encouragement. 1092 */ 942 1093 PVBOXSERVICECTRLPROCESS pProcess = VGSvcGstCtrlSessionRetainProcess(pSession, uPID); 943 1094 if (pProcess) … … 949 1100 rc = VERR_NOT_FOUND; 950 1101 } 951 1102 else 1103 { 1104 VGSvcError("Error fetching parameters for process wait request: %Rrc\n", rc); 1105 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 1106 } 952 1107 return rc; 953 1108 } … … 955 1110 956 1111 int VGSvcGstCtrlSessionHandler(PVBOXSERVICECTRLSESSION pSession, uint32_t uMsg, PVBGLR3GUESTCTRLCMDCTX pHostCtx, 957 void * pvScratchBuf, size_tcbScratchBuf, volatile bool *pfShutdown)1112 void **ppvScratchBuf, uint32_t *pcbScratchBuf, volatile bool *pfShutdown) 958 1113 { 959 1114 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 960 1115 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 961 AssertPtrReturn( pvScratchBuf, VERR_INVALID_POINTER);1116 AssertPtrReturn(*ppvScratchBuf, VERR_INVALID_POINTER); 962 1117 AssertPtrReturn(pfShutdown, VERR_INVALID_POINTER); 963 1118 … … 990 1145 991 1146 case HOST_EXEC_SET_INPUT: 992 rc = vgsvcGstCtrlSessionHandleProcInput(pSession, pHostCtx, p vScratchBuf,cbScratchBuf);1147 rc = vgsvcGstCtrlSessionHandleProcInput(pSession, pHostCtx, ppvScratchBuf, pcbScratchBuf); 993 1148 break; 994 1149 … … 1017 1172 case HOST_FILE_READ: 1018 1173 if (fImpersonated) 1019 rc = vgsvcGstCtrlSessionHandleFileRead(pSession, pHostCtx, p vScratchBuf,cbScratchBuf);1174 rc = vgsvcGstCtrlSessionHandleFileRead(pSession, pHostCtx, ppvScratchBuf, pcbScratchBuf); 1020 1175 break; 1021 1176 1022 1177 case HOST_FILE_READ_AT: 1023 1178 if (fImpersonated) 1024 rc = vgsvcGstCtrlSessionHandleFileReadAt(pSession, pHostCtx, p vScratchBuf,cbScratchBuf);1179 rc = vgsvcGstCtrlSessionHandleFileReadAt(pSession, pHostCtx, ppvScratchBuf, pcbScratchBuf); 1025 1180 break; 1026 1181 1027 1182 case HOST_FILE_WRITE: 1028 1183 if (fImpersonated) 1029 rc = vgsvcGstCtrlSessionHandleFileWrite(pSession, pHostCtx, p vScratchBuf,cbScratchBuf);1184 rc = vgsvcGstCtrlSessionHandleFileWrite(pSession, pHostCtx, ppvScratchBuf, pcbScratchBuf); 1030 1185 break; 1031 1186 1032 1187 case HOST_FILE_WRITE_AT: 1033 1188 if (fImpersonated) 1034 rc = vgsvcGstCtrlSessionHandleFileWriteAt(pSession, pHostCtx, p vScratchBuf,cbScratchBuf);1189 rc = vgsvcGstCtrlSessionHandleFileWriteAt(pSession, pHostCtx, ppvScratchBuf, pcbScratchBuf); 1035 1190 break; 1036 1191 … … 1063 1218 break; 1064 1219 } 1065 1066 if (rc == VERR_NOT_SUPPORTED) 1067 { 1220 if (RT_SUCCESS(rc)) 1221 { /* likely */ } 1222 else if (rc != VERR_NOT_SUPPORTED) /* Note: Reply to host must must be sent by above handler. */ 1223 VGSvcError("Error while handling message (uMsg=%RU32, cParms=%RU32), rc=%Rrc\n", uMsg, pHostCtx->uNumParms, rc); 1224 else 1225 { 1226 /* We must skip and notify host here as best we can... */ 1068 1227 VGSvcVerbose(3, "Unsupported message (uMsg=%RU32, cParms=%RU32) from host, skipping\n", uMsg, pHostCtx->uNumParms); 1069 1070 /* 1071 * !!! HACK ALERT BEGIN !!! 1072 * As peeking for the current message by VbglR3GuestCtrlMsgWaitFor() / GUEST_MSG_WAIT only gives us the message type and 1073 * the number of parameters, but *not* the actual context ID the message is bound to, try to retrieve it here. 1074 * 1075 * This is needed in order to reply to the host with the current context ID, without breaking existing clients. 1076 * Not doing this isn't fatal, but will make host clients wait longer (timing out) for not implemented messages. */ 1077 /** @todo Get rid of this as soon as we have a protocol bump (v4). */ 1078 struct HGCMMsgSkip 1079 { 1080 VBGLIOCHGCMCALL hdr; 1081 /** UInt32: Context ID. */ 1082 HGCMFunctionParameter context; 1083 }; 1084 1085 HGCMMsgSkip Msg; 1086 VBGL_HGCM_HDR_INIT(&Msg.hdr, pHostCtx->uClientID, GUEST_MSG_WAIT, pHostCtx->uNumParms); 1087 Msg.context.SetUInt32(0); 1088 1089 /* Retrieve the context ID of the message which is not supported and put it in pHostCtx. */ 1090 int rc2 = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 1091 if (RT_SUCCESS(rc2)) 1092 Msg.context.GetUInt32(&pHostCtx->uContextID); 1093 1094 /* Now fake a reply to the message. */ 1095 rc2 = VbglR3GuestCtrlMsgReply(pHostCtx, VERR_NOT_SUPPORTED); 1096 AssertRC(rc2); 1097 1098 /* !!! !!! 1099 * !!! HACK ALERT END !!! 1100 * !!! !!! */ 1101 1102 /* Tell the host service to skip the message. */ 1103 VbglR3GuestCtrlMsgSkipOld(pHostCtx->uClientID); 1104 1105 rc = VINF_SUCCESS; 1106 } 1107 /* Note: Other replies must be reported to the host service by the appropriate command handlers above. */ 1228 if (VbglR3GuestCtrlSupportsOptimizations(pHostCtx->uClientID)) 1229 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, VERR_NOT_SUPPORTED, uMsg); 1230 else 1231 { 1232 /* 1233 * !!! HACK ALERT BEGIN !!! 1234 * As peeking for the current message by VbglR3GuestCtrlMsgWaitFor() / GUEST_MSG_WAIT only gives us the message type and 1235 * the number of parameters, but *not* the actual context ID the message is bound to, try to retrieve it here. 1236 * 1237 * This is needed in order to reply to the host with the current context ID, without breaking existing clients. 1238 * Not doing this isn't fatal, but will make host clients wait longer (timing out) for not implemented messages. */ 1239 /** @todo Get rid of this as soon as we have a protocol bump (v4). */ 1240 struct HGCMMsgSkip 1241 { 1242 VBGLIOCHGCMCALL hdr; 1243 /** UInt32: Context ID. */ 1244 HGCMFunctionParameter context; 1245 }; 1246 1247 HGCMMsgSkip Msg; 1248 VBGL_HGCM_HDR_INIT(&Msg.hdr, pHostCtx->uClientID, GUEST_MSG_WAIT, pHostCtx->uNumParms); 1249 Msg.context.SetUInt32(0); 1250 1251 /* Retrieve the context ID of the message which is not supported and put it in pHostCtx. */ 1252 int rc2 = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 1253 if (RT_SUCCESS(rc2)) 1254 Msg.context.GetUInt32(&pHostCtx->uContextID); 1255 1256 /* Now fake a reply to the message. */ 1257 rc2 = VbglR3GuestCtrlMsgReply(pHostCtx, VERR_NOT_SUPPORTED); 1258 AssertRC(rc2); 1259 1260 /* !!! !!! 1261 * !!! HACK ALERT END !!! 1262 * !!! !!! */ 1263 1264 /* Tell the host service to skip the message. */ 1265 VbglR3GuestCtrlMsgSkipOld(pHostCtx->uClientID); 1266 1267 rc = VINF_SUCCESS; 1268 } 1269 } 1108 1270 1109 1271 if (RT_FAILURE(rc)) … … 1403 1565 /* 1404 1566 * Allocate a scratch buffer for commands which also send payload data with them. 1567 * This buffer may grow if the host sends us larger chunks of data. 1405 1568 */ 1406 /** @todo Make buffer size configurable via guest properties/argv! */1407 1569 uint32_t cbScratchBuf = _64K; 1408 Assert(RT_IS_POWER_OF_TWO(cbScratchBuf)); /** @todo r=bird: No idea why this needs to be the case... */ 1409 uint8_t *pvScratchBuf = (uint8_t *)RTMemAlloc(cbScratchBuf); 1570 void *pvScratchBuf = RTMemAlloc(cbScratchBuf); 1410 1571 if (pvScratchBuf) 1411 1572 { … … 1418 1579 VGSvcVerbose(3, "Waiting for host msg ...\n"); 1419 1580 uint32_t uMsg = 0; 1420 uint32_t cParms = 0; 1421 rc = VbglR3GuestCtrlMsgPeekWait(idClient, &uMsg, &cParms); 1581 rc = VbglR3GuestCtrlMsgPeekWait(idClient, &uMsg, &CtxHost.uNumParms); 1422 1582 if (RT_SUCCESS(rc)) 1423 1583 { 1424 VGSvcVerbose(4, "Msg=%RU32 (%RU32 parms) retrieved (%Rrc)\n", uMsg, cParms, rc);1584 VGSvcVerbose(4, "Msg=%RU32 (%RU32 parms) retrieved (%Rrc)\n", uMsg, CtxHost.uNumParms, rc); 1425 1585 1426 1586 /* 1427 * Set number of parameters for current host context and pass it on to the session handler.1587 * Pass it on to the session handler. 1428 1588 * Note! Only when handling HOST_SESSION_CLOSE is the rc used. 1429 1589 */ 1430 CtxHost.uNumParms = cParms;1431 1590 bool fShutdown = false; 1432 rc = VGSvcGstCtrlSessionHandler(pSession, uMsg, &CtxHost, pvScratchBuf,cbScratchBuf, &fShutdown);1591 rc = VGSvcGstCtrlSessionHandler(pSession, uMsg, &CtxHost, &pvScratchBuf, &cbScratchBuf, &fShutdown); 1433 1592 if (fShutdown) 1434 1593 break; -
trunk/src/VBox/HostServices/GuestControl/service.cpp
r75806 r75824 62 62 #define LOG_GROUP LOG_GROUP_GUEST_CONTROL 63 63 #include <VBox/HostServices/GuestControlSvc.h> 64 #include <VBox/GuestHost/GuestControl.h> /** @todo r=bird: Why two headers??? */ 64 65 65 66 #include <VBox/log.h> … … 915 916 int clientMsgGet(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 916 917 int clientMsgCancel(uint32_t idClient, uint32_t cParms); 917 int clientMsgSkip(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms );918 int clientMsgSkip(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 918 919 int clientSessionPrepare(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 919 920 int clientSessionCancelPrepared(uint32_t idClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); … … 974 975 pThis->mClientStateMap[idClient] = ClientState(pThis->mpHelpers, idClient); 975 976 } 976 catch (std::bad_alloc )977 catch (std::bad_alloc &) 977 978 { 978 979 return VERR_NO_MEMORY; … … 1417 1418 * @param hCall The call handle for completing it. 1418 1419 * @param cParms Number of parameters. 1419 */ 1420 int GstCtrlService::clientMsgSkip(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms) 1420 * @param paParms The parameters. 1421 */ 1422 int GstCtrlService::clientMsgSkip(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1421 1423 { 1422 1424 /* 1423 1425 * Validate the call. 1424 1426 */ 1425 ASSERT_GUEST_RETURN(cParms == 0, VERR_WRONG_PARAMETER_COUNT); 1427 ASSERT_GUEST_RETURN(cParms <= 2, VERR_WRONG_PARAMETER_COUNT); 1428 1429 int32_t rcSkip = VERR_NOT_SUPPORTED; 1430 if (cParms >= 1) 1431 { 1432 ASSERT_GUEST_RETURN(paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE); 1433 rcSkip = (int32_t)paParms[0].u.uint32; 1434 } 1435 1436 uint32_t idMsg = UINT32_MAX; 1437 if (cParms >= 2) 1438 { 1439 ASSERT_GUEST_RETURN(paParms[1].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE); 1440 idMsg = paParms[1].u.uint32; 1441 } 1426 1442 1427 1443 ClientStateMapIter ItClientState = mClientStateMap.find(idClient); … … 1434 1450 if (!rClientState.mHostCmdList.empty()) 1435 1451 { 1436 int rc = mpHelpers->pfnCallComplete(hCall, VINF_SUCCESS); 1437 if (RT_SUCCESS(rc)) 1438 { 1439 /* 1440 * Remove the command from the queue. 1441 */ 1442 HostCommand *pFirstCmd = *rClientState.mHostCmdList.begin(); 1443 rClientState.mHostCmdList.pop_front(); 1444 1445 /* 1446 * Compose a reply to the host service. 1447 */ 1448 VBOXHGCMSVCPARM aReplyParams[4]; 1449 HGCMSvcSetU32(&aReplyParams[0], pFirstCmd->m_idContext); 1450 HGCMSvcSetU32(&aReplyParams[1], pFirstCmd->mMsgType); 1451 HGCMSvcSetU32(&aReplyParams[2], (uint32_t)VERR_NOT_SUPPORTED); 1452 HGCMSvcSetPv(&aReplyParams[3], NULL, 0); 1453 GstCtrlService::hostCallback(GUEST_MSG_REPLY, RT_ELEMENTS(aReplyParams), aReplyParams); 1454 1455 /* 1456 * Free the command. 1457 */ 1458 pFirstCmd->SaneRelease(); 1459 } 1460 else 1461 LogFunc(("pfnCallComplete -> %Rrc\n", rc)); 1462 return VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */ 1452 HostCommand *pFirstCmd = *rClientState.mHostCmdList.begin(); 1453 if ( pFirstCmd->mMsgType == idMsg 1454 || idMsg == UINT32_MAX) 1455 { 1456 int rc = mpHelpers->pfnCallComplete(hCall, VINF_SUCCESS); 1457 if (RT_SUCCESS(rc)) 1458 { 1459 /* 1460 * Remove the command from the queue. 1461 */ 1462 HostCommand *pFirstCmd = *rClientState.mHostCmdList.begin(); 1463 if (pFirstCmd ) 1464 { 1465 rClientState.mHostCmdList.pop_front(); 1466 1467 /* 1468 * Compose a reply to the host service. 1469 */ 1470 VBOXHGCMSVCPARM aReplyParams[5]; 1471 HGCMSvcSetU32(&aReplyParams[0], pFirstCmd->m_idContext); 1472 switch (pFirstCmd->mMsgType) 1473 { 1474 case HOST_EXEC_CMD: 1475 HGCMSvcSetU32(&aReplyParams[1], 0); /* pid */ 1476 HGCMSvcSetU32(&aReplyParams[2], PROC_STS_ERROR); /* status */ 1477 HGCMSvcSetU32(&aReplyParams[3], rcSkip); /* flags / whatever */ 1478 HGCMSvcSetPv(&aReplyParams[4], NULL, 0); /* data buffer */ 1479 GstCtrlService::hostCallback(GUEST_EXEC_STATUS, 5, aReplyParams); 1480 break; 1481 1482 case HOST_SESSION_CREATE: 1483 HGCMSvcSetU32(&aReplyParams[1], GUEST_SESSION_NOTIFYTYPE_ERROR); /* type */ 1484 HGCMSvcSetU32(&aReplyParams[2], rcSkip); /* result */ 1485 GstCtrlService::hostCallback(GUEST_SESSION_NOTIFY, 3, aReplyParams); 1486 break; 1487 1488 case HOST_EXEC_SET_INPUT: 1489 HGCMSvcSetU32(&aReplyParams[1], pFirstCmd->mParmCount >= 2 ? pFirstCmd->mpParms[1].u.uint32 : 0); 1490 HGCMSvcSetU32(&aReplyParams[2], INPUT_STS_ERROR); /* status */ 1491 HGCMSvcSetU32(&aReplyParams[3], rcSkip); /* flags / whatever */ 1492 HGCMSvcSetU32(&aReplyParams[4], 0); /* bytes consumed */ 1493 GstCtrlService::hostCallback(GUEST_EXEC_INPUT_STATUS, 5, aReplyParams); 1494 break; 1495 1496 case HOST_FILE_OPEN: 1497 HGCMSvcSetU32(&aReplyParams[1], GUEST_FILE_NOTIFYTYPE_OPEN); /* type*/ 1498 HGCMSvcSetU32(&aReplyParams[2], rcSkip); /* rc */ 1499 HGCMSvcSetU32(&aReplyParams[3], VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pFirstCmd->m_idContext)); /* handle */ 1500 GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams); 1501 break; 1502 case HOST_FILE_CLOSE: 1503 HGCMSvcSetU32(&aReplyParams[1], GUEST_FILE_NOTIFYTYPE_ERROR); /* type*/ 1504 HGCMSvcSetU32(&aReplyParams[2], rcSkip); /* rc */ 1505 GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 3, aReplyParams); 1506 break; 1507 case HOST_FILE_READ: 1508 case HOST_FILE_READ_AT: 1509 HGCMSvcSetU32(&aReplyParams[1], GUEST_FILE_NOTIFYTYPE_READ); /* type */ 1510 HGCMSvcSetU32(&aReplyParams[2], rcSkip); /* rc */ 1511 HGCMSvcSetPv(&aReplyParams[3], NULL, 0); /* data buffer */ 1512 GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams); 1513 break; 1514 case HOST_FILE_WRITE: 1515 case HOST_FILE_WRITE_AT: 1516 HGCMSvcSetU32(&aReplyParams[1], GUEST_FILE_NOTIFYTYPE_WRITE); /* type */ 1517 HGCMSvcSetU32(&aReplyParams[2], rcSkip); /* rc */ 1518 HGCMSvcSetU32(&aReplyParams[3], 0); /* bytes written */ 1519 GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams); 1520 break; 1521 case HOST_FILE_SEEK: 1522 HGCMSvcSetU32(&aReplyParams[1], GUEST_FILE_NOTIFYTYPE_SEEK); /* type */ 1523 HGCMSvcSetU32(&aReplyParams[2], rcSkip); /* rc */ 1524 HGCMSvcSetU64(&aReplyParams[3], 0); /* actual */ 1525 GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams); 1526 break; 1527 case HOST_FILE_TELL: 1528 HGCMSvcSetU32(&aReplyParams[1], GUEST_FILE_NOTIFYTYPE_TELL); /* type */ 1529 HGCMSvcSetU32(&aReplyParams[2], rcSkip); /* rc */ 1530 HGCMSvcSetU64(&aReplyParams[3], 0); /* actual */ 1531 GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams); 1532 break; 1533 1534 case HOST_EXEC_GET_OUTPUT: /** @todo This can't be right/work. */ 1535 case HOST_EXEC_TERMINATE: /** @todo This can't be right/work. */ 1536 case HOST_EXEC_WAIT_FOR: /** @todo This can't be right/work. */ 1537 case HOST_PATH_USER_DOCUMENTS: 1538 case HOST_PATH_USER_HOME: 1539 case HOST_PATH_RENAME: 1540 case HOST_DIR_REMOVE: 1541 default: 1542 HGCMSvcSetU32(&aReplyParams[1], pFirstCmd->mMsgType); 1543 HGCMSvcSetU32(&aReplyParams[2], (uint32_t)rcSkip); 1544 HGCMSvcSetPv(&aReplyParams[3], NULL, 0); 1545 GstCtrlService::hostCallback(GUEST_MSG_REPLY, 4, aReplyParams); 1546 break; 1547 } 1548 1549 /* 1550 * Free the command. 1551 */ 1552 pFirstCmd->SaneRelease(); 1553 } 1554 } 1555 else 1556 LogFunc(("pfnCallComplete -> %Rrc\n", rc)); 1557 return VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */ 1558 } 1559 LogFunc(("Warning: GUEST_MSG_SKIP mismatch! Found %u, caller expected %u!\n", pFirstCmd->mMsgType, idMsg)); 1560 return VERR_MISMATCH; 1463 1561 } 1464 1562 return VERR_NOT_FOUND; … … 2018 2116 case GUEST_MSG_SKIP: 2019 2117 LogFlowFunc(("[Client %RU32] GUEST_MSG_SKIP\n", idClient)); 2020 rc = pThis->clientMsgSkip(idClient, hCall, cParms );2118 rc = pThis->clientMsgSkip(idClient, hCall, cParms, paParms); 2021 2119 break; 2022 2120 case GUEST_SESSION_PREPARE:
Note:
See TracChangeset
for help on using the changeset viewer.