Changeset 28286 in vbox for trunk/src/VBox
- Timestamp:
- Apr 14, 2010 10:02:30 AM (15 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibGuestCtrl.cpp
r28233 r28286 147 147 ** @todo Docs! 148 148 */ 149 VBGLR3DECL(int) VbglR3GuestCtrlExecGetHostCmd(uint32_t u32ClientId, uint32_t uNumParms, 150 char *pszCmd, uint32_t cbCmd, 149 VBGLR3DECL(int) VbglR3GuestCtrlExecGetHostCmd(uint32_t u32ClientId, uint32_t uNumParms, 150 uint32_t *puContext, 151 char *pszCmd, uint32_t cbCmd, 151 152 uint32_t *puFlags, 152 char *pszArgs, uint32_t cbArgs,uint32_t *puNumArgs,153 char *pszEnv, uint32_t *pcbEnv,uint32_t *puNumEnvVars,154 char *pszStdIn, uint32_tcbStdIn,155 char *pszStdOut, uint32_tcbStdOut,156 char *pszStdErr, uint32_tcbStdErr,157 char *pszUser, uint32_tcbUser,158 char *pszPassword, uint32_tcbPassword,153 char *pszArgs, uint32_t cbArgs, uint32_t *puNumArgs, 154 char *pszEnv, uint32_t *pcbEnv, uint32_t *puNumEnvVars, 155 char *pszStdIn, uint32_t cbStdIn, 156 char *pszStdOut, uint32_t cbStdOut, 157 char *pszStdErr, uint32_t cbStdErr, 158 char *pszUser, uint32_t cbUser, 159 char *pszPassword, uint32_t cbPassword, 159 160 uint32_t *puTimeLimit) 160 161 { 162 AssertPtr(puContext); 161 163 AssertPtr(pszCmd); 162 164 AssertPtr(puFlags); … … 181 183 Msg.hdr.cParms = uNumParms; 182 184 185 VbglHGCMParmUInt32Set(&Msg.context, 0); /** @todo Put this some header struct! */ 183 186 VbglHGCMParmPtrSet(&Msg.cmd, pszCmd, cbCmd); 184 187 VbglHGCMParmUInt32Set(&Msg.flags, 0); … … 205 208 else 206 209 { 210 Msg.context.GetUInt32(puContext); 207 211 Msg.flags.GetUInt32(puFlags); 208 212 Msg.num_args.GetUInt32(puNumArgs); … … 225 229 */ 226 230 VBGLR3DECL(int) VbglR3GuestCtrlExecReportStatus(uint32_t u32ClientId, 231 uint32_t u32Context, 227 232 uint32_t u32PID, 228 233 uint32_t u32Status, … … 236 241 Msg.hdr.u32ClientID = u32ClientId; 237 242 Msg.hdr.u32Function = GUEST_EXEC_SEND_STATUS; 238 Msg.hdr.cParms = 4; 239 243 Msg.hdr.cParms = 5; 244 245 VbglHGCMParmUInt32Set(&Msg.context, u32Context); 240 246 VbglHGCMParmUInt32Set(&Msg.pid, u32PID); 241 247 VbglHGCMParmUInt32Set(&Msg.status, u32Status); -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp
r28218 r28286 96 96 static int VBoxServiceControlHandleCmdExec(uint32_t u32ClientId, uint32_t uNumParms) 97 97 { 98 uint32_t uContextID; 98 99 char szCmd[_1K]; 99 100 uint32_t uFlags; … … 110 111 uint32_t uTimeLimitMS; 111 112 112 int rc = VbglR3GuestCtrlExecGetHostCmd(u32ClientId, uNumParms, 113 if (uNumParms != 14) 114 return VERR_INVALID_PARAMETER; 115 116 int rc = VbglR3GuestCtrlExecGetHostCmd(u32ClientId, 117 uNumParms, 118 &uContextID, 113 119 /* Command */ 114 120 szCmd, sizeof(szCmd), … … 134 140 else 135 141 { 136 rc = VBoxServiceControlExecProcess( szCmd, uFlags, szArgs, uNumArgs,142 rc = VBoxServiceControlExecProcess(uContextID, szCmd, uFlags, szArgs, uNumArgs, 137 143 szEnv, cbEnv, uNumEnvVars, 138 144 szStdIn, szStdOut, szStdErr, -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp
r28244 r28286 235 235 236 236 237 static int VBoxServiceControlExecProcLoop(uint32_t uClientID, RTPROCESS hProcess, RTMSINTERVAL cMillies, RTPOLLSET hPollSet, 237 static int VBoxServiceControlExecProcLoop(PVBOXSERVICECTRLTHREADDATA pData, 238 RTPROCESS hProcess, RTMSINTERVAL cMillies, RTPOLLSET hPollSet, 238 239 RTPIPE hStdInW, RTPIPE hStdOutR, RTPIPE hStdErrR) 239 240 { … … 256 257 RTMSINTERVAL cMsPollCur = 0; 257 258 259 /* Assign PID to thread data. */ 260 pData->uPID = hProcess; 261 258 262 /* 259 263 * Before entering the loop, tell the host that we've started the guest 260 264 * and that it's now OK to send input to the process. 261 265 */ 262 rc = VbglR3GuestCtrlExecReportStatus(uClientID, hProcess, 263 PROC_STS_STARTED, 0 /* u32Flags */, 266 AssertPtr(pData); 267 rc = VbglR3GuestCtrlExecReportStatus(pData->uClientID, pData->uContextID, 268 pData->uPID, PROC_STS_STARTED, 0 /* u32Flags */, 264 269 NULL /* pvData */, 0 /* cbData */); 265 270 … … 446 451 } 447 452 448 VBoxServiceVerbose(3, "Control: Process ended: Status=%u, Flags=%u\n", uStatus, uFlags); 449 rc = VbglR3GuestCtrlExecReportStatus(uClientID, hProcess, 450 uStatus, uFlags, 453 VBoxServiceVerbose(3, "Control: Process ended: PID=%u, Status=%u, Flags=%u\n", 454 pData->uPID, uStatus, uFlags); 455 rc = VbglR3GuestCtrlExecReportStatus(pData->uClientID, pData->uContextID, 456 pData->uPID, uStatus, uFlags, 451 457 NULL /* pvData */, 0 /* cbData */); 452 458 } … … 509 515 510 516 /** Allocates and gives back a thread data struct which then can be used by the worker thread. */ 511 PVBOXSERVICECTRLTHREADDATA VBoxServiceControlExecAllocateThreadData(const char *pszCmd, uint32_t uFlags, 517 PVBOXSERVICECTRLTHREADDATA VBoxServiceControlExecAllocateThreadData(uint32_t u32ContextID, 518 const char *pszCmd, uint32_t uFlags, 512 519 const char *pszArgs, uint32_t uNumArgs, 513 520 const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars, … … 519 526 return NULL; 520 527 528 /* ClientID will be assigned when thread is started! */ 529 pData->uContextID = u32ContextID; 521 530 pData->pszCmd = RTStrDup(pszCmd); 522 531 pData->uFlags = uFlags; … … 601 610 */ 602 611 RTThreadUserSignal(RTThreadSelf()); 603 VBoxServiceVerbose(3, "Control: Thread of process \"%s\" started.\n", pData->pszCmd); 604 605 uint32_t u32ClientID; 606 int rc = VbglR3GuestCtrlConnect(&u32ClientID); 612 VBoxServiceVerbose(3, "Control: Thread of process \"%s\" started\n", pData->pszCmd); 613 614 int rc = VbglR3GuestCtrlConnect(&pData->uClientID); 607 615 if (RT_FAILURE(rc)) 608 616 { … … 685 693 686 694 /* Enter the process loop. */ 687 rc = VBoxServiceControlExecProcLoop( u32ClientID,695 rc = VBoxServiceControlExecProcLoop(pData, 688 696 hProcess, pData->uTimeLimitMS, hPollSet, 689 697 hStdInW, hStdOutR, hStdErrR); … … 704 712 else /* Something went wrong; report error! */ 705 713 { 706 int rc2 = VbglR3GuestCtrlExecReportStatus( u32ClientID, 0 /* PID */,714 int rc2 = VbglR3GuestCtrlExecReportStatus(pData->uClientID, pData->uContextID, pData->uPID, 707 715 PROC_STS_ERROR, rc, 708 716 NULL /* pvData */, 0 /* cbData */); … … 726 734 } 727 735 728 VbglR3GuestCtrlDisconnect( u32ClientID);736 VbglR3GuestCtrlDisconnect(pData->uClientID); 729 737 VBoxServiceVerbose(3, "Control: Thread of process \"%s\" ended with rc=%Rrc\n", pData->pszCmd, rc); 730 738 … … 743 751 } 744 752 745 int VBoxServiceControlExecProcess( const char *pszCmd, uint32_t uFlags,753 int VBoxServiceControlExecProcess(uint32_t uContextID, const char *pszCmd, uint32_t uFlags, 746 754 const char *pszArgs, uint32_t uNumArgs, 747 755 const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars, … … 750 758 { 751 759 PVBOXSERVICECTRLTHREADDATA pThreadData = 752 VBoxServiceControlExecAllocateThreadData(pszCmd, uFlags, 760 VBoxServiceControlExecAllocateThreadData(uContextID, 761 pszCmd, uFlags, 753 762 pszArgs, uNumArgs, 754 763 pszEnv, cbEnv, uNumEnvVars, -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
r28251 r28286 129 129 typedef struct 130 130 { 131 uint32_t uClientID; 132 uint32_t uContextID; 133 uint32_t uPID; 131 134 char *pszCmd; 132 135 uint32_t uFlags; … … 213 216 214 217 #ifdef VBOX_WITH_GUEST_CONTROL 215 extern int VBoxServiceControlExecProcess( const char *pszCmd, uint32_t uFlags,218 extern int VBoxServiceControlExecProcess(uint32_t uContext, const char *pszCmd, uint32_t uFlags, 216 219 const char *pszArgs, uint32_t uNumArgs, 217 220 const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars, -
trunk/src/VBox/HostServices/GuestControl/service.cpp
r28243 r28286 244 244 int processHostMsg(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 245 245 int notifyGuest(GuestCall *pCall, uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 246 int notifyHost( VBOXHGCMCALLHANDLE callHandle,uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);246 int notifyHost(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 247 247 int processCmd(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 248 248 void call(VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, … … 487 487 } 488 488 489 int Service::notifyHost( VBOXHGCMCALLHANDLE callHandle,uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[])489 int Service::notifyHost(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 490 490 { 491 491 LogFlowFunc(("eFunction=%ld, cParms=%ld, paParms=%p\n", … … 493 493 int rc = VINF_SUCCESS; 494 494 if ( eFunction == GUEST_EXEC_SEND_STATUS 495 && cParms == 4)495 && cParms == 5) 496 496 { 497 497 HOSTEXECCALLBACKDATA data; 498 data.u32Magic = HOSTCALLBACKMAGIC; 499 paParms[0].getUInt32(&data.pid); 500 paParms[1].getUInt32(&data.status); 501 paParms[2].getUInt32(&data.flags); 498 data.hdr.u32Magic = HOSTEXECCALLBACKDATAMAGIC; 499 paParms[0].getUInt32(&data.hdr.u32ContextID); 500 501 paParms[1].getUInt32(&data.u32PID); 502 paParms[2].getUInt32(&data.u32Status); 503 paParms[3].getUInt32(&data.u32Flags); 502 504 paParms[4].getPointer(&data.pvData, &data.cbData); 503 505 … … 576 578 case GUEST_EXEC_SEND_STATUS: 577 579 LogFlowFunc(("SEND_STATUS\n")); 578 rc = notifyHost( callHandle,eFunction, cParms, paParms);580 rc = notifyHost(eFunction, cParms, paParms); 579 581 break; 580 582 -
trunk/src/VBox/Main/ConsoleImpl2.cpp
r28138 r28286 30 30 #include "ConsoleImpl.h" 31 31 #include "DisplayImpl.h" 32 #ifdef VBOX_WITH_GUEST_CONTROL 33 # include "GuestImpl.h" 34 #endif 32 35 #include "VMMDev.h" 33 36 … … 3729 3732 } 3730 3733 else 3731 Log(("VBoxGuestControlSvc loaded\n")); 3732 3733 return VINF_SUCCESS; 3734 { 3735 HGCMSVCEXTHANDLE hDummy; 3736 rc = HGCMHostRegisterServiceExtension(&hDummy, "VBoxGuestControlSvc", 3737 &Guest::doGuestCtrlNotification, 3738 pConsole->getGuest()); 3739 if (RT_FAILURE(rc)) 3740 Log(("Cannot register VBoxGuestControlSvc extension!\n")); 3741 else 3742 Log(("VBoxGuestControlSvc loaded\n")); 3743 } 3744 3745 return rc; 3734 3746 #else /* !VBOX_WITH_GUEST_CONTROL */ 3735 3747 return VERR_NOT_SUPPORTED; -
trunk/src/VBox/Main/GuestImpl.cpp
r28243 r28286 34 34 #include <VBox/VMMDev.h> 35 35 #ifdef VBOX_WITH_GUEST_CONTROL 36 # include <VBox/HostServices/GuestControlSvc.h>37 36 # include <VBox/com/array.h> 38 # include <hgcm/HGCM.h>39 37 #endif 40 38 #include <iprt/cpp/utils.h> … … 95 93 for (unsigned i = 0 ; i < GUESTSTATTYPE_MAX; i++) 96 94 mCurrentGuestStat[i] = 0; 95 96 /* Init the context ID counter at 1000. */ 97 mNextContextID = 1000; 97 98 98 99 return S_OK; … … 438 439 439 440 /** 440 * Static callback function for receiving updates on processes started on441 * the guest side.441 * Static callback function for receiving updates on guest control commands 442 * from the guest. Acts as a dispatcher for the actual class instance. 442 443 * 443 444 * @returns VBox status code. … … 446 447 * 447 448 */ 448 DECLCALLBACK(int) Guest::doGuestCtrl ExecNotification(void*pvExtension,449 450 void*pvParms,451 449 DECLCALLBACK(int) Guest::doGuestCtrlNotification(void *pvExtension, 450 uint32_t u32Function, 451 void *pvParms, 452 uint32_t cbParms) 452 453 { 453 454 using namespace guestControl; … … 457 458 * changes to the object state. 458 459 */ 459 PHOSTEXECCALLBACKDATA pCBData = reinterpret_cast<PHOSTEXECCALLBACKDATA>(pvParms);460 AssertPtr(pCBData);461 AssertReturn(sizeof(HOSTEXECCALLBACKDATA) == cbParms, VERR_INVALID_PARAMETER);462 AssertReturn(HOSTCALLBACKMAGIC == pCBData->u32Magic, VERR_INVALID_PARAMETER);463 460 LogFlowFunc(("pvExtension = %p, u32Function = %d, pvParms = %p, cbParms = %d\n", 464 461 pvExtension, u32Function, pvParms, cbParms)); 465 PHOSTEXECCALLBACKDATA pExt = reinterpret_cast<HOSTEXECCALLBACKDATA*>(pvExtension);462 ComObjPtr<Guest> pGuest = reinterpret_cast<Guest *>(pvExtension); 466 463 467 464 int rc = VINF_SUCCESS; … … 469 466 { 470 467 LogFlowFunc(("GUEST_EXEC_SEND_STATUS\n")); 471 pExt->pid = pCBData->pid; 472 pExt->status = pCBData->status; 473 pExt->flags = pCBData->flags; 474 /** @todo Copy void* buffer! */ 468 469 PHOSTEXECCALLBACKDATA pCBData = reinterpret_cast<PHOSTEXECCALLBACKDATA>(pvParms); 470 AssertPtr(pCBData); 471 AssertReturn(sizeof(HOSTEXECCALLBACKDATA) == cbParms, VERR_INVALID_PARAMETER); 472 AssertReturn(HOSTEXECCALLBACKDATAMAGIC == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 473 474 rc = pGuest->notifyCtrlExec(u32Function, pCBData); 475 475 } 476 476 else 477 477 rc = VERR_NOT_SUPPORTED; 478 479 ASMAtomicWriteBool(&pExt->called, true);480 478 return rc; 479 } 480 481 /* Notifier function for control execution stuff. */ 482 int Guest::notifyCtrlExec(uint32_t u32Function, 483 PHOSTEXECCALLBACKDATA pData) 484 { 485 int rc = VINF_SUCCESS; 486 487 /* bool bFound = false; 488 for (int i=0; i<mList.size(); i++) 489 { 490 } 491 if(pData->hdr.u32ContextID == it->hdr.u32ContextID) 492 { 493 }*/ 494 /*pExt->pid = pCBData->pid; 495 pExt->status = pCBData->status; 496 pExt->flags = pCBData->flags;*/ 497 /** @todo Copy void* buffer! */ 498 499 return rc; 500 } 501 502 void Guest::freeCtrlCallbackContextData(CallbackContext *pContext) 503 { 504 AssertPtr(pContext); 505 if (pContext->cbData) 506 { 507 RTMemFree(pContext->pvData); 508 pContext->cbData = 0; 509 pContext->pvData = NULL; 510 } 511 } 512 513 uint32_t Guest::addCtrlCallbackContext(void *pvData, uint32_t cbData) 514 { 515 uint32_t uNewContext = ASMAtomicIncU32(&mNextContextID); 516 /** @todo Add value clamping! */ 517 518 CallbackContext context; 519 context.mContextID = uNewContext; 520 context.pvData = pvData; 521 context.cbData = cbData; 522 523 mCallbackList.push_back(context); 524 if (mCallbackList.size() > 256) 525 { 526 freeCtrlCallbackContextData(&mCallbackList.front()); 527 mCallbackList.pop_front(); 528 } 529 return uNewContext; 481 530 } 482 531 #endif /* VBOX_WITH_GUEST_CONTROL */ … … 520 569 if (FAILED(rc)) return rc; 521 570 #endif 522 523 571 /* 524 * Register the host notification callback572 * Prepare process execution. 525 573 */ 526 HGCMSVCEXTHANDLE hExt; 527 HOSTEXECCALLBACKDATA callbackData; 528 callbackData.called = false; 529 int vrc = HGCMHostRegisterServiceExtension(&hExt, "VBoxGuestControlSvc", 530 &Guest::doGuestCtrlExecNotification, 531 &callbackData); 574 int vrc = VINF_SUCCESS; 575 Utf8Str Utf8Command(aCommand); 576 577 /* Prepare arguments. */ 578 com::SafeArray<IN_BSTR> args(ComSafeArrayInArg(aArguments)); 579 uint32_t uNumArgs = args.size(); 580 char **papszArgv = NULL; 581 if(uNumArgs > 0) 582 { 583 papszArgv = (char**)RTMemAlloc(sizeof(char*) * (uNumArgs + 1)); 584 AssertPtr(papszArgv); 585 for (unsigned i = 0; RT_SUCCESS(vrc) && i < uNumArgs; i++) 586 vrc = RTStrAPrintf(&papszArgv[i], "%s", Utf8Str(args[i]).raw()); 587 papszArgv[uNumArgs] = NULL; 588 } 589 532 590 if (RT_SUCCESS(vrc)) 533 591 { 534 /* 535 * Prepare process execution. 536 */ 537 Utf8Str Utf8Command(aCommand); 538 539 /* Prepare arguments. */ 540 com::SafeArray<IN_BSTR> args(ComSafeArrayInArg(aArguments)); 541 uint32_t uNumArgs = args.size(); 542 char **papszArgv = NULL; 543 if(uNumArgs > 0) 544 { 545 papszArgv = (char**)RTMemAlloc(sizeof(char*) * (uNumArgs + 1)); 546 AssertPtr(papszArgv); 547 for (unsigned i = 0; RT_SUCCESS(vrc) && i < uNumArgs; i++) 548 vrc = RTStrAPrintf(&papszArgv[i], "%s", Utf8Str(args[i]).raw()); 549 papszArgv[uNumArgs] = NULL; 550 } 551 592 char *pszArgs = NULL; 593 if (uNumArgs > 0) 594 vrc = RTGetOptArgvToString(&pszArgs, papszArgv, 0); 552 595 if (RT_SUCCESS(vrc)) 553 596 { 554 char *pszArgs = NULL; 555 if (uNumArgs > 0) 556 vrc = RTGetOptArgvToString(&pszArgs, papszArgv, 0); 597 uint32_t cbArgs = pszArgs ? strlen(pszArgs) + 1 : 0; /* Include terminating zero. */ 598 599 /* Prepare environment. */ 600 com::SafeArray<IN_BSTR> env(ComSafeArrayInArg(aEnvironment)); 601 602 void *pvEnv = NULL; 603 uint32_t uNumEnv = 0; 604 uint32_t cbEnv = 0; 605 606 for (unsigned i = 0; i < env.size(); i++) 607 { 608 vrc = prepareExecuteEnv(Utf8Str(env[i]).raw(), &pvEnv, &cbEnv, &uNumEnv); 609 if (RT_FAILURE(vrc)) 610 break; 611 } 612 557 613 if (RT_SUCCESS(vrc)) 558 614 { 559 uint32_t cbArgs = pszArgs ? strlen(pszArgs) + 1 : 0; /* Include terminating zero. */ 615 Utf8Str Utf8StdIn(aStdIn); 616 Utf8Str Utf8StdOut(aStdOut); 617 Utf8Str Utf8StdErr(aStdErr); 618 Utf8Str Utf8UserName(aUserName); 619 Utf8Str Utf8Password(aPassword); 620 621 PHOSTEXECCALLBACKDATA pData = (HOSTEXECCALLBACKDATA*)RTMemAlloc(sizeof(HOSTEXECCALLBACKDATA)); 622 AssertPtr(pData); 623 uint32_t uContextID = addCtrlCallbackContext(pData, sizeof(HOSTEXECCALLBACKDATA)); 624 625 VBOXHGCMSVCPARM paParms[15]; 626 int i = 0; 627 paParms[i++].setUInt32(uContextID); 628 paParms[i++].setPointer((void*)Utf8Command.raw(), (uint32_t)strlen(Utf8Command.raw()) + 1); 629 paParms[i++].setUInt32(aFlags); 630 paParms[i++].setUInt32(uNumArgs); 631 paParms[i++].setPointer((void*)pszArgs, cbArgs); 632 paParms[i++].setUInt32(uNumEnv); 633 paParms[i++].setUInt32(cbEnv); 634 paParms[i++].setPointer((void*)pvEnv, cbEnv); 635 paParms[i++].setPointer((void*)Utf8StdIn.raw(), (uint32_t)strlen(Utf8StdIn.raw()) + 1); 636 paParms[i++].setPointer((void*)Utf8StdOut.raw(), (uint32_t)strlen(Utf8StdOut.raw()) + 1); 637 paParms[i++].setPointer((void*)Utf8StdErr.raw(), (uint32_t)strlen(Utf8StdErr.raw()) + 1); 638 paParms[i++].setPointer((void*)Utf8UserName.raw(), (uint32_t)strlen(Utf8UserName.raw()) + 1); 639 paParms[i++].setPointer((void*)Utf8Password.raw(), (uint32_t)strlen(Utf8Password.raw()) + 1); 640 paParms[i++].setUInt32(aTimeoutMS); 560 641 561 /* Prepare environment. */ 562 com::SafeArray<IN_BSTR> env(ComSafeArrayInArg(aEnvironment)); 563 564 void *pvEnv = NULL; 565 uint32_t uNumEnv = 0; 566 uint32_t cbEnv = 0; 567 568 for (unsigned i = 0; i < env.size(); i++) 642 /* Forward the information to the VMM device. */ 643 AssertPtr(mParent); 644 VMMDev *vmmDev = mParent->getVMMDev(); 645 if (vmmDev) 569 646 { 570 vrc = prepareExecuteEnv(Utf8Str(env[i]).raw(), &pvEnv, &cbEnv, &uNumEnv); 571 if (RT_FAILURE(vrc)) 647 LogFlowFunc(("hgcmHostCall numParms=%d\n", i)); 648 vrc = vmmDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_CMD, 649 i, paParms); 650 } 651 RTMemFree(pvEnv); 652 } 653 RTStrFree(pszArgs); 654 } 655 if (RT_SUCCESS(vrc)) 656 { 657 LogFlowFunc(("Waiting for HGCM callback (timeout=%ldms) ...\n", aTimeoutMS)); 658 659 /* 660 * Wait for the HGCM low level callback until the process 661 * has been started (or something went wrong). This is necessary to 662 * get the PID. 663 */ 664 #if 0 665 uint64_t u64Started = RTTimeMilliTS(); 666 do 667 { 668 unsigned cMsWait; 669 if (aTimeoutMS == RT_INDEFINITE_WAIT) 670 cMsWait = 1000; 671 else 672 { 673 uint64_t cMsElapsed = RTTimeMilliTS() - u64Started; 674 if (cMsElapsed >= aTimeoutMS) 675 break; /* timed out */ 676 cMsWait = RT_MIN(1000, aTimeoutMS - (uint32_t)cMsElapsed); 677 } 678 RTThreadSleep(100); 679 } while (!callbackData.called); 680 681 /* Did we get some status? */ 682 if (callbackData.called) 683 { 684 switch (callbackData.status) 685 { 686 case PROC_STS_STARTED: 687 *aPID = callbackData.pid; 688 break; 689 690 case PROC_STS_ERROR: 691 vrc = callbackData.flags; /* flags member contains IPRT error code. */ 692 break; 693 694 default: 695 vrc = VERR_INVALID_PARAMETER; 572 696 break; 573 697 } 574 575 if (RT_SUCCESS(vrc)) 698 } 699 700 if (RT_FAILURE(vrc)) 701 { 702 if (vrc == VERR_FILE_NOT_FOUND) /* This is the most likely error. */ 576 703 { 577 Utf8Str Utf8StdIn(aStdIn); 578 Utf8Str Utf8StdOut(aStdOut); 579 Utf8Str Utf8StdErr(aStdErr); 580 Utf8Str Utf8UserName(aUserName); 581 Utf8Str Utf8Password(aPassword); 582 583 VBOXHGCMSVCPARM paParms[14]; 584 int i = 0; 585 paParms[i++].setPointer((void*)Utf8Command.raw(), (uint32_t)strlen(Utf8Command.raw()) + 1); 586 paParms[i++].setUInt32(aFlags); 587 paParms[i++].setUInt32(uNumArgs); 588 paParms[i++].setPointer((void*)pszArgs, cbArgs); 589 paParms[i++].setUInt32(uNumEnv); 590 paParms[i++].setUInt32(cbEnv); 591 paParms[i++].setPointer((void*)pvEnv, cbEnv); 592 paParms[i++].setPointer((void*)Utf8StdIn.raw(), (uint32_t)strlen(Utf8StdIn.raw()) + 1); 593 paParms[i++].setPointer((void*)Utf8StdOut.raw(), (uint32_t)strlen(Utf8StdOut.raw()) + 1); 594 paParms[i++].setPointer((void*)Utf8StdErr.raw(), (uint32_t)strlen(Utf8StdErr.raw()) + 1); 595 paParms[i++].setPointer((void*)Utf8UserName.raw(), (uint32_t)strlen(Utf8UserName.raw()) + 1); 596 paParms[i++].setPointer((void*)Utf8Password.raw(), (uint32_t)strlen(Utf8Password.raw()) + 1); 597 paParms[i++].setUInt32(aTimeoutMS); 598 599 /* Forward the information to the VMM device. */ 600 AssertPtr(mParent); 601 VMMDev *vmmDev = mParent->getVMMDev(); 602 if (vmmDev) 603 { 604 LogFlowFunc(("hgcmHostCall numParms=%d\n", i)); 605 vrc = vmmDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_CMD, 606 i, paParms); 607 } 608 RTMemFree(pvEnv); 704 rc = setError(VBOX_E_IPRT_ERROR, 705 tr("The file \"%s\" was not found on guest"), Utf8Command.raw()); 609 706 } 610 RTStrFree(pszArgs); 707 else 708 { 709 rc = setError(E_UNEXPECTED, 710 tr("The service call failed with the error %Rrc"), vrc); 711 } 611 712 } 612 if (RT_SUCCESS(vrc)) 613 { 614 LogFlowFunc(("Waiting for HGCM callback (timeout=%ldms) ...\n", aTimeoutMS)); 615 616 /* 617 * Wait for the HGCM low level callback until the process 618 * has been started (or something went wrong). This is necessary to 619 * get the PID. 620 */ 621 uint64_t u64Started = RTTimeMilliTS(); 622 do 623 { 624 unsigned cMsWait; 625 if (aTimeoutMS == RT_INDEFINITE_WAIT) 626 cMsWait = 1000; 627 else 628 { 629 uint64_t cMsElapsed = RTTimeMilliTS() - u64Started; 630 if (cMsElapsed >= aTimeoutMS) 631 break; /* timed out */ 632 cMsWait = RT_MIN(1000, aTimeoutMS - (uint32_t)cMsElapsed); 633 } 634 RTThreadSleep(100); 635 } while (!callbackData.called); 636 637 /* Did we get some status? */ 638 if (callbackData.called) 639 { 640 switch (callbackData.status) 641 { 642 case PROC_STS_STARTED: 643 *aPID = callbackData.pid; 644 break; 645 646 case PROC_STS_ERROR: 647 vrc = callbackData.flags; /* flags member contains IPRT error code. */ 648 break; 649 650 default: 651 vrc = VERR_INVALID_PARAMETER; 652 break; 653 } 654 } 655 656 if (RT_FAILURE(vrc)) 657 { 658 if (vrc == VERR_FILE_NOT_FOUND) /* This is the most likely error. */ 659 { 660 rc = setError(VBOX_E_IPRT_ERROR, 661 tr("The file \"%s\" was not found on guest"), Utf8Command.raw()); 662 } 663 else 664 { 665 rc = setError(E_UNEXPECTED, 666 tr("The service call failed with the error %Rrc"), vrc); 667 } 668 } 713 #endif 669 714 #if 0 670 715 progress.queryInterfaceTo(aProgress); 671 716 #endif 672 }673 else674 {675 /* HGCM call went wrong. */676 rc = setError(E_UNEXPECTED,677 tr("The service call failed with the error %Rrc"), vrc);678 }679 680 for (unsigned i = 0; i < uNumArgs; i++)681 RTMemFree(papszArgv[i]);682 RTMemFree(papszArgv);683 717 } 684 /* Unregister HGCM extension */ 685 HGCMHostUnregisterServiceExtension(hExt); 718 else 719 { 720 /* HGCM call went wrong. */ 721 rc = setError(E_UNEXPECTED, 722 tr("The service call failed with error %Rrc"), vrc); 723 } 724 725 for (unsigned i = 0; i < uNumArgs; i++) 726 RTMemFree(papszArgv[i]); 727 RTMemFree(papszArgv); 686 728 } 687 729 } -
trunk/src/VBox/Main/include/GuestImpl.h
r28233 r28286 25 25 #include "VirtualBoxBase.h" 26 26 #include <VBox/ostypes.h> 27 28 #ifdef VBOX_WITH_GUEST_CONTROL 29 # include <VBox/HostServices/GuestControlSvc.h> 30 # include <hgcm/HGCM.h> 31 using namespace guestControl; 32 #endif 27 33 28 34 typedef enum … … 104 110 static const wchar_t *getComponentName() { return L"Guest"; } 105 111 112 # ifdef VBOX_WITH_GUEST_CONTROL 113 /** Static callback for handling guest notifications. */ 114 static DECLCALLBACK(int) doGuestCtrlNotification(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms); 115 # endif 116 106 117 private: 107 118 108 119 # ifdef VBOX_WITH_GUEST_CONTROL 120 121 struct CallbackContext 122 { 123 uint32_t mContextID; 124 void *pvData; 125 uint32_t cbData; 126 }; 127 109 128 int prepareExecuteArgs(const char *pszArgs, void **ppvList, uint32_t *pcbList, uint32_t *pcArgs); 110 129 int prepareExecuteEnv(const char *pszEnv, void **ppvList, uint32_t *pcbList, uint32_t *pcEnv); 111 /** Static callback for handling guest notifications. */ 112 static DECLCALLBACK(int) doGuestCtrlExecNotification(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms); 130 /** Handler for guest execution control notifications. */ 131 int notifyCtrlExec(uint32_t u32Function, PHOSTEXECCALLBACKDATA pData); 132 void freeCtrlCallbackContextData(CallbackContext *pContext); 133 uint32_t addCtrlCallbackContext(void *pvData, uint32_t cbData); 113 134 # endif 114 135 … … 131 152 Console *mParent; 132 153 Data mData; 133 bool mSignalled; 154 155 # ifdef VBOX_WITH_GUEST_CONTROL 156 /** General extension callback for guest control. */ 157 HGCMSVCEXTHANDLE mhExtCtrl; 158 159 volatile uint32_t mNextContextID; 160 typedef std::list< CallbackContext > CallbackList; 161 CallbackList mCallbackList; 162 # endif 134 163 }; 135 164
Note:
See TracChangeset
for help on using the changeset viewer.