Changeset 75807 in vbox
- Timestamp:
- Nov 29, 2018 7:09:21 AM (6 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/VBoxGuestLib.h
r75798 r75807 767 767 VBGLR3DECL(int) VbglR3GuestCtrlConnect(uint32_t *pidClient); 768 768 VBGLR3DECL(int) VbglR3GuestCtrlDisconnect(uint32_t idClient); 769 VBGLR3DECL(bool) VbglR3GuestCtrlSupportsOptimizations(uint32_t idClient); 770 VBGLR3DECL(int) VbglR3GuestCtrlMakeMeMaster(uint32_t idClient); 769 771 VBGLR3DECL(int) VbglR3GuestCtrlMsgFilterSet(uint32_t uClientId, uint32_t uValue, uint32_t uMaskAdd, uint32_t uMaskRemove); 770 772 VBGLR3DECL(int) VbglR3GuestCtrlMsgReply(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc); 771 773 VBGLR3DECL(int) VbglR3GuestCtrlMsgReplyEx(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, uint32_t uType, 772 774 void *pvPayload, uint32_t cbPayload); 775 VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t idClient); 773 776 VBGLR3DECL(int) VbglR3GuestCtrlMsgSkipOld(uint32_t uClientId); 774 777 VBGLR3DECL(int) VbglR3GuestCtrlMsgPeekWait(uint32_t idClient, uint32_t *pidMsg, uint32_t *pcParameters); 775 778 VBGLR3DECL(int) VbglR3GuestCtrlCancelPendingWaits(HGCMCLIENTID idClient); 776 779 /* Guest session handling. */ 780 VBGLR3DECL(int) VbglR3GuestCtrlSessionPrepare(uint32_t idClient, uint32_t idSession, void const *pvKey, uint32_t cbKey); 781 VBGLR3DECL(int) VbglR3GuestCtrlSessionAccept(uint32_t idClient, uint32_t idSession, void const *pvKey, uint32_t cbKey); 782 VBGLR3DECL(int) VbglR3GuestCtrlSessionCancelPrepared(uint32_t idClient, uint32_t idSession); 777 783 VBGLR3DECL(int) VbglR3GuestCtrlSessionClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t fFlags); 778 VBGLR3DECL(int) VbglR3GuestCtrlSessionNotify(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uType, uint32_t uResult);784 VBGLR3DECL(int) VbglR3GuestCtrlSessionNotify(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uType, int32_t iResult); 779 785 VBGLR3DECL(int) VbglR3GuestCtrlSessionGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puProtocol, char *pszUser, uint32_t cbUser, 780 786 char *pszPassword, uint32_t cbPassword, char *pszDomain, uint32_t cbDomain, -
trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibGuestCtrl.cpp
r75804 r75807 83 83 * 84 84 * @returns VBox status code. 85 * @param uClientIdThe client ID returned by VbglR3GuestCtrlConnect().85 * @param idClient The client ID returned by VbglR3GuestCtrlConnect(). 86 86 * @param pidMsg Where to store the message id. 87 87 * @param pcParameters Where to store the number of parameters which will 88 88 * be received in a second call to the host. 89 89 */ 90 static int vbglR3GuestCtrlMsgWaitFor(uint32_t uClientId, uint32_t *pidMsg, uint32_t *pcParameters)90 static int vbglR3GuestCtrlMsgWaitFor(uint32_t idClient, uint32_t *pidMsg, uint32_t *pcParameters) 91 91 { 92 92 AssertPtrReturn(pidMsg, VERR_INVALID_POINTER); … … 94 94 95 95 HGCMMsgCmdWaitFor Msg; 96 VBGL_HGCM_HDR_INIT(&Msg.hdr, uClientId,96 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, 97 97 GUEST_MSG_WAIT, /* Tell the host we want our next command. */ 98 98 2); /* Just peek for the next message! */ … … 275 275 276 276 /** 277 * Checks if the host supports the optimizes message and session functions. 278 * 279 * @returns true / false. 280 * @param idClient The client ID returned by VbglR3GuestCtrlConnect(). 281 * We may need to use this for checking. 282 * @since 6.0 283 */ 284 VBGLR3DECL(bool) VbglR3GuestCtrlSupportsOptimizations(uint32_t idClient) 285 { 286 return vbglR3GuestCtrlSupportsPeekGetCancel(idClient); 287 } 288 289 290 /** 291 * Make us the guest control master client. 292 * 293 * @returns VBox status code. 294 * @param idClient The client ID returned by VbglR3GuestCtrlConnect(). 295 */ 296 VBGLR3DECL(int) VbglR3GuestCtrlMakeMeMaster(uint32_t idClient) 297 { 298 int rc; 299 do 300 { 301 VBGLIOCHGCMCALL Hdr; 302 VBGL_HGCM_HDR_INIT(&Hdr, idClient, GUEST_MAKE_ME_MASTER, 0); 303 rc = VbglR3HGCMCall(&Hdr, sizeof(Hdr)); 304 } while (rc == VERR_INTERRUPTED); 305 return rc; 306 } 307 308 309 310 /** 277 311 * Peeks at the next host message, waiting for one to turn up. 278 312 * … … 299 333 VbglHGCMParmUInt32Set(&Msg.num_parms, 0); 300 334 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 335 LogRel(("VbglR3GuestCtrlMsgPeekWait -> %Rrc\n", rc)); 301 336 if (RT_SUCCESS(rc)) 302 337 { … … 342 377 * 343 378 * @return IPRT status code. 344 * @param uClientIdThe client ID returned by VbglR3GuestCtrlConnect().379 * @param idClient The client ID returned by VbglR3GuestCtrlConnect(). 345 380 * @param uValue The value to filter messages for. 346 381 * @param uMaskAdd Filter mask to add. 347 382 * @param uMaskRemove Filter mask to remove. 348 383 */ 349 VBGLR3DECL(int) VbglR3GuestCtrlMsgFilterSet(uint32_t uClientId, uint32_t uValue, uint32_t uMaskAdd, uint32_t uMaskRemove)384 VBGLR3DECL(int) VbglR3GuestCtrlMsgFilterSet(uint32_t idClient, uint32_t uValue, uint32_t uMaskAdd, uint32_t uMaskRemove) 350 385 { 351 386 HGCMMsgCmdFilterSet Msg; 352 387 353 388 /* Tell the host we want to set a filter. */ 354 VBGL_HGCM_HDR_INIT(&Msg.hdr, uClientId, GUEST_MSG_FILTER_SET, 4);389 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, GUEST_MSG_FILTER_SET, 4); 355 390 VbglHGCMParmUInt32Set(&Msg.value, uValue); 356 391 VbglHGCMParmUInt32Set(&Msg.mask_add, uMaskAdd); … … 387 422 } 388 423 424 /** 425 * Tell the host to skip the current message replying VERR_NOT_SUPPORTED 426 * 427 * @return IPRT status code. 428 * @param idClient The client ID returned by VbglR3GuestCtrlConnect(). 429 */ 430 VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t idClient) 431 { 432 if (vbglR3GuestCtrlSupportsPeekGetCancel(idClient)) 433 { 434 VBGLIOCHGCMCALL Hdr; 435 VBGL_HGCM_HDR_INIT(&Hdr, idClient, GUEST_MSG_SKIP, 0); 436 return VbglR3HGCMCall(&Hdr, sizeof(Hdr)); 437 } 438 439 /* This is generally better than nothing... */ 440 return VbglR3GuestCtrlMsgSkipOld(idClient); 441 } 442 389 443 390 444 /** … … 393 447 * 394 448 * @return IPRT status code. 395 * @param uClientIdThe client ID returned by VbglR3GuestCtrlConnect().396 */ 397 VBGLR3DECL(int) VbglR3GuestCtrlMsgSkipOld(uint32_t uClientId)449 * @param idClient The client ID returned by VbglR3GuestCtrlConnect(). 450 */ 451 VBGLR3DECL(int) VbglR3GuestCtrlMsgSkipOld(uint32_t idClient) 398 452 { 399 453 HGCMMsgCmdSkip Msg; 400 454 401 455 /* Tell the host we want to skip the current assigned command. */ 402 VBGL_HGCM_HDR_INIT(&Msg.hdr, uClientId, GUEST_MSG_SKIP_OLD, 1);456 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, GUEST_MSG_SKIP_OLD, 1); 403 457 VbglHGCMParmUInt32Set(&Msg.flags, 0 /* Flags, unused */); 404 458 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); … … 410 464 * 411 465 * @returns VBox status code. 412 * @param uClientIdThe client ID returned by VbglR3GuestCtrlConnect().413 */ 414 VBGLR3DECL(int) VbglR3GuestCtrlCancelPendingWaits(uint32_t uClientId)466 * @param idClient The client ID returned by VbglR3GuestCtrlConnect(). 467 */ 468 VBGLR3DECL(int) VbglR3GuestCtrlCancelPendingWaits(uint32_t idClient) 415 469 { 416 470 HGCMMsgCancelPendingWaits Msg; 417 VBGL_HGCM_HDR_INIT(&Msg.hdr, uClientId, GUEST_MSG_CANCEL, 0);471 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, GUEST_MSG_CANCEL, 0); 418 472 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 473 } 474 475 476 /** 477 * Prepares a session. 478 * @since 6.0 479 * @sa GUEST_SESSION_PREPARE 480 */ 481 VBGLR3DECL(int) VbglR3GuestCtrlSessionPrepare(uint32_t idClient, uint32_t idSession, void const *pvKey, uint32_t cbKey) 482 { 483 int rc; 484 do 485 { 486 struct 487 { 488 VBGLIOCHGCMCALL Hdr; 489 HGCMFunctionParameter idSession; 490 HGCMFunctionParameter pKey; 491 } Msg; 492 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_SESSION_PREPARE, 2); 493 VbglHGCMParmUInt32Set(&Msg.idSession, idSession); 494 VbglHGCMParmPtrSet(&Msg.pKey, (void *)pvKey, cbKey); 495 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg)); 496 } while (rc == VERR_INTERRUPTED); 497 return rc; 498 } 499 500 501 /** 502 * Accepts a session. 503 * @since 6.0 504 * @sa GUEST_SESSION_ACCEPT 505 */ 506 VBGLR3DECL(int) VbglR3GuestCtrlSessionAccept(uint32_t idClient, uint32_t idSession, void const *pvKey, uint32_t cbKey) 507 { 508 int rc; 509 do 510 { 511 struct 512 { 513 VBGLIOCHGCMCALL Hdr; 514 HGCMFunctionParameter idSession; 515 HGCMFunctionParameter pKey; 516 } Msg; 517 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_SESSION_ACCEPT, 2); 518 VbglHGCMParmUInt32Set(&Msg.idSession, idSession); 519 VbglHGCMParmPtrSet(&Msg.pKey, (void *)pvKey, cbKey); 520 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg)); 521 } while (rc == VERR_INTERRUPTED); 522 return rc; 523 } 524 525 526 /** 527 * Cancels a prepared session. 528 * @since 6.0 529 * @sa GUEST_SESSION_CANCEL_PREPARED 530 */ 531 VBGLR3DECL(int) VbglR3GuestCtrlSessionCancelPrepared(uint32_t idClient, uint32_t idSession) 532 { 533 int rc; 534 do 535 { 536 struct 537 { 538 VBGLIOCHGCMCALL Hdr; 539 HGCMFunctionParameter idSession; 540 } Msg; 541 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_SESSION_CANCEL_PREPARED, 1); 542 VbglHGCMParmUInt32Set(&Msg.idSession, idSession); 543 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg)); 544 } while (rc == VERR_INTERRUPTED); 545 return rc; 419 546 } 420 547 … … 442 569 443 570 444 VBGLR3DECL(int) VbglR3GuestCtrlSessionNotify(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uType, uint32_t uResult)571 VBGLR3DECL(int) VbglR3GuestCtrlSessionNotify(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uType, int32_t iResult) 445 572 { 446 573 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); … … 450 577 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID); 451 578 VbglHGCMParmUInt32Set(&Msg.type, uType); 452 VbglHGCMParmUInt32Set(&Msg.result, uResult);579 VbglHGCMParmUInt32Set(&Msg.result, (uint32_t)iResult); 453 580 454 581 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); … … 497 624 *pidSession = VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(pCtx->uContextID); 498 625 } 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 499 630 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel); 500 631 return rc; … … 725 856 HGCMMsgProcOutput Msg; 726 857 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms); 727 VbglHGCMParmUInt32Set(&Msg.context, 0);858 VbglHGCMParmUInt32Set(&Msg.context, HOST_EXEC_GET_OUTPUT); 728 859 VbglHGCMParmUInt32Set(&Msg.pid, 0); 729 860 VbglHGCMParmUInt32Set(&Msg.handle, 0); -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp
r75803 r75807 77 77 static uint64_t g_idControlSession; 78 78 /** The guest control service client ID. */ 79 static uint32_tg_idControlSvcClient = 0;79 uint32_t g_idControlSvcClient = 0; 80 80 #if 0 /** @todo process limit */ 81 81 /** How many started guest processes are kept into memory for supplying … … 95 95 * are kept in VBOXSERVICECTRLSESSIONTHREAD structures. */ 96 96 VBOXSERVICECTRLSESSION g_Session; 97 /** Copy of VbglR3GuestCtrlSupportsOptimizations().*/ 98 bool g_fControlSupportsOptimizations = true; 97 99 98 100 … … 190 192 AssertRCReturn(rc, rc); 191 193 192 VbglR3GetSessionId(&g_idControlSession); 193 /* The status code is ignored as this information is not available with VBox < 3.2.10. */ 194 194 VbglR3GetSessionId(&g_idControlSession); /* The status code is ignored as this information is not available with VBox < 3.2.10. */ 195 196 RTListInit(&g_lstControlSessionThreads); 197 198 /* 199 * Try connect to the host service and tell it we want to be master (if supported). 200 */ 201 rc = VbglR3GuestCtrlConnect(&g_idControlSvcClient); 195 202 if (RT_SUCCESS(rc)) 196 rc = VbglR3GuestCtrlConnect(&g_idControlSvcClient); 197 if (RT_SUCCESS(rc)) 198 { 199 VGSvcVerbose(3, "Guest control service client ID=%RU32\n", g_idControlSvcClient); 200 201 /* Init session thread list. */ 202 RTListInit(&g_lstControlSessionThreads); 203 { 204 g_fControlSupportsOptimizations = VbglR3GuestCtrlSupportsOptimizations(g_idControlSvcClient); 205 if (g_fControlSupportsOptimizations) 206 rc = VbglR3GuestCtrlMakeMeMaster(g_idControlSvcClient); 207 if (RT_SUCCESS(rc)) 208 { 209 VGSvcVerbose(3, "Guest control service client ID=%RU32%s\n", 210 g_idControlSvcClient, g_fControlSupportsOptimizations ? " w/ optimizations" : ""); 211 return VINF_SUCCESS; 212 } 213 VGSvcError("Failed to become guest control master: %Rrc\n", rc); 214 VbglR3GuestCtrlDisconnect(g_idControlSvcClient); 203 215 } 204 216 else … … 213 225 else 214 226 VGSvcError("Failed to connect to the guest control service! Error: %Rrc\n", rc); 215 RTSemEventMultiDestroy(g_hControlEvent); 216 g_hControlEvent = NIL_RTSEMEVENTMULTI; 217 } 227 } 228 RTSemEventMultiDestroy(g_hControlEvent); 229 g_hControlEvent = NIL_RTSEMEVENTMULTI; 230 g_idControlSvcClient = 0; 218 231 return rc; 219 232 } … … 226 239 { 227 240 /* 228 * Tell the control thread that it can continue 229 * spawning services. 241 * Tell the control thread that it can continue spawning services. 230 242 */ 231 243 RTThreadUserSignal(RTThreadSelf()); … … 239 251 AssertReturn(pvScratchBuf, VERR_NO_MEMORY); 240 252 241 VBGLR3GUESTCTRLCMDCTX ctxHost = { g_idControlSvcClient }; 242 /* Set default protocol version to 1. */ 243 ctxHost.uProtocol = 1; 253 VBGLR3GUESTCTRLCMDCTX ctxHost = { g_idControlSvcClient, 0 /*idContext*/, 2 /*uProtocol*/, 0 /*cParms*/ }; 244 254 245 255 int rc = VINF_SUCCESS; /* (shut up compiler warnings) */ … … 288 298 break; 289 299 300 /* This message is also sent to the child session process (by the host). */ 290 301 case HOST_SESSION_CLOSE: 291 302 rc = vgsvcGstCtrlHandleSessionClose(&ctxHost); … … 293 304 294 305 default: 295 { 296 /* 297 * Protocol v1 did not have support for (dedicated) 298 * guest sessions, so all actions need to be performed 299 * under behalf of VBoxService's main executable. 300 * 301 * The global session object then acts as a host for all 302 * started guest processes which bring all their 303 * credentials with them with the actual guest process 304 * execution call. 305 */ 306 if (ctxHost.uProtocol == 1) 307 rc = VGSvcGstCtrlSessionHandler(&g_Session, idMsg, &ctxHost, pvScratchBuf, cbScratchBuf, pfShutdown); 306 if (VbglR3GuestCtrlSupportsOptimizations(g_idControlSvcClient)) 307 { 308 rc = VbglR3GuestCtrlMsgSkip(g_idControlSvcClient); 309 VGSvcVerbose(1, "Skipped unexpected message idMsg=%RU32 (%s), cParms=%RU32 (rc=%Rrc)\n", 310 idMsg, GstCtrlHostFnName((eHostFn)idMsg), cParms, rc); 311 } 308 312 else 309 313 { 310 /*311 * ... on newer protocols handling all other commands is312 * up to the guest session fork of VBoxService, so just313 * skip all not wanted messages here.314 */315 314 rc = VbglR3GuestCtrlMsgSkipOld(g_idControlSvcClient); 316 VGSvcVerbose(3, "Skipp ingidMsg=%RU32, cParms=%RU32, rc=%Rrc\n", idMsg, cParms, rc);315 VGSvcVerbose(3, "Skipped idMsg=%RU32, cParms=%RU32, rc=%Rrc\n", idMsg, cParms, rc); 317 316 } 318 317 break; 319 }320 318 } 321 319 … … 387 385 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 388 386 387 /* 388 * Retrieve the message parameters. 389 */ 389 390 VBOXSERVICECTRLSESSIONSTARTUPINFO ssInfo = { 0 }; 390 391 int rc = VbglR3GuestCtrlSessionGetOpen(pHostCtx, … … 396 397 if (RT_SUCCESS(rc)) 397 398 { 398 /* The session open call has the protocol version the host 399 * wants to use. So update the current protocol version with the one the 400 * host wants to use in subsequent calls. */ 401 pHostCtx->uProtocol = ssInfo.uProtocol; 402 VGSvcVerbose(3, "Client ID=%RU32 now is using protocol %RU32\n", pHostCtx->uClientID, pHostCtx->uProtocol); 403 404 rc = VGSvcGstCtrlSessionThreadCreate(&g_lstControlSessionThreads, &ssInfo, NULL /* ppSessionThread */); 405 } 406 407 if (RT_FAILURE(rc)) 408 { 409 /* Report back on failure. On success this will be done 410 * by the forked session thread. */ 411 int rc2 = VbglR3GuestCtrlSessionNotify(pHostCtx, GUEST_SESSION_NOTIFYTYPE_ERROR, rc /* uint32_t vs. int */); 412 if (RT_FAILURE(rc2)) 413 VGSvcError("Reporting session error status on open failed with rc=%Rrc\n", rc2); 414 } 415 399 /* 400 * Flat out refuse to work with protocol v1 hosts. 401 */ 402 if (ssInfo.uProtocol == 2) 403 { 404 pHostCtx->uProtocol = ssInfo.uProtocol; 405 VGSvcVerbose(3, "Client ID=%RU32 now is using protocol %RU32\n", pHostCtx->uClientID, pHostCtx->uProtocol); 406 407 /** @todo Someone explain why this code isn't in this file too? v1 support? */ 408 rc = VGSvcGstCtrlSessionThreadCreate(&g_lstControlSessionThreads, &ssInfo, NULL /* ppSessionThread */); 409 /* Report failures to the host (successes are taken care of by the session thread). */ 410 } 411 else 412 { 413 VGSvcError("The host wants to use protocol v%u, we only support v2!\n", ssInfo.uProtocol); 414 rc = VERR_VERSION_MISMATCH; 415 } 416 if (RT_FAILURE(rc)) 417 { 418 int rc2 = VbglR3GuestCtrlSessionNotify(pHostCtx, GUEST_SESSION_NOTIFYTYPE_ERROR, rc); 419 if (RT_FAILURE(rc2)) 420 VGSvcError("Reporting session error status on open failed with rc=%Rrc\n", rc2); 421 } 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 will 427 * not see the notification and be stuck till it times out. 428 */ 429 else 430 { 431 VGSvcError("Error fetching guest session parameters: %Rrc\n", rc); 432 VbglR3GuestCtrlSessionNotify(pHostCtx, GUEST_SESSION_NOTIFYTYPE_ERROR, rc); 433 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID); 434 } 416 435 VGSvcVerbose(3, "Opening a new guest session returned rc=%Rrc\n", rc); 417 436 return rc; -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.h
r70390 r75807 99 99 RTLISTNODE Node; 100 100 /** The sessions's startup info. */ 101 VBOXSERVICECTRLSESSIONSTARTUPINFO 102 StartupInfo; 101 VBOXSERVICECTRLSESSIONSTARTUPINFO StartupInfo; 102 /** Critical section for thread-safe use. */ 103 RTCRITSECT CritSect; 103 104 /** The worker thread. */ 104 105 RTTHREAD Thread; 105 /** Critical section for thread-safe use. */106 RTCRITSECT CritSect;107 106 /** Process handle for forked child. */ 108 107 RTPROCESS hProcess; … … 133 132 RTPIPE hNotificationPipeR; 134 133 #endif 134 /** Pipe for handing the secret key to the session process. */ 135 RTPIPE hKeyPipe; 136 /** Secret key. */ 137 uint8_t abKey[_4K]; 135 138 } VBOXSERVICECTRLSESSIONTHREAD; 136 139 /** Pointer to thread data. */ … … 289 292 extern RTLISTANCHOR g_lstControlSessionThreads; 290 293 extern VBOXSERVICECTRLSESSION g_Session; 294 extern uint32_t g_idControlSvcClient; 295 extern bool g_fControlSupportsOptimizations; 291 296 292 297 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp
r70390 r75807 1460 1460 pProcess->StartupInfo.szCmd, pProcess->uClientID, pProcess->StartupInfo.uFlags); 1461 1461 1462 /* The process thread is not interested in receiving any commands; 1463 * tell the host service. */ 1464 rc = VbglR3GuestCtrlMsgFilterSet(pProcess->uClientID, 0 /* Skip all */, 1465 0 /* Filter mask to add */, 0 /* Filter mask to remove */); 1466 if (RT_FAILURE(rc)) 1467 { 1468 VGSvcError("Unable to set message filter, rc=%Rrc\n", rc); 1469 /* Non-critical. */ 1462 /* Legacy setting: */ 1463 if (!VbglR3GuestCtrlSupportsOptimizations(pProcess->uClientID)) 1464 { 1465 rc = VbglR3GuestCtrlMsgFilterSet(pProcess->uClientID, 0 /* Skip all */, 1466 0 /* Filter mask to add */, 0 /* Filter mask to remove */); 1467 if (RT_FAILURE(rc)) 1468 VGSvcError("Unable to set message filter, rc=%Rrc\n", rc); /* Non-critical. */ 1470 1469 } 1471 1470 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp
r75798 r75807 33 33 #include <iprt/poll.h> 34 34 #include <iprt/process.h> 35 #include <iprt/rand.h> 35 36 36 37 #include "VBoxServiceInternal.h" … … 1115 1116 /** 1116 1117 * Thread main routine for a spawned guest session process. 1118 * 1117 1119 * This thread runs in the main executable to control the spawned session process. 1118 1120 * … … 1127 1129 AssertPtrReturn(pThread, VERR_INVALID_POINTER); 1128 1130 1129 uint32_t uSessionID = pThread->StartupInfo.uSessionID; 1130 1131 uint32_t idClient; 1132 int rc = VbglR3GuestCtrlConnect(&idClient); 1133 if (RT_SUCCESS(rc)) 1134 { 1135 VGSvcVerbose(3, "Session ID=%RU32 thread running, client ID=%RU32\n", uSessionID, idClient); 1136 1137 /* The session thread is not interested in receiving any commands; 1138 * tell the host service. */ 1139 rc = VbglR3GuestCtrlMsgFilterSet(idClient, 0 /* Skip all */, 0 /* Filter mask to add */, 0 /* Filter mask to remove */); 1140 if (RT_FAILURE(rc)) 1141 { 1142 VGSvcError("Unable to set message filter, rc=%Rrc\n", rc); 1143 /* Non-critical. */ 1144 rc = VINF_SUCCESS; 1145 } 1146 } 1147 else 1148 VGSvcError("Error connecting to guest control service, rc=%Rrc\n", rc); 1149 1150 if (RT_FAILURE(rc)) 1151 pThread->fShutdown = true; 1131 uint32_t const idSession = pThread->StartupInfo.uSessionID; 1132 uint32_t const idClient = g_idControlSvcClient; 1133 VGSvcVerbose(3, "Session ID=%RU32 thread running\n", idSession); 1152 1134 1153 1135 /* Let caller know that we're done initializing, regardless of the result. */ … … 1155 1137 AssertRC(rc2); 1156 1138 1157 if (RT_FAILURE(rc))1158 return rc;1159 1160 bool fProcessAlive = true;1161 RTPROCSTATUS ProcessStatus;1162 RT_ZERO(ProcessStatus);1163 1164 int rcWait;1165 uint 32_t uTimeoutsMS = 30 * 1000; /** @todo Make this configurable. Later. */1166 uint64_t u64TimeoutStart= 0;1167 1139 /* 1140 * Wait for the child process to stop or the shutdown flag to be signalled. 1141 */ 1142 RTPROCSTATUS ProcessStatus = { 0, RTPROCEXITREASON_NORMAL }; 1143 bool fProcessAlive = true; 1144 bool fSessionCancelled = VbglR3GuestCtrlSupportsOptimizations(g_idControlSvcClient); 1145 uint32_t cMsShutdownTimeout = 30 * 1000; /** @todo Make this configurable. Later. */ 1146 uint64_t msShutdownStart = 0; 1147 uint64_t const msStart = RTTimeMilliTS(); 1148 size_t offSecretKey = 0; 1149 int rcWait; 1168 1150 for (;;) 1169 1151 { 1152 /* Secret key feeding. */ 1153 if (offSecretKey < sizeof(pThread->abKey)) 1154 { 1155 size_t cbWritten = 0; 1156 rc2 = RTPipeWrite(pThread->hKeyPipe, &pThread->abKey[offSecretKey], sizeof(pThread->abKey) - offSecretKey, &cbWritten); 1157 if (RT_SUCCESS(rc2)) 1158 offSecretKey += cbWritten; 1159 } 1160 1161 /* Poll child process status. */ 1170 1162 rcWait = RTProcWaitNoResume(pThread->hProcess, RTPROCWAIT_FLAGS_NOBLOCK, &ProcessStatus); 1171 1163 if ( rcWait == VINF_SUCCESS … … 1178 1170 ("Got unexpected rc=%Rrc while waiting for session process termination\n", rcWait)); 1179 1171 1172 /* Shutting down? */ 1180 1173 if (ASMAtomicReadBool(&pThread->fShutdown)) 1181 1174 { 1182 if (! u64TimeoutStart)1175 if (!msShutdownStart) 1183 1176 { 1184 1177 VGSvcVerbose(3, "Notifying guest session process (PID=%RU32, session ID=%RU32) ...\n", 1185 pThread->hProcess, uSessionID);1178 pThread->hProcess, idSession); 1186 1179 1187 1180 VBGLR3GUESTCTRLCMDCTX hostCtx = 1188 1181 { 1189 1182 /* .idClient = */ idClient, 1190 /* .idContext = */ VBOX_GUESTCTRL_CONTEXTID_MAKE_SESSION( uSessionID),1183 /* .idContext = */ VBOX_GUESTCTRL_CONTEXTID_MAKE_SESSION(idSession), 1191 1184 /* .uProtocol = */ pThread->StartupInfo.uProtocol, 1192 1185 /* .cParams = */ 2 1193 1186 }; 1194 rc = VbglR3GuestCtrlSessionClose(&hostCtx, 0 /* fFlags */);1195 if (RT_FAILURE(rc ))1187 rc2 = VbglR3GuestCtrlSessionClose(&hostCtx, 0 /* fFlags */); 1188 if (RT_FAILURE(rc2)) 1196 1189 { 1197 1190 VGSvcError("Unable to notify guest session process (PID=%RU32, session ID=%RU32), rc=%Rrc\n", 1198 pThread->hProcess, uSessionID, rc);1199 1200 if (rc == VERR_NOT_SUPPORTED)1191 pThread->hProcess, idSession, rc2); 1192 1193 if (rc2 == VERR_NOT_SUPPORTED) 1201 1194 { 1202 1195 /* Terminate guest session process in case it's not supported by a too old host. */ 1203 rc = RTProcTerminate(pThread->hProcess);1196 rc2 = RTProcTerminate(pThread->hProcess); 1204 1197 VGSvcVerbose(3, "Terminating guest session process (PID=%RU32) ended with rc=%Rrc\n", 1205 pThread->hProcess, rc );1198 pThread->hProcess, rc2); 1206 1199 } 1207 1200 break; 1208 1201 } 1209 1202 1210 VGSvcVerbose(3, "Guest session ID=%RU32 thread was asked to terminate, waiting for session process to exit (%RU32 ms timeout) ...\n",1211 uSessionID, uTimeoutsMS);1212 u64TimeoutStart = RTTimeMilliTS();1203 VGSvcVerbose(3, "Guest session ID=%RU32 thread was asked to terminate, waiting for session process to exit (%RU32 ms timeout) ...\n", 1204 idSession, cMsShutdownTimeout); 1205 msShutdownStart = RTTimeMilliTS(); 1213 1206 continue; /* Don't waste time on waiting. */ 1214 1207 } 1215 if (RTTimeMilliTS() - u64TimeoutStart > uTimeoutsMS)1208 if (RTTimeMilliTS() - msShutdownStart > cMsShutdownTimeout) 1216 1209 { 1217 VGSvcVerbose(3, "Guest session ID=%RU32 process did not shut down within time\n", uSessionID);1210 VGSvcVerbose(3, "Guest session ID=%RU32 process did not shut down within time\n", idSession); 1218 1211 break; 1219 1212 } 1220 1213 } 1221 1214 1215 /* Cancel the prepared session stuff after 30 seconds. */ 1216 if ( !fSessionCancelled 1217 && RTTimeMilliTS() - msStart >= 30000) 1218 { 1219 VbglR3GuestCtrlSessionCancelPrepared(g_idControlSvcClient, idSession); 1220 fSessionCancelled = true; 1221 } 1222 1223 /** @todo r=bird: This 100ms sleep is _extremely_ sucky! */ 1222 1224 RTThreadSleep(100); /* Wait a bit. */ 1223 1225 } 1224 1226 1227 if (!fSessionCancelled) 1228 VbglR3GuestCtrlSessionCancelPrepared(g_idControlSvcClient, idSession); 1229 1225 1230 if (!fProcessAlive) 1226 1231 { 1227 1232 VGSvcVerbose(2, "Guest session process (ID=%RU32) terminated with rc=%Rrc, reason=%d, status=%d\n", 1228 uSessionID, rcWait, ProcessStatus.enmReason, ProcessStatus.iStatus);1233 idSession, rcWait, ProcessStatus.enmReason, ProcessStatus.iStatus); 1229 1234 if (ProcessStatus.iStatus == RTEXITCODE_INIT) 1230 1235 { 1231 VGSvcError("Guest session process (ID=%RU32) failed to initialize. Here some hints:\n", uSessionID);1236 VGSvcError("Guest session process (ID=%RU32) failed to initialize. Here some hints:\n", idSession); 1232 1237 VGSvcError("- Is logging enabled and the output directory is read-only by the guest session user?\n"); 1233 1238 /** @todo Add more here. */ … … 1242 1247 for (int i = 0; i < 3; i++) 1243 1248 { 1244 VGSvcVerbose(2, "Guest session ID=%RU32 process still alive, killing attempt %d/3\n", uSessionID, i + 1);1245 1246 rc = RTProcTerminate(pThread->hProcess);1247 if (RT_SUCCESS(rc ))1249 VGSvcVerbose(2, "Guest session ID=%RU32 process still alive, killing attempt %d/3\n", idSession, i + 1); 1250 1251 rc2 = RTProcTerminate(pThread->hProcess); 1252 if (RT_SUCCESS(rc2)) 1248 1253 break; 1249 1254 /** @todo r=bird: What's the point of sleeping 3 second after the last attempt? */ … … 1251 1256 } 1252 1257 1253 VGSvcVerbose(2, "Guest session ID=%RU32 process termination resulted in rc=%Rrc\n", uSessionID, rc); 1254 1255 uSessionStatus = RT_SUCCESS(rc) ? GUEST_SESSION_NOTIFYTYPE_TOK : GUEST_SESSION_NOTIFYTYPE_TOA; 1258 VGSvcVerbose(2, "Guest session ID=%RU32 process termination resulted in rc=%Rrc\n", idSession, rc2); 1259 uSessionStatus = RT_SUCCESS(rc2) ? GUEST_SESSION_NOTIFYTYPE_TOK : GUEST_SESSION_NOTIFYTYPE_TOA; 1256 1260 } 1257 1261 else if (RT_SUCCESS(rcWait)) … … 1279 1283 else 1280 1284 { 1281 /* If we didn't find the guest process anymore, just assume it 1282 * terminated normally. */ 1285 /* If we didn't find the guest process anymore, just assume it terminated normally. */ 1283 1286 uSessionStatus = GUEST_SESSION_NOTIFYTYPE_TEN; 1284 1287 } 1285 1288 1286 1289 VGSvcVerbose(3, "Guest session ID=%RU32 thread ended with sessionStatus=%RU32, sessionRc=%Rrc\n", 1287 uSessionID, uSessionStatus, uSessionRc); 1288 1289 /* Report final status. */ 1290 idSession, uSessionStatus, uSessionRc); 1291 1292 /* 1293 * Report final status. 1294 */ 1290 1295 Assert(uSessionStatus != GUEST_SESSION_NOTIFYTYPE_UNDEFINED); 1291 VBGLR3GUESTCTRLCMDCTX ctx = { idClient, VBOX_GUESTCTRL_CONTEXTID_MAKE_SESSION( uSessionID) };1296 VBGLR3GUESTCTRLCMDCTX ctx = { idClient, VBOX_GUESTCTRL_CONTEXTID_MAKE_SESSION(idSession) }; 1292 1297 rc2 = VbglR3GuestCtrlSessionNotify(&ctx, uSessionStatus, uSessionRc); 1293 1298 if (RT_FAILURE(rc2)) 1294 VGSvcError("Reporting session ID=%RU32 final status failed with rc=%Rrc\n", uSessionID, rc2); 1295 1296 VbglR3GuestCtrlDisconnect(idClient); 1297 1298 VGSvcVerbose(3, "Session ID=%RU32 thread ended with rc=%Rrc\n", uSessionID, rc); 1299 return rc; 1300 } 1301 1299 VGSvcError("Reporting session ID=%RU32 final status failed with rc=%Rrc\n", idSession, rc2); 1300 1301 VGSvcVerbose(3, "Session ID=%RU32 thread ending\n", idSession); 1302 return VINF_SUCCESS; 1303 } 1304 1305 /** 1306 * Reads the secret key the parent VBoxService instance passed us and pass it 1307 * along as a authentication token to the host service. 1308 * 1309 * For older hosts, this sets up the message filtering. 1310 * 1311 * @returns VBox status code. 1312 * @param idClient The HGCM client ID. 1313 * @param idSession The session ID. 1314 */ 1315 static int vgsvcGstCtrlSessionReadKeyAndAccept(uint32_t idClient, uint32_t idSession) 1316 { 1317 /* 1318 * Read it. 1319 */ 1320 RTHANDLE Handle; 1321 int rc = RTHandleGetStandard(RTHANDLESTD_INPUT, &Handle); 1322 if (RT_SUCCESS(rc)) 1323 { 1324 if (Handle.enmType == RTHANDLETYPE_PIPE) 1325 { 1326 uint8_t abSecretKey[RT_SIZEOFMEMB(VBOXSERVICECTRLSESSIONTHREAD, abKey)]; 1327 rc = RTPipeReadBlocking(Handle.u.hPipe, abSecretKey, sizeof(abSecretKey), NULL); 1328 if (RT_SUCCESS(rc)) 1329 { 1330 VGSvcVerbose(3, "Got secret key from standard input.\n"); 1331 1332 /* 1333 * Do the accepting, if appropriate. 1334 */ 1335 if (g_fControlSupportsOptimizations) 1336 { 1337 rc = VbglR3GuestCtrlSessionAccept(idClient, idSession, abSecretKey, sizeof(abSecretKey)); 1338 if (RT_SUCCESS(rc)) 1339 VGSvcVerbose(3, "Session %u accepted\n"); 1340 else 1341 VGSvcError("Failed to accept session: %Rrc\n", rc); 1342 } 1343 else 1344 { 1345 /* For legacy hosts, we do the filtering thingy. */ 1346 rc = VbglR3GuestCtrlMsgFilterSet(idClient, VBOX_GUESTCTRL_CONTEXTID_MAKE_SESSION(idSession), 1347 VBOX_GUESTCTRL_FILTER_BY_SESSION(idSession), 0); 1348 if (RT_SUCCESS(rc)) 1349 VGSvcVerbose(3, "Session %u filtering successfully enabled\n"); 1350 else 1351 VGSvcError("Failed to set session filter: %Rrc\n", rc); 1352 } 1353 } 1354 else 1355 VGSvcError("Error reading secret key from standard input: %Rrc\n", rc); 1356 } 1357 else 1358 { 1359 VGSvcError("Standard input is not a pipe!\n"); 1360 rc = VERR_INVALID_HANDLE; 1361 } 1362 RTHandleClose(&Handle); 1363 } 1364 else 1365 VGSvcError("RTHandleGetStandard failed on standard input: %Rrc\n", rc); 1366 return rc; 1367 } 1302 1368 1303 1369 /** … … 1320 1386 if (RT_FAILURE(rc)) 1321 1387 return VGSvcError("Error connecting to guest control service, rc=%Rrc\n", rc); 1322 1323 /* 1324 * Set session filter. This prevents the guest control host service from 1325 * sending messages which belong to another session we don't want to handle. 1326 * 1327 * Note! Earlier versions of this code would issue GUEST_SESSION_NOTIFYTYPE_STARTED 1328 * even if this failed, then shutdown after that. Since there was no 1329 * comments explain why, I (bird) assume is was an unintentional glitch. 1330 * 1331 * Note! There was also a fSessionFilter being set on VERR_NOT_SUPPORTED here 1332 * but since it wasn't used, I assume it was just a leftover from some 1333 * earlier workaround for host behaviour/whatever... 1334 */ 1335 /** @todo r=bird: Unless the host is filtering out everything by default, there 1336 * is a ugly race here between the client masking unwanted messages and the host 1337 * pushing more messages to the clients. We could in theory end up with someone 1338 * elses' messages as the first ones. Too late to require a VbglR3GuestCtrlMsgFilterSet 1339 * call by all clients, which is what would've made sense... I guess 1340 * VbglR3GuestCtrlSessionNotify can't be used as a green-light for sending messages 1341 * either. */ 1342 uint32_t uFilterAdd = VBOX_GUESTCTRL_FILTER_BY_SESSION(pSession->StartupInfo.uSessionID); 1343 rc = VbglR3GuestCtrlMsgFilterSet(idClient, 1344 VBOX_GUESTCTRL_CONTEXTID_MAKE_SESSION(pSession->StartupInfo.uSessionID), 1345 uFilterAdd, 0 /* Filter remove */); 1346 VGSvcVerbose(3, "Setting message filterAdd=0x%x returned %Rrc\n", uFilterAdd, rc); 1347 if ( RT_SUCCESS(rc) 1348 || rc == VERR_NOT_SUPPORTED /* No session filter available. Ignore. */ ) 1388 g_fControlSupportsOptimizations = VbglR3GuestCtrlSupportsOptimizations(idClient); 1389 1390 rc = vgsvcGstCtrlSessionReadKeyAndAccept(idClient, pSession->StartupInfo.uSessionID); 1391 if (RT_SUCCESS(rc)) 1349 1392 { 1350 1393 VGSvcVerbose(1, "Using client ID=%RU32\n", idClient); … … 1377 1420 uint32_t cParms = 0; 1378 1421 rc = VbglR3GuestCtrlMsgPeekWait(idClient, &uMsg, &cParms); 1379 if ( RT_SUCCESS(rc) 1380 || rc == VERR_TOO_MUCH_DATA) 1422 if (RT_SUCCESS(rc)) 1381 1423 { 1382 1424 VGSvcVerbose(4, "Msg=%RU32 (%RU32 parms) retrieved (%Rrc)\n", uMsg, cParms, rc); … … 1715 1757 * Creates the process for a guest session. 1716 1758 * 1717 *1718 1759 * @return VBox status code. 1719 1760 * @param pSessionStartupInfo Session startup info. … … 1760 1801 * Start by assembling the argument list. 1761 1802 */ 1762 int rc = VINF_SUCCESS;1763 1803 char szExeName[RTPATH_MAX]; 1764 1804 char *pszExeName = RTProcGetExecutablePath(szExeName, sizeof(szExeName)); 1765 if (pszExeName)1766 { 1767 1768 1769 1770 1771 1772 1805 AssertReturn(pszExeName, VERR_FILENAME_TOO_LONG); 1806 1807 char szParmSessionID[32]; 1808 RTStrPrintf(szParmSessionID, sizeof(szParmSessionID), "--session-id=%RU32", pSessionThread->StartupInfo.uSessionID); 1809 1810 char szParmSessionProto[32]; 1811 RTStrPrintf(szParmSessionProto, sizeof(szParmSessionProto), "--session-proto=%RU32", 1812 pSessionThread->StartupInfo.uProtocol); 1773 1813 #ifdef DEBUG 1774 1775 1776 #endif 1777 1778 1779 1780 1781 1782 1783 1814 char szParmThreadId[32]; 1815 RTStrPrintf(szParmThreadId, sizeof(szParmThreadId), "--thread-id=%RU32", uCtrlSessionThread); 1816 #endif 1817 unsigned idxArg = 0; /* Next index in argument vector. */ 1818 char const *apszArgs[24]; 1819 1820 apszArgs[idxArg++] = pszExeName; 1821 apszArgs[idxArg++] = "guestsession"; 1822 apszArgs[idxArg++] = szParmSessionID; 1823 apszArgs[idxArg++] = szParmSessionProto; 1784 1824 #ifdef DEBUG 1785 apszArgs[idxArg++] = szParmThreadId; 1786 #endif 1787 if (!fAnonymous) /* Do we need to pass a user name? */ 1788 { 1789 apszArgs[idxArg++] = "--user"; 1790 apszArgs[idxArg++] = pSessionThread->StartupInfo.szUser; 1791 1792 if (strlen(pSessionThread->StartupInfo.szDomain)) 1825 apszArgs[idxArg++] = szParmThreadId; 1826 #endif 1827 if (!fAnonymous) /* Do we need to pass a user name? */ 1828 { 1829 apszArgs[idxArg++] = "--user"; 1830 apszArgs[idxArg++] = pSessionThread->StartupInfo.szUser; 1831 1832 if (strlen(pSessionThread->StartupInfo.szDomain)) 1833 { 1834 apszArgs[idxArg++] = "--domain"; 1835 apszArgs[idxArg++] = pSessionThread->StartupInfo.szDomain; 1836 } 1837 } 1838 1839 /* Add same verbose flags as parent process. */ 1840 char szParmVerbose[32]; 1841 if (g_cVerbosity > 0) 1842 { 1843 unsigned cVs = RT_MIN(g_cVerbosity, RT_ELEMENTS(szParmVerbose) - 2); 1844 szParmVerbose[0] = '-'; 1845 memset(&szParmVerbose[1], 'v', cVs); 1846 szParmVerbose[1 + cVs] = '\0'; 1847 apszArgs[idxArg++] = szParmVerbose; 1848 } 1849 1850 /* Add log file handling. Each session will have an own 1851 * log file, naming based on the parent log file. */ 1852 char szParmLogFile[sizeof(g_szLogFile) + 128]; 1853 if (g_szLogFile[0]) 1854 { 1855 const char *pszSuffix = RTPathSuffix(g_szLogFile); 1856 if (!pszSuffix) 1857 pszSuffix = strchr(g_szLogFile, '\0'); 1858 size_t cchBase = pszSuffix - g_szLogFile; 1859 #ifndef DEBUG 1860 RTStrPrintf(szParmLogFile, sizeof(szParmLogFile), "%.*s-%RU32-%s%s", 1861 cchBase, g_szLogFile, pSessionStartupInfo->uSessionID, pSessionStartupInfo->szUser, pszSuffix); 1862 #else 1863 RTStrPrintf(szParmLogFile, sizeof(szParmLogFile), "%.*s-%RU32-%RU32-%s%s", 1864 cchBase, g_szLogFile, pSessionStartupInfo->uSessionID, uCtrlSessionThread, 1865 pSessionStartupInfo->szUser, pszSuffix); 1866 #endif 1867 apszArgs[idxArg++] = "--logfile"; 1868 apszArgs[idxArg++] = szParmLogFile; 1869 } 1870 1871 #ifdef DEBUG 1872 if (g_Session.fFlags & VBOXSERVICECTRLSESSION_FLAG_DUMPSTDOUT) 1873 apszArgs[idxArg++] = "--dump-stdout"; 1874 if (g_Session.fFlags & VBOXSERVICECTRLSESSION_FLAG_DUMPSTDERR) 1875 apszArgs[idxArg++] = "--dump-stderr"; 1876 #endif 1877 apszArgs[idxArg] = NULL; 1878 Assert(idxArg < RT_ELEMENTS(apszArgs)); 1879 1880 if (g_cVerbosity > 3) 1881 { 1882 VGSvcVerbose(4, "Spawning parameters:\n"); 1883 for (idxArg = 0; apszArgs[idxArg]; idxArg++) 1884 VGSvcVerbose(4, "\t%s\n", apszArgs[idxArg]); 1885 } 1886 1887 /* 1888 * Flags. 1889 */ 1890 uint32_t const fProcCreate = RTPROC_FLAGS_PROFILE 1891 #ifdef RT_OS_WINDOWS 1892 | RTPROC_FLAGS_SERVICE 1893 | RTPROC_FLAGS_HIDDEN 1894 #endif 1895 ; 1896 1897 /* 1898 * Configure standard handles. 1899 */ 1900 RTHANDLE hStdIn; 1901 int rc = RTPipeCreate(&hStdIn.u.hPipe, &pSessionThread->hKeyPipe, RTPIPE_C_INHERIT_READ); 1902 if (RT_SUCCESS(rc)) 1903 { 1904 hStdIn.enmType = RTHANDLETYPE_PIPE; 1905 1906 RTHANDLE hStdOutAndErr; 1907 rc = RTFileOpenBitBucket(&hStdOutAndErr.u.hFile, RTFILE_O_WRITE); 1908 if (RT_SUCCESS(rc)) 1909 { 1910 hStdOutAndErr.enmType = RTHANDLETYPE_FILE; 1911 1912 /* 1913 * Windows: If a domain name is given, construct an UPN (User Principle Name) 1914 * with the domain name built-in, e.g. "[email protected]". 1915 */ 1916 const char *pszUser = pSessionThread->StartupInfo.szUser; 1917 #ifdef RT_OS_WINDOWS 1918 char *pszUserUPN = NULL; 1919 if (pSessionThread->StartupInfo.szDomain[0]) 1793 1920 { 1794 apszArgs[idxArg++] = "--domain"; 1795 apszArgs[idxArg++] = pSessionThread->StartupInfo.szDomain; 1921 int cchbUserUPN = RTStrAPrintf(&pszUserUPN, "%s@%s", 1922 pSessionThread->StartupInfo.szUser, 1923 pSessionThread->StartupInfo.szDomain); 1924 if (cchbUserUPN > 0) 1925 { 1926 pszUser = pszUserUPN; 1927 VGSvcVerbose(3, "Using UPN: %s\n", pszUserUPN); 1928 } 1929 else 1930 rc = VERR_NO_STR_MEMORY; 1796 1931 } 1797 }1798 1799 /* Add same verbose flags as parent process. */1800 char szParmVerbose[32];1801 if (g_cVerbosity > 0)1802 {1803 unsigned cVs = RT_MIN(g_cVerbosity, RT_ELEMENTS(szParmVerbose) - 2);1804 szParmVerbose[0] = '-';1805 memset(&szParmVerbose[1], 'v', cVs);1806 szParmVerbose[1 + cVs] = '\0';1807 apszArgs[idxArg++] = szParmVerbose;1808 }1809 1810 /* Add log file handling. Each session will have an own1811 * log file, naming based on the parent log file. */1812 char szParmLogFile[sizeof(g_szLogFile) + 128];1813 if (g_szLogFile[0])1814 {1815 const char *pszSuffix = RTPathSuffix(g_szLogFile);1816 if (!pszSuffix)1817 pszSuffix = strchr(g_szLogFile, '\0');1818 size_t cchBase = pszSuffix - g_szLogFile;1819 #ifndef DEBUG1820 RTStrPrintf(szParmLogFile, sizeof(szParmLogFile), "%.*s-%RU32-%s%s",1821 cchBase, g_szLogFile, pSessionStartupInfo->uSessionID, pSessionStartupInfo->szUser, pszSuffix);1822 #else1823 RTStrPrintf(szParmLogFile, sizeof(szParmLogFile), "%.*s-%RU32-%RU32-%s%s",1824 cchBase, g_szLogFile, pSessionStartupInfo->uSessionID, uCtrlSessionThread,1825 pSessionStartupInfo->szUser, pszSuffix);1826 #endif1827 apszArgs[idxArg++] = "--logfile";1828 apszArgs[idxArg++] = szParmLogFile;1829 }1830 1831 #ifdef DEBUG1832 VGSvcVerbose(4, "Argv building rc=%Rrc, session flags=%x\n", rc, g_Session.fFlags);1833 if (RT_SUCCESS(rc))1834 {1835 if (g_Session.fFlags & VBOXSERVICECTRLSESSION_FLAG_DUMPSTDOUT)1836 apszArgs[idxArg++] = "--dump-stdout";1837 if (g_Session.fFlags & VBOXSERVICECTRLSESSION_FLAG_DUMPSTDERR)1838 apszArgs[idxArg++] = "--dump-stderr";1839 }1840 #endif1841 apszArgs[idxArg] = NULL;1842 Assert(idxArg < RT_ELEMENTS(apszArgs));1843 1844 if (g_cVerbosity > 3)1845 {1846 VGSvcVerbose(4, "Spawning parameters:\n");1847 for (idxArg = 0; apszArgs[idxArg]; idxArg++)1848 VGSvcVerbose(4, "\t%s\n", apszArgs[idxArg]);1849 }1850 1851 /*1852 * Configure standard handles and finally create the process.1853 */1854 uint32_t fProcCreate = RTPROC_FLAGS_PROFILE;1855 #ifdef RT_OS_WINDOWS /* Windows only flags: */1856 fProcCreate |= RTPROC_FLAGS_SERVICE1857 | RTPROC_FLAGS_HIDDEN; /** @todo More flags from startup info? */1858 #endif1859 1860 #if 0 /* Pipe handling not needed (yet). */1861 /* Setup pipes. */1862 rc = GstcntlProcessSetupPipe("|", 0 /*STDIN_FILENO*/,1863 &pSession->StdIn.hChild, &pSession->StdIn.phChild, &pSession->hStdInW);1864 if (RT_SUCCESS(rc))1865 {1866 rc = GstcntlProcessSetupPipe("|", 1 /*STDOUT_FILENO*/,1867 &pSession->StdOut.hChild, &pSession->StdOut.phChild, &pSession->hStdOutR);1868 1932 if (RT_SUCCESS(rc)) 1933 #endif 1869 1934 { 1870 rc = GstcntlProcessSetupPipe("|", 2 /*STDERR_FILENO*/, 1871 &pSession->StdErr.hChild, &pSession->StdErr.phChild, &pSession->hStdErrR); 1872 if (RT_SUCCESS(rc)) 1873 { 1874 rc = RTPollSetCreate(&pSession->hPollSet); 1875 if (RT_SUCCESS(rc)) 1876 rc = RTPollSetAddPipe(pSession->hPollSet, pSession->hStdInW, RTPOLL_EVT_ERROR, 1877 VBOXSERVICECTRLPIPEID_STDIN); 1878 if (RT_SUCCESS(rc)) 1879 rc = RTPollSetAddPipe(pSession->hPollSet, pSession->hStdOutR, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, 1880 VBOXSERVICECTRLPIPEID_STDOUT); 1881 if (RT_SUCCESS(rc)) 1882 rc = RTPollSetAddPipe(pSession->hPollSet, pSession->hStdErrR, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, 1883 VBOXSERVICECTRLPIPEID_STDERR); 1884 } 1885 1886 if (RT_SUCCESS(rc)) 1887 rc = RTProcCreateEx(pszExeName, apszArgs, hEnv, fProcCreate, 1888 pSession->StdIn.phChild, pSession->StdOut.phChild, pSession->StdErr.phChild, 1889 !fAnonymous ? pSession->StartupInfo.szUser : NULL, 1890 !fAnonymous ? pSession->StartupInfo.szPassword : NULL, 1891 &pSession->hProcess); 1892 1893 if (RT_SUCCESS(rc)) 1894 { 1895 /* 1896 * Close the child ends of any pipes and redirected files. 1897 */ 1898 int rc2 = RTHandleClose(pSession->StdIn.phChild); AssertRC(rc2); 1899 pSession->StdIn.phChild = NULL; 1900 rc2 = RTHandleClose(pSession->StdOut.phChild); AssertRC(rc2); 1901 pSession->StdOut.phChild = NULL; 1902 rc2 = RTHandleClose(pSession->StdErr.phChild); AssertRC(rc2); 1903 pSession->StdErr.phChild = NULL; 1904 } 1935 /* 1936 * Finally, create the process. 1937 */ 1938 rc = RTProcCreateEx(pszExeName, apszArgs, RTENV_DEFAULT, fProcCreate, 1939 &hStdIn, &hStdOutAndErr, &hStdOutAndErr, 1940 !fAnonymous ? pszUser : NULL, 1941 !fAnonymous ? pSessionThread->StartupInfo.szPassword : NULL, 1942 &pSessionThread->hProcess); 1905 1943 } 1906 } 1907 #else 1908 if (RT_SUCCESS(rc)) 1909 { 1910 RTHANDLE hStdIn; 1911 rc = RTFileOpenBitBucket(&hStdIn.u.hFile, RTFILE_O_READ); 1912 if (RT_SUCCESS(rc)) 1913 { 1914 hStdIn.enmType = RTHANDLETYPE_FILE; 1915 1916 RTHANDLE hStdOutAndErr; 1917 rc = RTFileOpenBitBucket(&hStdOutAndErr.u.hFile, RTFILE_O_WRITE); 1918 if (RT_SUCCESS(rc)) 1919 { 1920 hStdOutAndErr.enmType = RTHANDLETYPE_FILE; 1921 1922 const char *pszUser = pSessionThread->StartupInfo.szUser; 1923 # ifdef RT_OS_WINDOWS 1924 /* If a domain name is given, construct an UPN (User Principle Name) with 1925 * the domain name built-in, e.g. "[email protected]". */ 1926 char *pszUserUPN = NULL; 1927 if (strlen(pSessionThread->StartupInfo.szDomain)) 1928 { 1929 int cbUserUPN = RTStrAPrintf(&pszUserUPN, "%s@%s", 1930 pSessionThread->StartupInfo.szUser, 1931 pSessionThread->StartupInfo.szDomain); 1932 if (cbUserUPN > 0) 1933 { 1934 pszUser = pszUserUPN; 1935 VGSvcVerbose(3, "Using UPN: %s\n", pszUserUPN); 1936 } 1937 } 1938 # endif 1939 1940 rc = RTProcCreateEx(pszExeName, apszArgs, RTENV_DEFAULT, fProcCreate, 1941 &hStdIn, &hStdOutAndErr, &hStdOutAndErr, 1942 !fAnonymous ? pszUser : NULL, 1943 !fAnonymous ? pSessionThread->StartupInfo.szPassword : NULL, 1944 &pSessionThread->hProcess); 1945 # ifdef RT_OS_WINDOWS 1946 if (pszUserUPN) 1947 RTStrFree(pszUserUPN); 1948 # endif 1949 RTFileClose(hStdOutAndErr.u.hFile); 1950 } 1951 1952 RTFileClose(hStdIn.u.hFile); 1953 } 1954 } 1955 #endif 1956 } 1957 else 1958 rc = VERR_FILE_NOT_FOUND; 1944 #ifdef RT_OS_WINDOWS 1945 RTStrFree(pszUserUPN); 1946 #endif 1947 RTFileClose(hStdOutAndErr.u.hFile); 1948 } 1949 1950 RTPipeClose(hStdIn.u.hPipe); 1951 } 1959 1952 return rc; 1960 1953 } … … 1992 1985 } 1993 1986 #endif 1994 int rc = VINF_SUCCESS;1995 1987 1996 1988 /* Static counter to help tracking session thread <-> process relations. */ 1997 1989 static uint32_t s_uCtrlSessionThread = 0; 1990 #if 1 1991 if (++s_uCtrlSessionThread == 100000) 1992 #else /* This must be some joke, right? ;-) */ 1998 1993 if (s_uCtrlSessionThread++ == UINT32_MAX) 1994 #endif 1999 1995 s_uCtrlSessionThread = 0; /* Wrap around to not let IPRT freak out. */ 2000 1996 … … 2002 1998 * Allocate and initialize the session thread structure. 2003 1999 */ 2000 int rc; 2004 2001 PVBOXSERVICECTRLSESSIONTHREAD pSessionThread = (PVBOXSERVICECTRLSESSIONTHREAD)RTMemAllocZ(sizeof(*pSessionThread)); 2005 2002 if (pSessionThread) 2006 2003 { 2004 //pSessionThread->fShutdown = false; 2005 //pSessionThread->fStarted = false; 2006 //pSessionThread->fStopped = false; 2007 pSessionThread->hKeyPipe = NIL_RTPIPE; 2008 pSessionThread->Thread = NIL_RTTHREAD; 2009 pSessionThread->hProcess = NIL_RTPROCESS; 2010 2007 2011 /* Copy over session startup info. */ 2008 2012 memcpy(&pSessionThread->StartupInfo, pSessionStartupInfo, sizeof(VBOXSERVICECTRLSESSIONSTARTUPINFO)); 2009 2013 2010 pSessionThread->fShutdown = false; 2011 pSessionThread->fStarted = false; 2012 pSessionThread->fStopped = false; 2014 /* Generate the secret key. */ 2015 RTRandBytes(pSessionThread->abKey, sizeof(pSessionThread->abKey)); 2013 2016 2014 2017 rc = RTCritSectInit(&pSessionThread->CritSect); … … 2017 2020 { 2018 2021 /* 2019 * Start the session thread.2022 * Give the session key to the host so it can validate the client. 2020 2023 */ 2021 rc = vgsvcVGSvcGstCtrlSessionThreadCreateProcess(pSessionStartupInfo, pSessionThread, s_uCtrlSessionThread); 2024 if (VbglR3GuestCtrlSupportsOptimizations(g_idControlSvcClient)) 2025 { 2026 for (uint32_t i = 0; i < 10; i++) 2027 { 2028 rc = VbglR3GuestCtrlSessionPrepare(g_idControlSvcClient, pSessionStartupInfo->uSessionID, 2029 pSessionThread->abKey, sizeof(pSessionThread->abKey)); 2030 if (rc != VERR_OUT_OF_RESOURCES) 2031 break; 2032 RTThreadSleep(100); 2033 } 2034 } 2022 2035 if (RT_SUCCESS(rc)) 2023 2036 { 2024 2037 /* 2025 * Start the session thread.2038 * Start the session child process. 2026 2039 */ 2027 rc = RTThreadCreateF(&pSessionThread->Thread, vgsvcGstCtrlSessionThread, 2028 pSessionThread /*pvUser*/, 0 /*cbStack*/, 2029 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "sess%u", s_uCtrlSessionThread); 2040 rc = vgsvcVGSvcGstCtrlSessionThreadCreateProcess(pSessionStartupInfo, pSessionThread, s_uCtrlSessionThread); 2030 2041 if (RT_SUCCESS(rc)) 2031 2042 { 2032 /* Wait for the thread to initialize. */ 2033 rc = RTThreadUserWait(pSessionThread->Thread, RT_MS_1MIN); 2034 if ( RT_SUCCESS(rc) 2035 && !ASMAtomicReadBool(&pSessionThread->fShutdown)) 2043 /* 2044 * Start the session thread. 2045 */ 2046 rc = RTThreadCreateF(&pSessionThread->Thread, vgsvcGstCtrlSessionThread, pSessionThread /*pvUser*/, 0 /*cbStack*/, 2047 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "CtrlSess%u", s_uCtrlSessionThread); 2048 if (RT_SUCCESS(rc)) 2036 2049 { 2037 VGSvcVerbose(2, "Thread for session ID=%RU32 started\n", pSessionThread->StartupInfo.uSessionID); 2038 2039 ASMAtomicXchgBool(&pSessionThread->fStarted, true); 2040 2041 /* Add session to list. */ 2042 RTListAppend(pList, &pSessionThread->Node); 2043 if (ppSessionThread) /* Return session if wanted. */ 2044 *ppSessionThread = pSessionThread; 2045 return VINF_SUCCESS; 2050 /* Wait for the thread to initialize. */ 2051 rc = RTThreadUserWait(pSessionThread->Thread, RT_MS_1MIN); 2052 if ( RT_SUCCESS(rc) 2053 && !ASMAtomicReadBool(&pSessionThread->fShutdown)) 2054 { 2055 VGSvcVerbose(2, "Thread for session ID=%RU32 started\n", pSessionThread->StartupInfo.uSessionID); 2056 2057 ASMAtomicXchgBool(&pSessionThread->fStarted, true); 2058 2059 /* Add session to list. */ 2060 RTListAppend(pList, &pSessionThread->Node); 2061 if (ppSessionThread) /* Return session if wanted. */ 2062 *ppSessionThread = pSessionThread; 2063 return VINF_SUCCESS; 2064 } 2065 2066 /* 2067 * Bail out. 2068 */ 2069 VGSvcError("Thread for session ID=%RU32 failed to start, rc=%Rrc\n", 2070 pSessionThread->StartupInfo.uSessionID, rc); 2071 if (RT_SUCCESS_NP(rc)) 2072 rc = VERR_CANT_CREATE; /** @todo Find a better rc. */ 2046 2073 } 2047 2048 /* 2049 * Bail out. 2050 */ 2051 VGSvcError("Thread for session ID=%RU32 failed to start, rc=%Rrc\n", 2052 pSessionThread->StartupInfo.uSessionID, rc); 2053 if (RT_SUCCESS_NP(rc)) 2054 rc = VERR_CANT_CREATE; /** @todo Find a better rc. */ 2074 else 2075 VGSvcError("Creating session thread failed, rc=%Rrc\n", rc); 2076 2077 RTProcTerminate(pSessionThread->hProcess); 2078 uint32_t cMsWait = 1; 2079 while ( RTProcWait(pSessionThread->hProcess, RTPROCWAIT_FLAGS_NOBLOCK, NULL) == VERR_PROCESS_RUNNING 2080 && cMsWait <= 9) /* 1023 ms */ 2081 { 2082 RTThreadSleep(cMsWait); 2083 cMsWait <<= 1; 2084 } 2055 2085 } 2056 else 2057 VGSvcError("Creating session thread failed, rc=%Rrc\n", rc); 2058 2059 RTProcTerminate(pSessionThread->hProcess); 2060 uint32_t cMsWait = 1; 2061 while ( RTProcWait(pSessionThread->hProcess, RTPROCWAIT_FLAGS_NOBLOCK, NULL) == VERR_PROCESS_RUNNING 2062 && cMsWait <= 9) /* 1023 ms */ 2063 { 2064 RTThreadSleep(cMsWait); 2065 cMsWait <<= 1; 2066 } 2086 2087 if (VbglR3GuestCtrlSupportsOptimizations(g_idControlSvcClient)) 2088 VbglR3GuestCtrlSessionCancelPrepared(g_idControlSvcClient, pSessionStartupInfo->uSessionID); 2067 2089 } 2090 else 2091 VGSvcVerbose(3, "VbglR3GuestCtrlSessionPrepare failed: %Rrc\n", rc); 2092 RTPipeClose(pSessionThread->hKeyPipe); 2093 pSessionThread->hKeyPipe = NIL_RTPIPE; 2068 2094 RTCritSectDelete(&pSessionThread->CritSect); 2069 2095 }
Note:
See TracChangeset
for help on using the changeset viewer.