Changeset 42461 in vbox
- Timestamp:
- Jul 30, 2012 9:28:12 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/HostServices/GuestControlSvc.h
r42160 r42461 44 44 /** 45 45 * Process status when executed in the guest. 46 * Note: Has to match Main's ExecuteProcessStatus_*!47 46 */ 48 47 enum eProcessStatus … … 250 249 * new data on stdout/stderr, process terminated etc. 251 250 */ 252 HOST_EXEC_GET_OUTPUT = 102 251 HOST_EXEC_GET_OUTPUT = 102, 252 253 /* 254 * Guest control 2.0 commands start in the 2xx number space. 255 */ 256 257 /** 258 * Waits for a certain event to happen. This can be an input, output 259 * or status event. 260 */ 261 HOST_EXEC_WAIT_FOR = 210 253 262 }; 254 263 … … 278 287 /* 279 288 * Process execution. 289 * The 1xx commands are legacy guest control commands and 290 * will be replaced by newer commands in the future. 280 291 */ 281 292 … … 291 302 * Guests sends an input status notification to the host. 292 303 */ 293 GUEST_EXEC_SEND_INPUT_STATUS = 102 304 GUEST_EXEC_SEND_INPUT_STATUS = 102, 305 306 /* 307 * Guest control 2.0 commands start in the 2xx number space. 308 */ 309 310 /** 311 * Guest notifies the host about some I/O event. This can be 312 * a stdout, stderr or a stdin event. The actual event only tells 313 * how many data is available / can be sent without actually 314 * transmitting the data. 315 */ 316 GUEST_EXEC_IO_NOTIFY = 210, 294 317 }; 295 318 … … 332 355 /** The command to execute on the guest. */ 333 356 HGCMFunctionParameter cmd; 334 /** Execution flags (see IGuest:: ExecuteProcessFlag_*). */357 /** Execution flags (see IGuest::ProcessCreateFlag_*). */ 335 358 HGCMFunctionParameter flags; 336 359 /** Number of arguments. */ … … 351 374 * overall lifetime of the process or how long it 352 375 * can take to bring the process up and running - 353 * (depends on the IGuest:: ExecuteProcessFlag_*). */376 * (depends on the IGuest::ProcessCreateFlag_*). */ 354 377 HGCMFunctionParameter timeout; 355 378 … … 434 457 } VBoxGuestCtrlHGCMMsgExecStatusIn; 435 458 459 /** 460 * Reports back the currente I/O status of a guest process. 461 */ 462 typedef struct VBoxGuestCtrlHGCMMsgExecIONotify 463 { 464 VBoxGuestHGCMCallInfo hdr; 465 /** Context ID. */ 466 HGCMFunctionParameter context; 467 /** Data written. */ 468 HGCMFunctionParameter written; 469 470 } VBoxGuestCtrlHGCMMsgExecIONotify; 471 436 472 #pragma pack () 437 473 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlThread.cpp
r41774 r42461 486 486 } 487 487 488 /* Re qport back actual data written (if any). */488 /* Report back actual data written (if any). */ 489 489 pRequest->cbData = cbWritten; 490 490 break; -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r42442 r42461 8884 8884 <enum 8885 8885 name="ProcessWaitResult" 8886 uuid=" c593a234-21ee-4a67-85ef-ba0cc9b9b86a"8886 uuid="24a4d49f-a7c1-44b0-b01f-5686a316466b" 8887 8887 > 8888 8888 <desc> … … 8915 8915 </const> 8916 8916 <const name="StdErr" value="8"> 8917 <desc>TODO</desc> 8918 </const> 8919 <const name="Any" value="9"> 8917 8920 <desc>TODO</desc> 8918 8921 </const> -
trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h
r42411 r42461 127 127 void Destroy(void); 128 128 129 int FillData(const void *p Data, size_t cbData);129 int FillData(const void *pvToWrite, size_t cbToWrite); 130 130 131 131 int Init(eVBoxGuestCtrlCallbackType enmType); … … 133 133 eVBoxGuestCtrlCallbackType GetCallbackType(void) { return mType; } 134 134 135 protected: 136 137 /** Pointer to user-supplied data. */ 135 const void* GetPayloadRaw(void) const { return pvPayload; } 136 137 size_t GetPayloadSize(void) { return cbPayload; } 138 139 protected: 140 141 /** Pointer to actual callback data. */ 138 142 void *pvData; 139 143 /** Size of user-supplied data. */ … … 143 147 /** Callback flags. */ 144 148 uint32_t uFlags; 149 /** Payload which will be available on successful 150 * waiting (optional). */ 151 void *pvPayload; 152 /** Size of the payload. */ 153 size_t cbPayload; 145 154 }; 146 155 typedef std::map < uint32_t, GuestCtrlCallback* > GuestCtrlCallbacks; -
trunk/src/VBox/Main/include/GuestImpl.h
r42411 r42461 207 207 * @{ */ 208 208 int dispatchToSession(uint32_t uContextID, uint32_t uFunction, void *pvData, size_t cbData); 209 uint32_t getAdditionsVersion(void) { return mData.mAdditionsVersionFull; } 209 210 Console *getConsole(void) { return mParent; } 210 211 int sessionClose(ComObjPtr<GuestSession> pSession); -
trunk/src/VBox/Main/include/GuestProcessImpl.h
r42436 r42461 76 76 bool isReady(void); 77 77 ULONG getPID(void) { return mData.mPID; } 78 int readData(ULONG uHandle, ULONG uSize, ULONG uTimeoutMS, BYTE *pbData, size_t cbData );78 int readData(ULONG uHandle, ULONG uSize, ULONG uTimeoutMS, BYTE *pbData, size_t cbData, size_t *pcbRead); 79 79 int startProcess(void); 80 80 int startProcessAsync(void); … … 92 92 int onGuestDisconnected(GuestCtrlCallback *pCallback, PCALLBACKDATACLIENTDISCONNECTED pData); 93 93 int onProcessInputStatus(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECINSTATUS pData); 94 int onProcessNotifyIO(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECSTATUS pData); 94 95 int onProcessStatusChange(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECSTATUS pData); 95 96 int onProcessOutput(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECOUT pData); -
trunk/src/VBox/Main/include/GuestSessionImpl.h
r42441 r42461 128 128 const GuestCredentials &getCredentials(void); 129 129 const GuestEnvironment &getEnvironment(void); 130 uint32_t getProtocolVersion(void) { return mData.mProtocolVersion; } 130 131 int processClose(ComObjPtr<GuestProcess> pProcess); 131 132 int processCreateExInteral(GuestProcessInfo &procInfo, ComObjPtr<GuestProcess> &pProgress); 132 133 inline bool processExists(uint32_t uProcessID, ComObjPtr<GuestProcess> *pProcess); 133 134 inline int processGetByPID(ULONG uPID, ComObjPtr<GuestProcess> *pProcess); 135 int queryInfo(void); 134 136 /** @} */ 135 137 … … 138 140 struct Data 139 141 { 142 /** Guest control protocol version. 143 * Guest control prior to VBox 4.2 has version 1, 144 * guest control 2.0 has ...well, 2. */ 145 uint32_t mProtocolVersion; 140 146 /** Flag indicating if this is an internal session 141 147 * or not. Internal session are not accessible by clients. */ -
trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp
r42436 r42461 2816 2816 if (FAILED(hr2)) 2817 2817 rc = VERR_COM_OBJECT_NOT_FOUND; 2818 2819 if (RT_SUCCESS(rc)) 2820 rc = pSession->queryInfo(); 2818 2821 } 2819 2822 -
trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp
r42436 r42461 122 122 : pvData(NULL), 123 123 cbData(0), 124 mType(VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN), 125 uFlags(0) 124 mType(VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN), 125 uFlags(0), 126 pvPayload(NULL), 127 cbPayload(0) 126 128 { 127 129 } … … 131 133 cbData(0), 132 134 mType(VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN), 133 uFlags(0) 135 uFlags(0), 136 pvPayload(NULL), 137 cbPayload(0) 134 138 { 135 139 int rc = Init(enmType); … … 206 210 } 207 211 cbData = 0; 208 } 209 210 int GuestCtrlCallback::FillData(const void *pData, size_t cbData) 211 { 212 if (!cbData) 212 213 if (pvPayload) 214 { 215 RTMemFree(pvPayload); 216 pvPayload = NULL; 217 } 218 cbPayload = 0; 219 } 220 221 int GuestCtrlCallback::FillData(const void *pvToWrite, size_t cbToWrite) 222 { 223 if (!cbToWrite) 213 224 return VINF_SUCCESS; 214 AssertPtr(p Data);215 216 Assert(pv Data== NULL); /* Can't reuse callbacks! */217 pv Data = RTMemAlloc(cbData);218 if (!pv Data)225 AssertPtr(pvToWrite); 226 227 Assert(pvPayload == NULL); /* Can't reuse callbacks! */ 228 pvPayload = RTMemAlloc(cbToWrite); 229 if (!pvPayload) 219 230 return VERR_NO_MEMORY; 220 231 221 memcpy(pvData, pData, cbData); 232 memcpy(pvPayload, pvToWrite, cbToWrite); 233 cbPayload = cbToWrite; 222 234 223 235 return VINF_SUCCESS; -
trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp
r42439 r42461 82 82 83 83 HRESULT hr = BaseFinalConstruct(); 84 LogFlowFuncLeaveRC(hr);85 84 return hr; 86 85 } … … 308 307 // private methods 309 308 ///////////////////////////////////////////////////////////////////////////// 310 311 /*312 313 SYNC TO ASK:314 Everything which involves HGCM communication (start, read/write/status(?)/...)315 either can be called synchronously or asynchronously by running in a Main worker316 thread.317 318 Rules:319 - Only one async operation per process a time can be around.320 321 */322 309 323 310 inline int GuestProcess::callbackAdd(GuestCtrlCallback *pCallback, ULONG *puContextID) … … 387 374 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 388 375 389 #ifdef DEBUG390 LogFlowFunc(("Callback count=%RU32\n", VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(uContextID)));391 #endif392 393 376 int rc; 377 378 /* Get the optional callback associated to this context ID. 379 * The callback may not be around anymore if just kept locally by the caller when 380 * doing the actual HGCM sending stuff. */ 381 GuestCtrlCallback *pCallback = NULL; 394 382 GuestCtrlCallbacks::const_iterator it 395 383 = mData.mCallbacks.find(VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(uContextID)); 396 384 if (it != mData.mCallbacks.end()) 397 385 { 398 GuestCtrlCallback *pCallback = it->second;386 pCallback = it->second; 399 387 AssertPtr(pCallback); 400 401 switch (uFunction) 402 { 403 case GUEST_DISCONNECTED: 404 { 405 PCALLBACKDATACLIENTDISCONNECTED pCallbackData = reinterpret_cast<PCALLBACKDATACLIENTDISCONNECTED>(pvData); 406 AssertPtr(pCallbackData); 407 AssertReturn(sizeof(CALLBACKDATACLIENTDISCONNECTED) == cbData, VERR_INVALID_PARAMETER); 408 AssertReturn(CALLBACKDATAMAGIC_CLIENT_DISCONNECTED == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER); 409 410 rc = onGuestDisconnected(pCallback, pCallbackData); /* Affects all callbacks. */ 411 break; 412 } 413 414 case GUEST_EXEC_SEND_STATUS: 415 { 416 PCALLBACKDATAEXECSTATUS pCallbackData = reinterpret_cast<PCALLBACKDATAEXECSTATUS>(pvData); 417 AssertPtr(pCallbackData); 418 AssertReturn(sizeof(CALLBACKDATAEXECSTATUS) == cbData, VERR_INVALID_PARAMETER); 419 AssertReturn(CALLBACKDATAMAGIC_EXEC_STATUS == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER); 420 421 rc = onProcessStatusChange(pCallback, pCallbackData); 422 break; 423 } 424 425 case GUEST_EXEC_SEND_OUTPUT: 426 { 427 PCALLBACKDATAEXECOUT pCallbackData = reinterpret_cast<PCALLBACKDATAEXECOUT>(pvData); 428 AssertPtr(pCallbackData); 429 AssertReturn(sizeof(CALLBACKDATAEXECOUT) == cbData, VERR_INVALID_PARAMETER); 430 AssertReturn(CALLBACKDATAMAGIC_EXEC_OUT == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER); 431 432 Assert(mData.mPID == pCallbackData->u32PID); 433 rc = onProcessOutput(pCallback, pCallbackData); 434 break; 435 } 436 437 case GUEST_EXEC_SEND_INPUT_STATUS: 438 { 439 PCALLBACKDATAEXECINSTATUS pCallbackData = reinterpret_cast<PCALLBACKDATAEXECINSTATUS>(pvData); 440 AssertPtr(pCallbackData); 441 AssertReturn(sizeof(CALLBACKDATAEXECINSTATUS) == cbData, VERR_INVALID_PARAMETER); 442 AssertReturn(CALLBACKDATAMAGIC_EXEC_IN_STATUS == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER); 443 444 Assert(mData.mPID == pCallbackData->u32PID); 445 rc = onProcessInputStatus(pCallback, pCallbackData); 446 break; 447 } 448 449 default: 450 /* Silently ignore not implemented functions. */ 451 rc = VERR_NOT_IMPLEMENTED; 452 break; 453 } 454 } 455 else 456 rc = VERR_NOT_FOUND; 388 #ifdef DEBUG 389 LogFlowFunc(("pCallback=%p\n", pCallback)); 390 #endif 391 } 392 393 switch (uFunction) 394 { 395 case GUEST_DISCONNECTED: 396 { 397 PCALLBACKDATACLIENTDISCONNECTED pCallbackData = reinterpret_cast<PCALLBACKDATACLIENTDISCONNECTED>(pvData); 398 AssertPtr(pCallbackData); 399 AssertReturn(sizeof(CALLBACKDATACLIENTDISCONNECTED) == cbData, VERR_INVALID_PARAMETER); 400 AssertReturn(CALLBACKDATAMAGIC_CLIENT_DISCONNECTED == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER); 401 402 rc = onGuestDisconnected(pCallback, pCallbackData); /* Affects all callbacks. */ 403 break; 404 } 405 406 case GUEST_EXEC_SEND_STATUS: 407 { 408 PCALLBACKDATAEXECSTATUS pCallbackData = reinterpret_cast<PCALLBACKDATAEXECSTATUS>(pvData); 409 AssertPtr(pCallbackData); 410 AssertReturn(sizeof(CALLBACKDATAEXECSTATUS) == cbData, VERR_INVALID_PARAMETER); 411 AssertReturn(CALLBACKDATAMAGIC_EXEC_STATUS == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER); 412 413 rc = onProcessStatusChange(pCallback, pCallbackData); 414 break; 415 } 416 417 case GUEST_EXEC_SEND_OUTPUT: 418 { 419 PCALLBACKDATAEXECOUT pCallbackData = reinterpret_cast<PCALLBACKDATAEXECOUT>(pvData); 420 AssertPtr(pCallbackData); 421 AssertReturn(sizeof(CALLBACKDATAEXECOUT) == cbData, VERR_INVALID_PARAMETER); 422 AssertReturn(CALLBACKDATAMAGIC_EXEC_OUT == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER); 423 424 rc = onProcessOutput(pCallback, pCallbackData); 425 break; 426 } 427 428 case GUEST_EXEC_SEND_INPUT_STATUS: 429 { 430 PCALLBACKDATAEXECINSTATUS pCallbackData = reinterpret_cast<PCALLBACKDATAEXECINSTATUS>(pvData); 431 AssertPtr(pCallbackData); 432 AssertReturn(sizeof(CALLBACKDATAEXECINSTATUS) == cbData, VERR_INVALID_PARAMETER); 433 AssertReturn(CALLBACKDATAMAGIC_EXEC_IN_STATUS == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER); 434 435 rc = onProcessInputStatus(pCallback, pCallbackData); 436 break; 437 } 438 439 default: 440 /* Silently ignore not implemented functions. */ 441 rc = VERR_NOT_IMPLEMENTED; 442 break; 443 } 457 444 458 445 #ifdef DEBUG … … 473 460 GuestCtrlCallbacks::iterator it = 474 461 mData.mCallbacks.find(VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(uContextID)); 475 if (it == mData.mCallbacks.end())462 if (it != mData.mCallbacks.end()) 476 463 { 477 464 delete it->second; … … 537 524 int GuestProcess::onGuestDisconnected(GuestCtrlCallback *pCallback, PCALLBACKDATACLIENTDISCONNECTED pData) 538 525 { 539 AssertPtrReturn(pCallback, VERR_INVALID_POINTER);526 /* pCallback is optional. */ 540 527 AssertPtrReturn(pData, VERR_INVALID_POINTER); 541 528 … … 545 532 546 533 /* First, signal callback in every case. */ 547 pCallback->Signal(); 534 if (pCallback) 535 pCallback->Signal(); 548 536 549 537 /* Do we need to report a termination? */ … … 564 552 int GuestProcess::onProcessInputStatus(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECINSTATUS pData) 565 553 { 566 AssertPtrReturn(pCallback, VERR_INVALID_POINTER);554 /* pCallback is optional. */ 567 555 AssertPtrReturn(pData, VERR_INVALID_POINTER); 568 556 … … 575 563 576 564 /* First, signal callback in every case. */ 577 pCallback->Signal(); 565 if (pCallback) 566 pCallback->Signal(); 578 567 579 568 /* Then do the WaitFor signalling stuff. */ … … 588 577 } 589 578 579 int GuestProcess::onProcessNotifyIO(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECSTATUS pData) 580 { 581 /* pCallback is optional. */ 582 AssertPtrReturn(pData, VERR_INVALID_POINTER); 583 584 return 0; 585 } 586 590 587 int GuestProcess::onProcessStatusChange(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECSTATUS pData) 591 588 { 592 AssertPtrReturn(pCallback, VERR_INVALID_POINTER);589 /* pCallback is optional. */ 593 590 AssertPtrReturn(pData, VERR_INVALID_POINTER); 594 591 … … 620 617 case PROC_STS_TEN: 621 618 { 622 fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);619 fSignal = TRUE; /* Signal in any case. */ 623 620 waitRes = ProcessWaitResult_Status; 624 621 … … 630 627 case PROC_STS_TES: 631 628 { 632 fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);629 fSignal = TRUE; /* Signal in any case. */ 633 630 waitRes = ProcessWaitResult_Status; 634 631 … … 640 637 case PROC_STS_TEA: 641 638 { 642 fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);639 fSignal = TRUE; /* Signal in any case. */ 643 640 waitRes = ProcessWaitResult_Status; 644 641 … … 649 646 case PROC_STS_TOK: 650 647 { 651 fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);648 fSignal = TRUE; /* Signal in any case. */ 652 649 waitRes = ProcessWaitResult_Timeout; 653 650 … … 658 655 case PROC_STS_TOA: 659 656 { 660 fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);657 fSignal = TRUE; /* Signal in any case. */ 661 658 waitRes = ProcessWaitResult_Timeout; 662 659 … … 667 664 case PROC_STS_DWN: 668 665 { 669 fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);666 fSignal = TRUE; /* Signal in any case. */ 670 667 waitRes = (mData.mProcess.mFlags & ProcessCreateFlag_IgnoreOrphanedProcesses) 671 668 ? ProcessWaitResult_Terminate : ProcessWaitResult_Status; … … 759 756 * Now do the signalling stuff. 760 757 */ 761 rc = pCallback->Signal(); 758 if (pCallback) 759 rc = pCallback->Signal(); 762 760 763 761 if (fSignal) … … 774 772 int GuestProcess::onProcessOutput(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECOUT pData) 775 773 { 776 AssertPtrReturn(pCallback, VERR_INVALID_POINTER);774 /* pCallback is optional. */ 777 775 AssertPtrReturn(pData, VERR_INVALID_POINTER); 778 776 … … 780 778 mData.mPID, pData->u32HandleId, pData->u32Flags, pData->pvData, pData->cbData, pCallback, pData)); 781 779 782 /* Copy data into callback. */ 783 int rc = pCallback->FillData(pData->pvData, pData->cbData); 784 785 /* First, signal callback in every case. */ 786 int rc2 = pCallback->Signal(); 787 if (RT_SUCCESS(rc)) 788 rc = rc2; 780 /* Copy data into callback (if any). */ 781 int rc = VINF_SUCCESS; 782 783 /* First, signal callback in every case (if available). */ 784 if (pCallback) 785 { 786 if (pData->pvData && pData->cbData) 787 rc = pCallback->FillData(pData->pvData, pData->cbData); 788 789 int rc2 = pCallback->Signal(); 790 if (RT_SUCCESS(rc)) 791 rc = rc2; 792 } 789 793 790 794 /* Then do the WaitFor signalling stuff. */ … … 811 815 if (fSignal) 812 816 { 813 rc2 = signalWaiters( pData->u32HandleId == OUTPUT_HANDLE_ID_STDOUT814 ? ProcessWaitResult_StdOut : ProcessWaitResult_StdErr);817 int rc2 = signalWaiters( pData->u32HandleId == OUTPUT_HANDLE_ID_STDOUT 818 ? ProcessWaitResult_StdOut : ProcessWaitResult_StdErr); 815 819 if (RT_SUCCESS(rc)) 816 820 rc = rc2; 817 821 } 818 AssertRC(rc);819 822 820 823 LogFlowFuncLeaveRC(rc); … … 822 825 } 823 826 824 int GuestProcess::readData(ULONG uHandle, ULONG uSize, ULONG uTimeoutMS, BYTE *pbData, size_t cbData) 825 { 826 LogFlowFunc(("uPID=%RU32, uHandle=%RU32, uSize=%RU32, uTimeoutMS=%RU32, pbData=%p, cbData=%z\n", 827 int GuestProcess::readData(ULONG uHandle, ULONG uSize, ULONG uTimeoutMS, 828 BYTE *pbData, size_t cbData, size_t *pcbRead) 829 { 830 LogFlowFunc(("uPID=%RU32, uHandle=%RU32, uSize=%RU32, uTimeoutMS=%RU32, pbData=%p, cbData=%RU32\n", 827 831 mData.mPID, uHandle, uSize, uTimeoutMS, pbData, cbData)); 828 832 AssertReturn(uSize, VERR_INVALID_PARAMETER); 829 833 AssertPtrReturn(pbData, VERR_INVALID_POINTER); 830 834 AssertReturn(cbData >= uSize, VERR_INVALID_PARAMETER); 831 832 LogFlowFuncLeave(); 833 return 0; 835 /* pcbRead is optional. */ 836 837 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 838 839 if (mData.mStatus != ProcessStatus_Started) 840 return VERR_NOT_AVAILABLE; 841 842 ULONG uContextID = 0; 843 GuestCtrlCallback *pCallbackRead = new GuestCtrlCallback(); 844 if (!pCallbackRead) 845 return VERR_NO_MEMORY; 846 847 /* Create callback and add it to the map. */ 848 int rc = pCallbackRead->Init(VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT); 849 if (RT_SUCCESS(rc)) 850 rc = callbackAdd(pCallbackRead, &uContextID); 851 852 alock.release(); /* Drop the write lock again. */ 853 854 if (RT_SUCCESS(rc)) 855 { 856 VBOXHGCMSVCPARM paParms[5]; 857 858 int i = 0; 859 paParms[i++].setUInt32(uContextID); 860 paParms[i++].setUInt32(mData.mPID); 861 paParms[i++].setUInt32(uHandle); 862 paParms[i++].setUInt32(0 /* Flags, none set yet. */); 863 864 rc = sendCommand(HOST_EXEC_GET_OUTPUT, i, paParms); 865 } 866 867 if (RT_SUCCESS(rc)) 868 { 869 /* 870 * Let's wait for the process being started. 871 * Note: Be sure not keeping a AutoRead/WriteLock here. 872 */ 873 LogFlowFunc(("Waiting for callback (%RU32ms) ...\n", uTimeoutMS)); 874 rc = pCallbackRead->Wait(uTimeoutMS); 875 if (RT_SUCCESS(rc)) /* Wait was successful, check for supplied information. */ 876 { 877 rc = pCallbackRead->GetResultCode(); 878 LogFlowFunc(("Callback returned rc=%Rrc, cbData=%RU32\n", rc, pCallbackRead->GetPayloadSize())); 879 880 if (RT_SUCCESS(rc)) 881 { 882 size_t cbDataCB = pCallbackRead->GetPayloadSize(); 883 if (cbDataCB) 884 { 885 Assert(cbData >= cbDataCB); 886 memcpy(pbData, pCallbackRead->GetPayloadRaw(), cbDataCB); 887 } 888 889 if (pcbRead) 890 *pcbRead = cbDataCB; 891 } 892 } 893 else 894 rc = VERR_TIMEOUT; 895 } 896 897 alock.acquire(); 898 899 AssertPtr(pCallbackRead); 900 int rc2 = callbackRemove(uContextID); 901 if (RT_SUCCESS(rc)) 902 rc = rc2; 903 904 LogFlowFuncLeaveRC(rc); 905 return rc; 834 906 } 835 907 … … 839 911 LogFlowThisFuncEnter(); 840 912 841 Co nsole *pConsole = mData.mConsole;842 Assert Ptr(pConsole);913 ComObjPtr<Console> pConsole = mData.mConsole; 914 Assert(!pConsole.isNull()); 843 915 844 916 /* Forward the information to the VMM device. */ … … 850 922 if (RT_FAILURE(rc)) 851 923 { 924 int rc2; 925 if (rc == VERR_INVALID_VM_HANDLE) 926 rc2 = setErrorInternal(rc, tr("VMM device is not available (is the VM running?)")); 927 else if (rc == VERR_NOT_FOUND) 928 rc2 = setErrorInternal(rc, tr("The guest execution service is not ready (yet)")); 929 else if (rc == VERR_HGCM_SERVICE_NOT_FOUND) 930 rc2 = setErrorInternal(rc, tr("The guest execution service is not available")); 931 else 932 rc2 = setErrorInternal(rc, Utf8StrFmt(tr("The HGCM call failed with error %Rrc"), rc)); 933 AssertRC(rc2); 852 934 } 853 935 … … 983 1065 984 1066 rc = sendCommand(HOST_EXEC_CMD, i, paParms); 985 if (RT_FAILURE(rc))986 {987 int rc2;988 if (rc == VERR_INVALID_VM_HANDLE)989 rc2 = setErrorInternal(rc, tr("VMM device is not available (is the VM running?)"));990 else if (rc == VERR_NOT_FOUND)991 rc2 = setErrorInternal(rc, tr("The guest execution service is not ready (yet)"));992 else if (rc == VERR_HGCM_SERVICE_NOT_FOUND)993 rc2 = setErrorInternal(rc, tr("The guest execution service is not available"));994 else995 rc2 = setErrorInternal(rc, Utf8StrFmt(tr("The HGCM call failed with error %Rrc"), rc));996 AssertRC(rc2);997 }998 1067 } 999 1068 … … 1004 1073 uint32_t uTimeoutMS = mData.mProcess.mTimeoutMS; 1005 1074 1006 alock.release(); /* Drop the readlock again. */1075 alock.release(); /* Drop the write lock again. */ 1007 1076 1008 1077 if (RT_SUCCESS(rc)) … … 1085 1154 LogFlowThisFuncEnter(); 1086 1155 1156 if (mData.mParent->getProtocolVersion() < 2) 1157 return VERR_NOT_SUPPORTED; 1158 1087 1159 LogFlowFuncLeave(); 1088 1160 return VERR_NOT_IMPLEMENTED; … … 1095 1167 AssertReturn(fWaitFlags, VERR_INVALID_PARAMETER); 1096 1168 1097 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1098 1099 1169 LogFlowFunc(("fWaitFlags=%x, uTimeoutMS=%RU32, mStatus=%RU32, mWaitCount=%RU32, mWaitEvent=%p\n", 1100 1170 fWaitFlags, uTimeoutMS, mData.mStatus, mData.mWaitCount, mData.mWaitEvent)); 1101 1171 1102 ProcessStatus_T curStatus = mData.mStatus; 1172 ProcessStatus_T curStatus; 1173 { 1174 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 1175 curStatus = mData.mStatus; 1176 } 1103 1177 1104 1178 /* Did some error occur before? Then skip waiting and return. */ … … 1117 1191 || (fWaitFlags & ProcessWaitForFlag_StdErr)) 1118 1192 { 1193 /* Filter out waits which are *not* supported using 1194 * older guest control Guest Additions. */ 1195 AssertPtr(mData.mParent); 1196 if (mData.mParent->getProtocolVersion() < 2) 1197 { 1198 /* We don't support waiting for stdin, out + err, 1199 * just skip waiting then. */ 1200 if ( (fWaitFlags & ProcessWaitForFlag_StdIn) 1201 || (fWaitFlags & ProcessWaitForFlag_StdOut) 1202 || (fWaitFlags & ProcessWaitForFlag_StdErr)) 1203 { 1204 /* Use _Any because we don't know what to tell the caller. */ 1205 waitRes.mResult = ProcessWaitResult_Any; 1206 } 1207 } 1208 1119 1209 switch (mData.mStatus) 1120 1210 { … … 1138 1228 case ProcessStatus_Undefined: 1139 1229 case ProcessStatus_Starting: 1230 case ProcessStatus_Started: 1140 1231 /* Do the waiting below. */ 1141 1232 break; … … 1181 1272 if (waitRes.mResult != ProcessWaitResult_None) 1182 1273 return VINF_SUCCESS; 1274 1275 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 1183 1276 1184 1277 if (mData.mWaitCount > 0) … … 1348 1441 int GuestProcess::writeData(ULONG uHandle, const BYTE *pbData, size_t cbData, ULONG uTimeoutMS, ULONG *puWritten) 1349 1442 { 1350 LogFlowFunc(("uPID=%RU32, uHandle=%RU32, pbData=%p, cbData=% z, uTimeoutMS=%RU32, puWritten=%p\n",1443 LogFlowFunc(("uPID=%RU32, uHandle=%RU32, pbData=%p, cbData=%RU32, uTimeoutMS=%RU32, puWritten=%p\n", 1351 1444 mData.mPID, uHandle, pbData, cbData, uTimeoutMS, puWritten)); 1352 1445 AssertPtrReturn(pbData, VERR_INVALID_POINTER); … … 1366 1459 ReturnComNotImplemented(); 1367 1460 #else 1368 LogFlowThisFuncEnter();1369 1461 if (aSize < 0) 1462 return setError(E_INVALIDARG, tr("The size argument (%lld) is negative"), aSize); 1370 1463 if (aSize == 0) 1371 return setError(E_INVALIDARG, tr(" Invalid size to read specified"));1464 return setError(E_INVALIDARG, tr("The size (%lld) is zero"), aSize); 1372 1465 CheckComArgOutSafeArrayPointerValid(aData); 1373 1466 … … 1375 1468 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1376 1469 1377 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 1378 1379 com::SafeArray<BYTE> data(aSize); 1380 int rc = readData(aHandle, aSize, aTimeoutMS, data.raw(), aSize); 1470 com::SafeArray<BYTE> data((size_t)aSize); 1471 Assert(data.size() >= aSize); 1472 1473 size_t cbRead; 1474 int rc = readData(aHandle, aSize, aTimeoutMS, data.raw(), aSize, &cbRead); 1381 1475 if (RT_SUCCESS(rc)) 1476 { 1477 if (data.size() != cbRead) 1478 data.resize(cbRead); 1382 1479 data.detachTo(ComSafeArrayOutArg(aData)); 1480 } 1383 1481 1384 1482 /** @todo Do setError() here. */ 1385 1483 HRESULT hr = RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR; 1386 LogFlowFuncLeaveRC( hr);1484 LogFlowFuncLeaveRC(rc); 1387 1485 1388 1486 return hr; … … 1405 1503 /** @todo Do setError() here. */ 1406 1504 HRESULT hr = RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR; 1407 LogFlowFuncLeaveRC( hr);1505 LogFlowFuncLeaveRC(rc); 1408 1506 1409 1507 return hr; … … 1471 1569 fWaitFor |= flags[i]; 1472 1570 1473 HRESULT hr = WaitFor(fWaitFor, aTimeoutMS, aReason); 1474 1475 LogFlowFuncLeaveRC(hr); 1476 return hr; 1571 return WaitFor(fWaitFor, aTimeoutMS, aReason); 1477 1572 #endif /* VBOX_WITH_GUEST_CONTROL */ 1478 1573 } … … 1496 1591 /** @todo Do setError() here. */ 1497 1592 HRESULT hr = RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR; 1498 LogFlowFuncLeaveRC( hr);1593 LogFlowFuncLeaveRC(rc); 1499 1594 1500 1595 return hr; -
trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp
r42439 r42461 31 31 32 32 #include <VBox/com/array.h> 33 #include <VBox/version.h> 33 34 34 35 … … 562 563 } 563 564 565 /** 566 * Queries/collects information prior to establishing a guest session. 567 * This is necessary to know which guest control protocol version to use, 568 * among other things (later). 569 * 570 * @return IPRT status code. 571 */ 572 int GuestSession::queryInfo(void) 573 { 574 /* 575 * Try querying the guest control protocol version running on the guest. 576 * This is done using the Guest Additions version 577 */ 578 ComObjPtr<Guest> pGuest = mData.mParent; 579 Assert(!pGuest.isNull()); 580 581 uint32_t uVerAdditions = pGuest->getAdditionsVersion(); 582 mData.mProtocolVersion = ( VBOX_FULL_VERSION_GET_MAJOR(uVerAdditions) >= 4 583 && VBOX_FULL_VERSION_GET_MINOR(uVerAdditions) >= 2 ) 584 ? 2 /* Guest control 2.0. */ 585 : 1; /* Legacy guest control (VBox < 4.2). */ 586 /* Build revision is ignored. */ 587 588 /* Tell the user but don't bitch too often. */ 589 static short s_gctrlLegacyWarning = 0; 590 if (s_gctrlLegacyWarning++ < 3) /** @todo Find a bit nicer text. */ 591 LogRel((tr("Warning: Guest Additions are older (%ld.%ld) than host capabilities for guest control, please upgrade them. Using protocol version %ld now\n"), 592 VBOX_FULL_VERSION_GET_MAJOR(uVerAdditions), VBOX_FULL_VERSION_GET_MINOR(uVerAdditions), mData.mProtocolVersion)); 593 594 return VINF_SUCCESS; 595 } 596 564 597 // implementation of public methods 565 598 /////////////////////////////////////////////////////////////////////////////
Note:
See TracChangeset
for help on using the changeset viewer.