Changeset 75755 in vbox
- Timestamp:
- Nov 27, 2018 1:36:00 AM (6 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
-
include/VBox/HostServices/GuestControlSvc.h (modified) (3 diffs)
-
src/VBox/HostServices/GuestControl/service.cpp (modified) (28 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/HostServices/GuestControlSvc.h
r71364 r75755 221 221 * when used in the first capacity. 222 222 * 223 * @todo r=bird: Next time this interface gets a major adjustment, please split 224 * this function up into two calls and, for heavens sake, make them return 225 * VINF_SUCCESS on success. 223 * @note Has a problem if the guest kernel module cancels the HGCM call, as the 224 * guest cannot resume waiting till the host issues a message for it and 225 * the cancelled call returns. The new message may potentially end up in 226 * /dev/null depending and hang the message conversation between the guest 227 * and the host (SIGCHLD). 228 * 229 * @deprecated Replaced by GUEST_MSG_PEEK_WAIT, GUEST_MSG_GET and 230 * GUEST_MSG_CANCEL. 226 231 */ 227 232 GUEST_MSG_WAIT = 1, … … 263 268 */ 264 269 GUEST_MSG_PROGRESS_UPDATE = 12, 270 271 /** Peeks at the next message, returning immediately. 272 * 273 * Returns two 32-bit parameters, first is the message ID and the second the 274 * parameter count. May optionally return additional 32-bit parameters with the 275 * sizes of respective message parameters. To distinguish buffer sizes from 276 * integer parameters, the latter gets their sizes inverted (uint32_t is ~4U, 277 * uint64_t is ~8U). 278 * 279 * @retval VINF_SUCCESS if a message was pending and is being returned. 280 * @retval VERR_TRY_AGAIN if no message pending. 281 * @retval VERR_INVALID_HANDLE if invalid client ID. 282 * @retval VERR_INVALID_PARAMETER if incorrect parameter count or types. 283 * @since 6.0 284 */ 285 GUEST_MSG_PEEK_NOWAIT, 286 /** Peeks at the next message, waiting for one to arrive. 287 * 288 * Returns two 32-bit parameters, first is the message ID and the second the 289 * parameter count. May optionally return additional 32-bit parameters with the 290 * sizes of respective message parameters. To distinguish buffer sizes from 291 * integer parameters, the latter gets their sizes inverted (uint32_t is ~4U, 292 * uint64_t is ~8U). 293 * 294 * @retval VINF_SUCCESS if info about an pending message is being returned. 295 * @retval VINF_TRY_AGAIN and message set to HOST_CANCEL_PENDING_WAITS if 296 * cancelled by GUEST_MSG_CANCEL or GUEST_CANCEL_PENDING_WAITS. 297 * @retval VERR_RESOURCE_BUSY if another thread already made a waiting call. 298 * @retval VERR_INVALID_HANDLE if invalid client ID. 299 * @retval VERR_INVALID_PARAMETER if incorrect parameter count or types. 300 * @note This replaces GUEST_MSG_WAIT. 301 * @since 6.0 302 */ 303 GUEST_MSG_PEEK_WAIT, 304 /** Gets the next message, returning immediately. 305 * 306 * First argument is the message ID returned by the peek and which the caller 307 * expects to retrieve (holds actual message ID when VERR_MISMATCH is returned). 308 * Second argument is the parameter count (output only) and exist for 309 * compatibility with GUEST_MSG_WAIT. Any subsequent parameters are specific to 310 * the message being retrieved. 311 * 312 * @retval VINF_SUCCESS if message retrieved and removed from the pending queue. 313 * @retval VERR_TRY_AGAIN if no message pending. 314 * @retval VERR_MISMATCH if the incoming message ID does not match the pending. 315 * @retval VERR_OUT_OF_RANGE if the wrong parameter count. 316 * @retval VERR_WRONG_TYPE if a parameter has the wrong type. 317 * @retval VERR_BUFFER_OVERFLOW if a parmeter buffer is too small. The buffer 318 * size was updated to reflect the required size. 319 * @retval VERR_INVALID_HANDLE if invalid client ID. 320 * @note This replaces GUEST_MSG_WAIT. 321 * @since 6.0 322 */ 323 GUEST_MSG_GET, 324 /** Cancels pending calls for this client session. 325 * 326 * This should be used if a GUEST_MSG_PEEK_WAIT or GUEST_MSG_WAIT call gets 327 * interrupted on the client end, so as to prevent being rebuffed with 328 * VERR_RESOURCE_BUSY when restarting the call. 329 * 330 * @retval VINF_SUCCESS if cancelled any calls. 331 * @retval VWRN_NOT_FOUND if no callers. 332 * @retval VERR_INVALID_PARAMETER if any parameters specified (expects zero). 333 * @retval VERR_INVALID_HANDLE if invalid client ID. 334 * @since 6.0 335 */ 336 GUEST_MSG_CANCEL, 337 265 338 /** 266 339 * Guest reports back a guest session status. … … 271 344 */ 272 345 GUEST_SESSION_CLOSE = 21, 346 273 347 /** 274 348 * Guests sends output from an executed process. -
trunk/src/VBox/HostServices/GuestControl/service.cpp
r75750 r75755 67 67 68 68 #include <VBox/log.h> 69 #include <VBox/AssertGuest.h> 69 70 #include <iprt/assert.h> 70 71 #include <iprt/cpp/autores.h> … … 472 473 mHostCmdRc(VINF_SUCCESS), mHostCmdTries(0), 473 474 mHostCmdTS(0), 474 mIsPending(false), 475 mPeekCount(0) { } 475 mIsPending((guestControl::eGuestFn)0), 476 mPeekCount(0) 477 { } 476 478 477 479 ClientState(PVBOXHGCMSVCHELPERS pSvcHelpers, uint32_t uClientID) … … 482 484 mHostCmdRc(VINF_SUCCESS), mHostCmdTries(0), 483 485 mHostCmdTS(0), 484 mIsPending(false), 485 mPeekCount(0){ } 486 mIsPending((guestControl::eGuestFn)0), 487 mPeekCount(0) 488 { } 486 489 487 490 void DequeueAll(void) … … 541 544 } 542 545 546 #if 0 /* not used by anyone */ 543 547 /** Returns the pointer to the current host command in a client's list. 544 548 * NULL if no current command available. */ … … 550 554 return (*mHostCmdList.begin()); 551 555 } 556 #endif 552 557 553 558 bool WantsHostCommand(const HostCommand *pHostCmd) const … … 587 592 /** 588 593 * Set to indicate that a client call (GUEST_MSG_WAIT) is pending. 589 */ 590 int SetPending(const ClientConnection *pConnection) 594 * 595 * @note Only used by GUEST_MSG_WAIT scenarios. 596 */ 597 int OldSetPending(const ClientConnection *pConnection) 591 598 { 592 599 AssertPtrReturn(pConnection, VERR_INVALID_POINTER); 593 600 594 if (mIsPending )601 if (mIsPending != 0) 595 602 { 596 603 LogFlowFunc(("[Client %RU32] Already is in pending mode\n", mID)); … … 604 611 if (mHostCmdList.empty()) 605 612 { 606 AssertMsg(mIsPending == false, 607 ("Client ID=%RU32 already is pending but tried to receive a new host command\n", mID)); 613 AssertMsg(mIsPending == 0, ("Client ID=%RU32 already is pending but tried to receive a new host command\n", mID)); 608 614 609 615 mPendingCon.mHandle = pConnection->mHandle; … … 611 617 mPendingCon.mParms = pConnection->mParms; 612 618 613 mIsPending = true;619 mIsPending = GUEST_MSG_WAIT; 614 620 615 621 LogFlowFunc(("[Client %RU32] Is now in pending mode\n", mID)); … … 629 635 } 630 636 631 /** Used by Wakeup() and RunCurrent(). */ 632 int Run(ClientConnection const *pConnection, 633 HostCommand *pHostCmd) 637 /** 638 * Used by Wakeup() and OldRunCurrent(). 639 * 640 * @note Only used by GUEST_MSG_WAIT scenarios. 641 */ 642 int OldRun(ClientConnection const *pConnection, 643 HostCommand *pHostCmd) 634 644 { 635 645 AssertPtrReturn(pConnection, VERR_INVALID_POINTER); … … 639 649 mID, pConnection, mHostCmdRc, mHostCmdTries, mPeekCount)); 640 650 641 int rc = mHostCmdRc = SendReply(pConnection, pHostCmd);651 int rc = mHostCmdRc = OldSendReply(pConnection, pHostCmd); 642 652 643 653 LogFlowThisFunc(("[Client %RU32] Processing command %RU32 ended with rc=%Rrc\n", mID, pHostCmd->mMsgType, mHostCmdRc)); … … 699 709 } 700 710 701 int RunCurrent(const ClientConnection *pConnection) 711 /** 712 * @note Only used by GUEST_MSG_WAIT scenarios. 713 */ 714 int OldRunCurrent(const ClientConnection *pConnection) 702 715 { 703 716 AssertPtrReturn(pConnection, VERR_INVALID_POINTER); … … 706 719 if (mHostCmdList.empty()) 707 720 { 708 rc = SetPending(pConnection);721 rc = OldSetPending(pConnection); 709 722 } 710 723 else 711 724 { 712 AssertMsgReturn( !mIsPending,725 AssertMsgReturn(mIsPending == 0, 713 726 ("Client ID=%RU32 still is in pending mode; can't use another connection\n", mID), VERR_INVALID_PARAMETER); 714 727 … … 718 731 AssertPtrReturn(pHostCmd, VERR_INVALID_POINTER); 719 732 720 rc = Run(pConnection, pHostCmd);733 rc = OldRun(pConnection, pHostCmd); 721 734 } 722 735 … … 724 737 } 725 738 726 /** Used by for Service::hostProcessCommand(). */ 739 /** 740 * Used by for Service::hostProcessCommand(). 741 * 742 * @note This wakes up both GUEST_MSG_WAIT and GUEST_MSG_PEEK_WAIT sleepers. 743 */ 727 744 int Wakeup(void) 728 745 { 729 746 int rc = VINF_NO_CHANGE; 730 747 731 if (mIsPending )748 if (mIsPending != 0) 732 749 { 733 750 LogFlowFunc(("[Client %RU32] Waking up ...\n", mID)); … … 744 761 mID, pHostCmd->mMsgType, pHostCmd->mContextID, pHostCmd->mParmCount, pHostCmd->mRefCount)); 745 762 746 rc = Run(&mPendingCon, pHostCmd); 763 if (mIsPending == GUEST_MSG_PEEK_WAIT) 764 { 765 HGCMSvcSetU32(&mPendingCon.mParms[0], pHostCmd->mMsgType); 766 HGCMSvcSetU32(&mPendingCon.mParms[1], pHostCmd->mParmCount); 767 for (uint32_t i = pHostCmd->mParmCount; i >= 2; i--) 768 switch (pHostCmd->mpParms[i].type) 769 { 770 case VBOX_HGCM_SVC_PARM_32BIT: mPendingCon.mParms[i].u.uint32 = ~(uint32_t)sizeof(uint32_t); break; 771 case VBOX_HGCM_SVC_PARM_64BIT: mPendingCon.mParms[i].u.uint32 = ~(uint32_t)sizeof(uint64_t); break; 772 case VBOX_HGCM_SVC_PARM_PTR: mPendingCon.mParms[i].u.uint32 = pHostCmd->mpParms[i].u.pointer.size; break; 773 } 774 775 rc = mSvcHelpers->pfnCallComplete(mPendingCon.mHandle, VINF_SUCCESS); 776 mIsPending = (guestControl::eGuestFn)0; 777 } 778 else if (mIsPending == GUEST_MSG_WAIT) 779 rc = OldRun(&mPendingCon, pHostCmd); 780 else 781 AssertMsgFailed(("mIsPending=%d\n", mIsPending)); 747 782 } 748 783 else … … 755 790 } 756 791 757 int CancelWaiting(int rcPending) 758 { 759 LogFlowFunc(("[Client %RU32] Cancelling waiting with %Rrc, isPending=%RTbool, pendingNumParms=%RU32, flags=%x\n", 760 mID, rcPending, mIsPending, mPendingCon.mNumParms, mFlags)); 792 /** 793 * Used by Service::call() to handle GUEST_CANCEL_PENDING_WAITS. 794 * 795 * @note This cancels both GUEST_MSG_WAIT and GUEST_MSG_PEEK_WAIT sleepers. 796 */ 797 int CancelWaiting() 798 { 799 LogFlowFunc(("[Client %RU32] Cancelling waiting thread, isPending=%d, pendingNumParms=%RU32, flags=%x\n", 800 mID, mIsPending, mPendingCon.mNumParms, mFlags)); 761 801 762 802 int rc; 763 if ( mIsPending 803 if ( mIsPending != 0 764 804 && mPendingCon.mNumParms >= 2) 765 805 { … … 768 808 769 809 AssertPtr(mSvcHelpers); 770 mSvcHelpers->pfnCallComplete(mPendingCon.mHandle, rcPending);771 772 mIsPending = false;810 mSvcHelpers->pfnCallComplete(mPendingCon.mHandle, mIsPending == GUEST_MSG_WAIT ? VINF_SUCCESS : VINF_TRY_AGAIN); 811 812 mIsPending = (guestControl::eGuestFn)0; 773 813 774 814 rc = VINF_SUCCESS; … … 782 822 } 783 823 784 /** Internal worker for Run(). */ 785 int SendReply(ClientConnection const *pConnection, 786 HostCommand *pHostCmd) 824 /** 825 * Internal worker for OldRun(). 826 * @note Only used for GUEST_MSG_WAIT. 827 */ 828 int OldSendReply(ClientConnection const *pConnection, 829 HostCommand *pHostCmd) 787 830 { 788 831 AssertPtrReturn(pConnection, VERR_INVALID_POINTER); … … 797 840 if (mIsPending) 798 841 { 842 Assert(mIsPending == GUEST_MSG_WAIT); 799 843 rc = pHostCmd->Peek(pConnection); 800 844 mPeekCount++; … … 826 870 827 871 /* Reset pending status. */ 828 mIsPending = false;872 mIsPending = (guestControl::eGuestFn)0; 829 873 830 874 /* In any case the client did something, so complete … … 866 910 * @todo r=bird: Where is this set? */ 867 911 uint64_t mHostCmdTS; 868 /** Flag indicating whether a client call (GUEST_MSG_WAIT) currently ispending.912 /** Pending client call (GUEST_MSG_PEEK_WAIT or GUEST_MSG_WAIT), zero if none pending. 869 913 * 870 914 * This means the client waits for a new host command to reply and won't return 871 915 * from the waiting call until a new host command is available. 872 916 */ 873 boolmIsPending;917 guestControl::eGuestFn mIsPending; 874 918 /** Number of times we've peeked at a pending message. 875 919 * … … 1019 1063 int clientConnect(uint32_t u32ClientID, void *pvClient); 1020 1064 int clientDisconnect(uint32_t u32ClientID, void *pvClient); 1065 int clientMsgOldGet(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 1066 int clientMsgPeek(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool fWait); 1021 1067 int clientMsgGet(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 1068 int clientMsgCancel(uint32_t u32ClientID, uint32_t cParms); 1022 1069 int clientMsgFilterSet(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 1023 1070 int clientMsgFilterUnset(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); … … 1150 1197 * @param paParms Array of parameters. 1151 1198 */ 1152 int Service::clientMsg Get(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle,1153 uint32_t cParms, VBOXHGCMSVCPARM paParms[])1199 int Service::clientMsgOldGet(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, 1200 uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1154 1201 { 1155 1202 /* … … 1177 1224 thisCon.mParms = paParms; 1178 1225 1179 return clientState. RunCurrent(&thisCon);1226 return clientState.OldRunCurrent(&thisCon); 1180 1227 } 1228 1229 /** 1230 * Implements GUEST_MSG_PEEK_WAIT and GUEST_MSG_PEEK_NOWAIT. 1231 * 1232 * @returns VBox status code. 1233 * @retval VINF_SUCCESS if a message was pending and is being returned. 1234 * @retval VERR_INVALID_HANDLE if invalid client ID. 1235 * @retval VERR_INVALID_PARAMETER if incorrect parameter count or types. 1236 * @retval VERR_TRY_AGAIN if no message pending and not blocking. 1237 * @retval VERR_RESOURCE_BUSY if another read already made a waiting call. 1238 * @retval VINF_HGCM_ASYNC_EXECUTE if message wait is pending. 1239 * 1240 * @param idClientID The client's ID. 1241 * @param hCall The client's call handle. 1242 * @param cParms Number of parameters. 1243 * @param paParms Array of parameters. 1244 * @param fWait Set if we should wait for a message, clear if to return 1245 * immediately. 1246 */ 1247 int Service::clientMsgPeek(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool fWait) 1248 { 1249 /* 1250 * Validate the request. 1251 */ 1252 ASSERT_GUEST_MSG_RETURN(cParms >= 2, ("cParms=%u!\n", cParms), VERR_INVALID_PARAMETER); 1253 for (uint32_t i = 0; i < cParms; i++) 1254 { 1255 ASSERT_GUEST_MSG_RETURN(paParms[i].type == VBOX_HGCM_SVC_PARM_32BIT, ("#%u type=%u\n", i, paParms[i].type), 1256 VERR_INVALID_PARAMETER); 1257 paParms[i].u.uint32 = 0; 1258 } 1259 1260 ClientStateMapIter itClientState = mClientStateMap.find(idClient); 1261 ASSERT_GUEST_MSG_RETURN(itClientState != mClientStateMap.end(), ("idClient=%RU32\n", idClient), VERR_INVALID_HANDLE); 1262 1263 ClientState &rClientState = itClientState->second; 1264 1265 /* 1266 * Return information about the first command if one is pending in the list. 1267 */ 1268 HostCmdListIter itFirstCmd = rClientState.mHostCmdList.begin(); 1269 if (itFirstCmd != rClientState.mHostCmdList.end()) 1270 { 1271 HostCommand *pFirstCmd = *itFirstCmd; 1272 paParms[0].u.uint32 = pFirstCmd->mMsgType; 1273 paParms[1].u.uint32 = pFirstCmd->mParmCount; 1274 for (uint32_t i = pFirstCmd->mParmCount; i >= 2; i--) 1275 switch (pFirstCmd->mpParms[i].type) 1276 { 1277 case VBOX_HGCM_SVC_PARM_32BIT: paParms[i].u.uint32 = ~(uint32_t)sizeof(uint32_t); break; 1278 case VBOX_HGCM_SVC_PARM_64BIT: paParms[i].u.uint32 = ~(uint32_t)sizeof(uint64_t); break; 1279 case VBOX_HGCM_SVC_PARM_PTR: paParms[i].u.uint32 = pFirstCmd->mpParms[i].u.pointer.size; break; 1280 } 1281 1282 LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_XXXX -> VINF_SUCCESS (idMsg=%u, cParms=%u)\n", 1283 idClient, pFirstCmd->mMsgType, pFirstCmd->mParmCount)); 1284 return VINF_SUCCESS; 1285 } 1286 1287 /* 1288 * If we cannot wait, fail the call. 1289 */ 1290 if (!fWait) 1291 { 1292 LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_NOWAIT -> VERR_TRY_AGAIN\n", idClient)); 1293 return VERR_TRY_AGAIN; 1294 } 1295 1296 /* 1297 * Wait for the host to queue a message for this client. 1298 */ 1299 ASSERT_GUEST_MSG_RETURN(rClientState.mIsPending == 0, ("Already pending! (idClient=%RU32)\n", idClient), VERR_RESOURCE_BUSY); 1300 rClientState.mPendingCon.mHandle = hCall; 1301 rClientState.mPendingCon.mNumParms = cParms; 1302 rClientState.mPendingCon.mParms = paParms; 1303 rClientState.mIsPending = GUEST_MSG_PEEK_WAIT; 1304 LogFlowFunc(("[Client %RU32] Is now in pending mode\n", idClient)); 1305 return VINF_HGCM_ASYNC_EXECUTE; 1306 } 1307 1308 /** 1309 * Implements GUEST_MSG_GET. 1310 * 1311 * @returns VBox status code. 1312 * @retval VINF_SUCCESS if message retrieved and removed from the pending queue. 1313 * @retval VERR_TRY_AGAIN if no message pending. 1314 * @retval VERR_BUFFER_OVERFLOW if a parmeter buffer is too small. The buffer 1315 * size was updated to reflect the required size. 1316 * @retval VERR_MISMATCH if the incoming message ID does not match the pending. 1317 * @retval VERR_OUT_OF_RANGE if the wrong parameter count. 1318 * @retval VERR_WRONG_TYPE if a parameter has the wrong type. 1319 * @retval VERR_INVALID_HANDLE if invalid client ID. 1320 * @retval VINF_HGCM_ASYNC_EXECUTE if message wait is pending. 1321 * 1322 * @param idClientID The client's ID. 1323 * @param hCall The client's call handle. 1324 * @param cParms Number of parameters. 1325 * @param paParms Array of parameters. 1326 */ 1327 int Service::clientMsgGet(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1328 { 1329 /* 1330 * Validate the request. 1331 * 1332 * Note! The 2nd parameter is basically ignored as it's only purpose is 1333 * compatibility with GUEST_MSG_WAIT 1334 */ 1335 ASSERT_GUEST_MSG_RETURN(cParms >= 2, ("cParms=%u!\n", cParms), VERR_INVALID_PARAMETER); 1336 ASSERT_GUEST_MSG_RETURN(paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT, ("type=%u\n", paParms[0].type), VERR_WRONG_TYPE); 1337 uint32_t const idMsgExpected = paParms[0].u.uint32; 1338 ASSERT_GUEST_MSG_RETURN(paParms[1].type == VBOX_HGCM_SVC_PARM_32BIT, ("type=%u\n", paParms[0].type), VERR_WRONG_TYPE); 1339 1340 ClientStateMapIter itClientState = mClientStateMap.find(idClient); 1341 ASSERT_GUEST_MSG_RETURN(itClientState != mClientStateMap.end(), ("idClient=%RU32\n", idClient), VERR_INVALID_HANDLE); 1342 1343 ClientState &rClientState = itClientState->second; 1344 1345 /* 1346 * Return information aobut the first command if one is pending in the list. 1347 */ 1348 HostCmdListIter itFirstCmd = rClientState.mHostCmdList.begin(); 1349 if (itFirstCmd != rClientState.mHostCmdList.end()) 1350 { 1351 HostCommand *pFirstCmd = *itFirstCmd; 1352 1353 /* The 'peek' parameters. */ 1354 paParms[0].u.uint32 = pFirstCmd->mMsgType; 1355 paParms[1].u.uint32 = pFirstCmd->mParmCount; 1356 ASSERT_GUEST_MSG_RETURN(pFirstCmd->mMsgType == idMsgExpected, 1357 ("idMsg=%u cParms=%u, caller expected %u and %u\n", 1358 pFirstCmd->mMsgType, pFirstCmd->mParmCount, idMsgExpected, cParms), 1359 VERR_MISMATCH); 1360 ASSERT_GUEST_MSG_RETURN(pFirstCmd->mParmCount == cParms, 1361 ("idMsg=%u cParms=%u, caller expected %u and %u\n", 1362 pFirstCmd->mMsgType, pFirstCmd->mParmCount, idMsgExpected, cParms), 1363 VERR_OUT_OF_RANGE); 1364 1365 /* Check the parameter types. */ 1366 for (uint32_t i = 2; i < cParms; i++) 1367 ASSERT_GUEST_MSG_RETURN(pFirstCmd->mpParms[i].type == paParms[i].type, 1368 ("param #%u: type %u, caller expected %u\n", i, pFirstCmd->mpParms[i].type, paParms[i].type), 1369 VERR_WRONG_TYPE); 1370 1371 /* 1372 * Copy out the parameters. 1373 * 1374 * No assertions on buffer overflows, and keep going till the end so we can 1375 * communicate all the required buffer sizes. 1376 */ 1377 int rc = VINF_SUCCESS; 1378 for (uint32_t i = 2; i < cParms; i++) 1379 switch (pFirstCmd->mpParms[i].type) 1380 { 1381 case VBOX_HGCM_SVC_PARM_32BIT: 1382 paParms[i].u.uint32 = pFirstCmd->mpParms[i].u.uint32; 1383 break; 1384 1385 case VBOX_HGCM_SVC_PARM_64BIT: 1386 paParms[i].u.uint64 = pFirstCmd->mpParms[i].u.uint64; 1387 break; 1388 1389 case VBOX_HGCM_SVC_PARM_PTR: 1390 { 1391 uint32_t const cbSrc = pFirstCmd->mpParms[i].u.pointer.size; 1392 uint32_t const cbDst = paParms[i].u.pointer.size; 1393 paParms[i].u.pointer.size = cbSrc; /** @todo Check if this is safe in other layers... 1394 * Update: Safe, yes, but VMMDevHGCM doesn't pass it along. */ 1395 if (cbSrc <= cbDst) 1396 memcpy(paParms[i].u.pointer.addr, pFirstCmd->mpParms[i].u.pointer.addr, cbSrc); 1397 else 1398 rc = VERR_BUFFER_OVERFLOW; 1399 break; 1400 } 1401 1402 default: 1403 AssertMsgFailed(("#%u: %u\n", i, pFirstCmd->mpParms[i].type)); 1404 rc = VERR_INTERNAL_ERROR; 1405 break; 1406 } 1407 if (RT_SUCCESS(rc)) 1408 { 1409 /* 1410 * Complete the command and remove the pending message unless the 1411 * guest raced us and cancelled this call in the meantime. 1412 */ 1413 AssertPtr(mpHelpers); 1414 rc = mpHelpers->pfnCallComplete(hCall, rc); 1415 if (rc != VERR_CANCELLED) 1416 { 1417 rClientState.mHostCmdList.erase(itFirstCmd); 1418 if (pFirstCmd->Release() == 0) 1419 { 1420 delete pFirstCmd; 1421 LogFlow(("[Client %RU32] Destroying command (idMsg=%u cParms=%u)\n", idClient, idMsgExpected, cParms)); 1422 } 1423 } 1424 return VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */ 1425 } 1426 return rc; 1427 } 1428 1429 paParms[0].u.uint32 = 0; 1430 paParms[1].u.uint32 = 0; 1431 LogFlowFunc(("[Client %RU32] GUEST_MSG_GET -> VERR_TRY_AGAIN\n", idClient)); 1432 return VERR_TRY_AGAIN; 1433 } 1434 1435 /** 1436 * Implements GUEST_MSG_CANCEL. 1437 * 1438 * @returns VBox status code. 1439 * @retval VINF_SUCCESS if cancelled any calls. 1440 * @retval VWRN_NOT_FOUND if no callers. 1441 * @retval VERR_INVALID_PARAMETER if any parameters specified (expects zero). 1442 * @retval VERR_INVALID_HANDLE if invalid client ID. 1443 * @retval VINF_HGCM_ASYNC_EXECUTE if message wait is pending. 1444 * 1445 * @param idClientID The client's ID. 1446 * @param cParms Number of parameters. 1447 */ 1448 int Service::clientMsgCancel(uint32_t idClient, uint32_t cParms) 1449 { 1450 /* 1451 * Validate the request. 1452 */ 1453 ASSERT_GUEST_MSG_RETURN(cParms == 0, ("cParms=%u!\n", cParms), VERR_INVALID_PARAMETER); 1454 1455 ClientStateMapIter itClientState = mClientStateMap.find(idClient); 1456 ASSERT_GUEST_MSG_RETURN(itClientState != mClientStateMap.end(), ("idClient=%RU32\n", idClient), VERR_INVALID_HANDLE); 1457 1458 ClientState &rClientState = itClientState->second; 1459 if (rClientState.mIsPending != 0) 1460 { 1461 rClientState.CancelWaiting(); 1462 return VINF_SUCCESS; 1463 } 1464 return VWRN_NOT_FOUND; 1465 } 1466 1181 1467 1182 1468 /** … … 1447 1733 if (eFunction == GUEST_MSG_WAIT) 1448 1734 { 1449 LogFlowFunc(("[Client %RU32] GUEST_MSG_ GET\n", u32ClientID));1450 rc = clientMsg Get(u32ClientID, callHandle, cParms, paParms);1735 LogFlowFunc(("[Client %RU32] GUEST_MSG_WAIT\n", u32ClientID)); 1736 rc = clientMsgOldGet(u32ClientID, callHandle, cParms, paParms); 1451 1737 } 1452 1738 else … … 1464 1750 ClientStateMapIter itClientState = mClientStateMap.find(u32ClientID); 1465 1751 if (itClientState != mClientStateMap.end()) 1466 rc = itClientState->second.CancelWaiting( VINF_SUCCESS /* Pending result */);1752 rc = itClientState->second.CancelWaiting(); 1467 1753 break; 1468 1754 } … … 1497 1783 1498 1784 /* 1785 * New message peeking and retrieval functions replacing GUEST_MSG_WAIT. 1786 */ 1787 case GUEST_MSG_PEEK_NOWAIT: 1788 LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_NOWAIT\n", u32ClientID)); 1789 rc = clientMsgPeek(u32ClientID, callHandle, cParms, paParms, false /*fWait*/); 1790 break; 1791 case GUEST_MSG_PEEK_WAIT: 1792 LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_WAIT\n", u32ClientID)); 1793 rc = clientMsgPeek(u32ClientID, callHandle, cParms, paParms, true /*fWait*/); 1794 break; 1795 case GUEST_MSG_GET: 1796 LogFlowFunc(("[Client %RU32] GUEST_MSG_GET\n", u32ClientID)); 1797 rc = clientMsgGet(u32ClientID, callHandle, cParms, paParms); 1798 break; 1799 case GUEST_MSG_CANCEL: 1800 LogFlowFunc(("[Client %RU32] GUEST_MSG_CANCEL\n", u32ClientID)); 1801 rc = clientMsgCancel(u32ClientID, cParms); 1802 break; 1803 1804 /* 1499 1805 * The guest wants to close specific guest session. This is handy for 1500 1806 * shutting down dedicated guest session processes from another process. … … 1552 1858 while (itClientState != mClientStateMap.end()) 1553 1859 { 1554 int rc2 = itClientState->second.CancelWaiting( VINF_SUCCESS /* Pending rc. */);1860 int rc2 = itClientState->second.CancelWaiting(); 1555 1861 if (RT_FAILURE(rc2)) 1556 1862 LogFlowFunc(("Cancelling waiting for client ID=%RU32 failed with rc=%Rrc",
Note:
See TracChangeset
for help on using the changeset viewer.

