Changeset 45780 in vbox
- Timestamp:
- Apr 26, 2013 3:19:33 PM (12 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h
r45568 r45780 375 375 }; 376 376 377 class GuestWaitEvent 378 { 379 public: 380 381 GuestWaitEvent(uint32_t mCID, const std::list<VBoxEventType_T> &lstEvents); 382 virtual ~GuestWaitEvent(void); 383 384 public: 385 386 uint32_t ContextID(void) { return mCID; }; 387 const ComPtr<IEvent> Event(void) { return mEvent; }; 388 const std::list<VBoxEventType_T> Types(void) { return mEventTypes; }; 389 int Signal(IEvent *pEvent); 390 int Wait(RTMSINTERVAL uTimeoutMS); 391 392 protected: 393 394 uint32_t mCID; 395 std::list<VBoxEventType_T> mEventTypes; 396 /** The event semaphore for triggering 397 * the actual event. */ 398 RTSEMEVENT mEventSem; 399 /** Pointer to the actual event. */ 400 ComPtr<IEvent> mEvent; 401 }; 402 typedef std::list < GuestWaitEvent* > GuestWaitEvents; 403 typedef std::map < VBoxEventType_T, GuestWaitEvents > GuestWaitEventTypes; 404 377 405 class GuestBase 378 406 { … … 385 413 public: 386 414 415 /** For external event listeners. */ 416 int signalWaitEvents(VBoxEventType_T aType, IEvent *aEvent); 417 418 public: 419 387 420 int generateContextID(uint32_t uSessionID, uint32_t uObjectID, uint32_t *puContextID); 421 int registerEvent(uint32_t uSessionID, uint32_t uObjectID, const std::list<VBoxEventType_T> &lstEvents, GuestWaitEvent **ppEvent); 422 void unregisterEvent(GuestWaitEvent *pEvent); 423 void unregisterEventListener(void); 424 int waitForEvent(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, VBoxEventType_T *pType, IEvent **ppEvent); 388 425 389 426 protected: … … 394 431 /** The next upcoming context ID for this object. */ 395 432 uint32_t mNextContextID; 433 /** Local listener for handling the waiting events. */ 434 ComPtr<IEventListener> mListener; 435 /** Critical section for wait events access. */ 436 RTCRITSECT mWaitEventCritSect; 437 /** Map of internal events to wait for. */ 438 GuestWaitEventTypes mWaitEvents; 396 439 }; 397 440 … … 420 463 421 464 int bindToSession(Console *pConsole, GuestSession *pSession, uint32_t uObjectID); 465 int registerEvent(const std::list<VBoxEventType_T> &lstEvents, GuestWaitEvent **ppEvent); 422 466 int sendCommand(uint32_t uFunction, uint32_t uParms, PVBOXHGCMSVCPARM paParms); 423 467 -
trunk/src/VBox/Main/include/GuestFileImpl.h
r45568 r45780 94 94 static HRESULT setErrorExternal(VirtualBoxBase *pInterface, int guestRc); 95 95 int setFileStatus(FileStatus_T fileStatus, int fileRc); 96 int waitForEvents(uint32_t uTimeoutMS, ComSafeArrayIn(VBoxEventType_T, pEvents), VBoxEventType_T *pType, IEvent **ppEvent); 97 int waitForOffsetChange(uint32_t uTimeoutMS, uint64_t *puOffset); 98 int waitForRead(uint32_t uTimeoutMS, void *pvData, size_t cbData, uint32_t *pcbRead); 99 int waitForStatusChange(uint32_t uTimeoutMS, FileStatus_T *pFileStatus); 100 int waitForWrite(uint32_t uTimeoutMS, uint32_t *pcbWritten); 96 int waitForOffsetChange(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, uint64_t *puOffset); 97 int waitForRead(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, void *pvData, size_t cbData, uint32_t *pcbRead); 98 int waitForStatusChange(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, FileStatus_T *pFileStatus); 99 int waitForWrite(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, uint32_t *pcbWritten); 101 100 int writeData(uint32_t uTimeoutMS, void *pvData, uint32_t cbData, uint32_t *pcbWritten); 102 101 int writeDataAt(uint64_t uOffset, uint32_t uTimeoutMS, void *pvData, uint32_t cbData, uint32_t *pcbWritten); -
trunk/src/VBox/Main/include/GuestProcessImpl.h
r45482 r45780 84 84 int terminateProcess(int *pGuestRc); 85 85 int waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, ProcessWaitResult_T &waitResult, int *pGuestRc); 86 int waitForEvents(uint32_t uTimeoutMS, ComSafeArrayIn(VBoxEventType_T, pEvents), VBoxEventType_T *pType, IEvent **ppEvent); 87 int waitForInputNotify(uint32_t uHandle, uint32_t uTimeoutMS, ProcessInputStatus_T *pInputStatus, uint32_t *pcbProcessed); 88 int waitForOutput(uint32_t uHandle, uint32_t uTimeoutMS, void* pvData, size_t cbData, uint32_t *pcbRead); 89 int waitForStatusChange(uint32_t fWaitFlags, uint32_t uTimeoutMS, ProcessStatus_T *pProcessStatus, int *pGuestRc); 86 int waitForInputNotify(GuestWaitEvent *pEvent, uint32_t uHandle, uint32_t uTimeoutMS, ProcessInputStatus_T *pInputStatus, uint32_t *pcbProcessed); 87 int waitForOutput(GuestWaitEvent *pEvent, uint32_t uHandle, uint32_t uTimeoutMS, void* pvData, size_t cbData, uint32_t *pcbRead); 88 int waitForStatusChange(GuestWaitEvent *pEvent, uint32_t fWaitFlags, uint32_t uTimeoutMS, ProcessStatus_T *pProcessStatus, int *pGuestRc); 90 89 int writeData(uint32_t uHandle, uint32_t uFlags, void *pvData, size_t cbData, uint32_t uTimeoutMS, uint32_t *puWritten, int *pGuestRc); 91 90 /** @} */ -
trunk/src/VBox/Main/include/GuestSessionImpl.h
r45415 r45780 371 371 int queryInfo(void); 372 372 int waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, GuestSessionWaitResult_T &waitResult, int *pGuestRc); 373 int waitForStat eChange(uint32_t fWaitFlags, uint32_t uTimeoutMS, GuestSessionStatus_T *pSessionStatus, int *pGuestRc);373 int waitForStatusChange(GuestWaitEvent *pEvent, uint32_t fWaitFlags, uint32_t uTimeoutMS, GuestSessionStatus_T *pSessionStatus, int *pGuestRc); 374 374 /** @} */ 375 375 -
trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp
r45571 r45780 804 804 } 805 805 806 int GuestBase::registerEvent(uint32_t uSessionID, uint32_t uObjectID, 807 const std::list<VBoxEventType_T> &lstEvents, 808 GuestWaitEvent **ppEvent) 809 { 810 AssertPtrReturn(ppEvent, VERR_INVALID_POINTER); 811 812 uint32_t uContextID; 813 int rc = generateContextID(uSessionID, uObjectID, &uContextID); 814 if (RT_FAILURE(rc)) 815 return rc; 816 817 rc = RTCritSectEnter(&mWaitEventCritSect); 818 if (RT_SUCCESS(rc)) 819 { 820 try 821 { 822 GuestWaitEvent *pEvent = new GuestWaitEvent(uContextID, lstEvents); 823 AssertPtr(pEvent); 824 825 for (std::list<VBoxEventType_T>::const_iterator itEvents = lstEvents.begin(); 826 itEvents != lstEvents.end(); itEvents++) 827 { 828 mWaitEvents[(*itEvents)].push_back(pEvent); 829 } 830 831 *ppEvent = pEvent; 832 } 833 catch(std::bad_alloc &) 834 { 835 rc = VERR_NO_MEMORY; 836 } 837 838 int rc2 = RTCritSectLeave(&mWaitEventCritSect); 839 if (RT_SUCCESS(rc)) 840 rc = rc2; 841 } 842 843 return rc; 844 } 845 846 int GuestBase::signalWaitEvents(VBoxEventType_T aType, IEvent *aEvent) 847 { 848 int rc = RTCritSectEnter(&mWaitEventCritSect); 849 if (RT_SUCCESS(rc)) 850 { 851 GuestWaitEventTypes::iterator itTypes = mWaitEvents.find(aType); 852 if (itTypes != mWaitEvents.end()) 853 { 854 for (GuestWaitEvents::iterator itEvents = itTypes->second.begin(); 855 itEvents != itTypes->second.end(); itEvents++) 856 { 857 ComPtr<IEvent> pThisEvent = aEvent; 858 Assert(!pThisEvent.isNull()); 859 int rc2 = (*itEvents)->Signal(aEvent); 860 if (RT_SUCCESS(rc)) 861 rc = rc2; 862 } 863 } 864 865 int rc2 = RTCritSectLeave(&mWaitEventCritSect); 866 if (RT_SUCCESS(rc)) 867 rc = rc2; 868 } 869 870 return rc; 871 } 872 873 void GuestBase::unregisterEvent(GuestWaitEvent *pEvent) 874 { 875 AssertPtrReturnVoid(pEvent); 876 877 int rc = RTCritSectEnter(&mWaitEventCritSect); 878 if (RT_SUCCESS(rc)) 879 { 880 const std::list<VBoxEventType_T> lstTypes = pEvent->Types(); 881 for (std::list<VBoxEventType_T>::const_iterator itEvents = lstTypes.begin(); 882 itEvents != lstTypes.end(); itEvents++) 883 { 884 /** @todo Slow O(n) lookup. Optimize this. */ 885 GuestWaitEvents::iterator itCurEvent = mWaitEvents[(*itEvents)].begin(); 886 while (itCurEvent != mWaitEvents[(*itEvents)].end()) 887 { 888 if ((*itCurEvent) == pEvent) 889 { 890 itCurEvent = mWaitEvents[(*itEvents)].erase(itCurEvent); 891 break; 892 } 893 else 894 itCurEvent++; 895 } 896 } 897 898 delete pEvent; 899 900 int rc2 = RTCritSectLeave(&mWaitEventCritSect); 901 if (RT_SUCCESS(rc)) 902 rc = rc2; 903 } 904 } 905 906 void GuestBase::unregisterEventListener(void) 907 { 908 if (mListener) 909 { 910 ComPtr<IEventSource> es; 911 HRESULT hr = mConsole->COMGETTER(EventSource)(es.asOutParam()); 912 if (SUCCEEDED(hr)) 913 { 914 Assert(!es.isNull()); 915 es->UnregisterListener(mListener); 916 } 917 918 mListener.setNull(); 919 } 920 921 int rc2 = RTCritSectDelete(&mWaitEventCritSect); 922 AssertRC(rc2); 923 } 924 925 int GuestBase::waitForEvent(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, 926 VBoxEventType_T *pType, IEvent **ppEvent) 927 { 928 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 929 930 LogFlowFunc(("pEvent=%p, uTimeoutMS=%RU32\n", 931 pEvent, uTimeoutMS)); 932 933 int vrc = pEvent->Wait(uTimeoutMS); 934 if (RT_SUCCESS(vrc)) 935 { 936 const ComPtr<IEvent> pThisEvent = pEvent->Event(); 937 Assert(!pThisEvent.isNull()); 938 939 if (pType) 940 { 941 HRESULT hr = pThisEvent->COMGETTER(Type)(pType); 942 ComAssertComRC(hr); 943 } 944 if (ppEvent) 945 pThisEvent.queryInterfaceTo(ppEvent); 946 } 947 948 LogFlowFuncLeaveRC(vrc); 949 return vrc; 950 } 951 806 952 GuestObject::GuestObject(void) 807 953 : mSession(NULL), … … 824 970 825 971 return VINF_SUCCESS; 972 } 973 974 int GuestObject::registerEvent(const std::list<VBoxEventType_T> &lstEvents, 975 GuestWaitEvent **ppEvent) 976 { 977 AssertPtr(mSession); 978 return GuestBase::registerEvent(mSession->getId(), mObjectID, lstEvents, ppEvent); 826 979 } 827 980 … … 853 1006 } 854 1007 1008 GuestWaitEvent::GuestWaitEvent(uint32_t uCID, 1009 const std::list<VBoxEventType_T> &lstEvents) 1010 : mCID(uCID), 1011 mEventTypes(lstEvents), 1012 mEventSem(NIL_RTSEMEVENT), 1013 mEvent(false) 1014 { 1015 int rc = RTSemEventCreate(&mEventSem); 1016 AssertRC(rc); 1017 /** @todo Throw an exception on failure! */ 1018 } 1019 1020 GuestWaitEvent::~GuestWaitEvent(void) 1021 { 1022 1023 } 1024 1025 int GuestWaitEvent::Signal(IEvent *pEvent) 1026 { 1027 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 1028 AssertReturn(mEventSem != NIL_RTSEMEVENT, VERR_CANCELLED); 1029 1030 mEvent = pEvent; 1031 1032 return RTSemEventSignal(mEventSem); 1033 } 1034 1035 int GuestWaitEvent::Wait(RTMSINTERVAL uTimeoutMS) 1036 { 1037 LogFlowThisFuncEnter(); 1038 1039 AssertReturn(mEventSem != NIL_RTSEMEVENT, VERR_CANCELLED); 1040 1041 RTMSINTERVAL msInterval = uTimeoutMS; 1042 if (!uTimeoutMS) 1043 msInterval = RT_INDEFINITE_WAIT; 1044 int rc = RTSemEventWait(mEventSem, msInterval); 1045 1046 LogFlowFuncLeaveRC(rc); 1047 return rc; 1048 } 1049 -
trunk/src/VBox/Main/src-client/GuestFileImpl.cpp
r45482 r45780 33 33 #include <iprt/cpp/utils.h> /* For unconst(). */ 34 34 #include <iprt/file.h> 35 35 36 #include <VBox/com/array.h> 37 #include <VBox/com/listeners.h> 36 38 37 39 #ifdef LOG_GROUP … … 41 43 #include <VBox/log.h> 42 44 45 46 /** 47 * Internal listener class to serve events in an 48 * active manner, e.g. without polling delays. 49 */ 50 class GuestFileListener 51 { 52 public: 53 54 GuestFileListener(void) 55 { 56 } 57 58 HRESULT init(GuestFile *pFile) 59 { 60 mFile = pFile; 61 return S_OK; 62 } 63 64 void uninit(void) 65 { 66 mFile.setNull(); 67 } 68 69 STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent *aEvent) 70 { 71 switch (aType) 72 { 73 case VBoxEventType_OnGuestFileStateChanged: 74 case VBoxEventType_OnGuestFileOffsetChanged: 75 case VBoxEventType_OnGuestFileRead: 76 case VBoxEventType_OnGuestFileWrite: 77 { 78 Assert(!mFile.isNull()); 79 int rc2 = mFile->signalWaitEvents(aType, aEvent); 80 #ifdef DEBUG_andy 81 LogFlowFunc(("Signalling events of type=%ld, file=%p resulted in rc=%Rrc\n", 82 aType, mFile, rc2)); 83 #endif 84 break; 85 } 86 87 default: 88 AssertMsgFailed(("Unhandled event %ld\n", aType)); 89 break; 90 } 91 92 return S_OK; 93 } 94 95 private: 96 97 ComObjPtr<GuestFile> mFile; 98 }; 99 typedef ListenerImpl<GuestFileListener, GuestFile*> GuestFileListenerImpl; 100 101 VBOX_LISTENER_DECLARE(GuestFileListenerImpl) 43 102 44 103 // constructor / destructor … … 106 165 if (RT_SUCCESS(vrc)) 107 166 { 167 try 168 { 169 GuestFileListener *pListener = new GuestFileListener(); 170 ComObjPtr<GuestFileListenerImpl> thisListener; 171 HRESULT hr = thisListener.createObject(); 172 if (SUCCEEDED(hr)) 173 hr = thisListener->init(pListener, this); 174 175 if (SUCCEEDED(hr)) 176 { 177 mListener = thisListener; 178 179 com::SafeArray <VBoxEventType_T> eventTypes; 180 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged); 181 eventTypes.push_back(VBoxEventType_OnGuestFileOffsetChanged); 182 eventTypes.push_back(VBoxEventType_OnGuestFileRead); 183 eventTypes.push_back(VBoxEventType_OnGuestFileWrite); 184 hr = mEventSource->RegisterListener(mListener, 185 ComSafeArrayAsInParam(eventTypes), 186 TRUE /* Active listener */); 187 if (SUCCEEDED(hr)) 188 { 189 vrc = RTCritSectInit(&mWaitEventCritSect); 190 AssertRC(vrc); 191 } 192 else 193 vrc = VERR_COM_UNEXPECTED; 194 } 195 else 196 vrc = VERR_COM_UNEXPECTED; 197 } 198 catch(std::bad_alloc &) 199 { 200 vrc = VERR_NO_MEMORY; 201 } 202 } 203 204 if (RT_SUCCESS(vrc)) 205 { 108 206 /* Confirm a successful initialization when it's the case. */ 109 207 autoInitSpan.setSucceeded(); … … 132 230 #ifdef VBOX_WITH_GUEST_CONTROL 133 231 unconst(mEventSource).setNull(); 232 unregisterEventListener(); 134 233 #endif 135 234 … … 325 424 LogFlowThisFunc(("strFile=%s\n", mData.mOpenInfo.mFileName.c_str())); 326 425 327 uint32_t uContextID; 328 int vrc = generateContextID(mSession->getId(), mObjectID, 329 &uContextID); 330 if (RT_SUCCESS(vrc)) 331 { 332 /* Prepare HGCM call. */ 333 VBOXHGCMSVCPARM paParms[4]; 334 int i = 0; 335 paParms[i++].setUInt32(mData.mID /* Guest file ID */); 336 337 vrc = sendCommand(HOST_FILE_CLOSE, i, paParms); 338 if (RT_SUCCESS(vrc)) 339 vrc = waitForStatusChange(30 * 1000 /* Timeout in ms */, 340 NULL /* FileStatus */); 341 } 426 int vrc; 427 428 GuestWaitEvent *pEvent = NULL; 429 std::list < VBoxEventType_T > eventTypes; 430 try 431 { 432 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged); 433 434 vrc = registerEvent(eventTypes, &pEvent); 435 } 436 catch (std::bad_alloc) 437 { 438 vrc = VERR_NO_MEMORY; 439 } 440 441 if (RT_FAILURE(vrc)) 442 return vrc; 443 444 /* Prepare HGCM call. */ 445 VBOXHGCMSVCPARM paParms[4]; 446 int i = 0; 447 paParms[i++].setUInt32(pEvent->ContextID()); 448 paParms[i++].setUInt32(mData.mID /* Guest file ID */); 449 450 vrc = sendCommand(HOST_FILE_CLOSE, i, paParms); 451 if (RT_SUCCESS(vrc)) 452 vrc = waitForStatusChange(pEvent, 30 * 1000 /* Timeout in ms */, 453 NULL /* FileStatus */); 454 unregisterEvent(pEvent); 342 455 343 456 LogFlowFuncLeaveRC(vrc); … … 590 703 mData.mOpenInfo.mFileName.c_str(), mData.mOpenInfo.mOpenMode.c_str(), 591 704 mData.mOpenInfo.mDisposition.c_str(), mData.mOpenInfo.mCreationMode)); 705 int vrc; 706 707 GuestWaitEvent *pEvent = NULL; 708 std::list < VBoxEventType_T > eventTypes; 709 try 710 { 711 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged); 712 713 vrc = registerEvent(eventTypes, &pEvent); 714 } 715 catch (std::bad_alloc) 716 { 717 vrc = VERR_NO_MEMORY; 718 } 719 720 if (RT_FAILURE(vrc)) 721 return vrc; 592 722 593 723 /* Prepare HGCM call. */ 594 724 VBOXHGCMSVCPARM paParms[8]; 595 725 int i = 0; 726 paParms[i++].setUInt32(pEvent->ContextID()); 596 727 paParms[i++].setPointer((void*)mData.mOpenInfo.mFileName.c_str(), 597 728 (ULONG)mData.mOpenInfo.mFileName.length() + 1); … … 603 734 paParms[i++].setUInt64(mData.mOpenInfo.mInitialOffset); 604 735 605 intvrc = sendCommand(HOST_FILE_OPEN, i, paParms);606 if (RT_SUCCESS(vrc)) 607 vrc = waitForStatusChange( 30 * 1000 /* Timeout in ms */,736 vrc = sendCommand(HOST_FILE_OPEN, i, paParms); 737 if (RT_SUCCESS(vrc)) 738 vrc = waitForStatusChange(pEvent, 30 * 1000 /* Timeout in ms */, 608 739 NULL /* FileStatus */); 740 741 unregisterEvent(pEvent); 609 742 610 743 LogFlowFuncLeaveRC(vrc); … … 620 753 LogFlowThisFunc(("uSize=%RU32, uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n", 621 754 uSize, uTimeoutMS, pvData, cbData)); 622 623 uint32_t uContextID; 624 int vrc = generateContextID(mSession->getId(), mObjectID, 625 &uContextID); 626 if (RT_SUCCESS(vrc)) 627 { 628 /* Prepare HGCM call. */ 629 VBOXHGCMSVCPARM paParms[4]; 630 int i = 0; 631 paParms[i++].setUInt32(mData.mID /* File handle */); 632 paParms[i++].setUInt32(uSize /* Size (in bytes) to read */); 633 634 uint32_t cbRead; 635 vrc = sendCommand(HOST_FILE_READ, i, paParms); 636 if (RT_SUCCESS(vrc)) 637 vrc = waitForRead(uTimeoutMS, pvData, cbData, &cbRead); 638 639 if (RT_SUCCESS(vrc)) 640 { 641 LogFlowThisFunc(("cbRead=%RU32\n", cbRead)); 642 643 if (pcbRead) 644 *pcbRead = cbRead; 645 } 646 } 647 648 LogFlowFuncLeaveRC(vrc); 649 return vrc; 650 } 651 652 int GuestFile::readDataAt(uint64_t uOffset, uint32_t uSize, uint32_t uTimeoutMS, 653 void* pvData, size_t cbData, size_t* pcbRead) 654 { 655 LogFlowThisFunc(("uOffset=%RU64, uSize=%RU32, uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n", 656 uOffset, uSize, uTimeoutMS, pvData, cbData)); 657 658 uint32_t uContextID; 659 int vrc = generateContextID(mSession->getId(), mObjectID, 660 &uContextID); 661 if (RT_SUCCESS(vrc)) 662 { 663 664 /* Prepare HGCM call. */ 665 VBOXHGCMSVCPARM paParms[4]; 666 int i = 0; 667 paParms[i++].setUInt32(mData.mID /* File handle */); 668 paParms[i++].setUInt64(uOffset /* Offset (in bytes) to start reading */); 669 paParms[i++].setUInt32(uSize /* Size (in bytes) to read */); 670 671 uint32_t cbRead; 672 vrc = sendCommand(HOST_FILE_READ_AT, i, paParms); 673 if (RT_SUCCESS(vrc)) 674 vrc = waitForRead(uTimeoutMS, pvData, cbData, &cbRead); 675 676 if (RT_SUCCESS(vrc)) 677 { 678 LogFlowThisFunc(("cbRead=%RU32\n", cbRead)); 679 680 if (pcbRead) 681 *pcbRead = cbRead; 682 } 683 } 684 685 LogFlowFuncLeaveRC(vrc); 686 return vrc; 687 } 688 689 int GuestFile::seekAt(uint64_t uOffset, GUEST_FILE_SEEKTYPE eSeekType, 690 uint32_t uTimeoutMS, uint64_t *puOffset) 691 { 692 LogFlowThisFunc(("uOffset=%RU64, uTimeoutMS=%RU32\n", 693 uOffset, uTimeoutMS)); 755 int vrc; 756 757 GuestWaitEvent *pEvent = NULL; 758 std::list < VBoxEventType_T > eventTypes; 759 try 760 { 761 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged); 762 eventTypes.push_back(VBoxEventType_OnGuestFileRead); 763 764 vrc = registerEvent(eventTypes, &pEvent); 765 } 766 catch (std::bad_alloc) 767 { 768 vrc = VERR_NO_MEMORY; 769 } 770 771 if (RT_FAILURE(vrc)) 772 return vrc; 694 773 695 774 /* Prepare HGCM call. */ 696 775 VBOXHGCMSVCPARM paParms[4]; 697 776 int i = 0; 777 paParms[i++].setUInt32(pEvent->ContextID()); 778 paParms[i++].setUInt32(mData.mID /* File handle */); 779 paParms[i++].setUInt32(uSize /* Size (in bytes) to read */); 780 781 uint32_t cbRead; 782 vrc = sendCommand(HOST_FILE_READ, i, paParms); 783 if (RT_SUCCESS(vrc)) 784 vrc = waitForRead(pEvent, uTimeoutMS, pvData, cbData, &cbRead); 785 786 if (RT_SUCCESS(vrc)) 787 { 788 LogFlowThisFunc(("cbRead=%RU32\n", cbRead)); 789 790 if (pcbRead) 791 *pcbRead = cbRead; 792 } 793 794 unregisterEvent(pEvent); 795 796 LogFlowFuncLeaveRC(vrc); 797 return vrc; 798 } 799 800 int GuestFile::readDataAt(uint64_t uOffset, uint32_t uSize, uint32_t uTimeoutMS, 801 void* pvData, size_t cbData, size_t* pcbRead) 802 { 803 LogFlowThisFunc(("uOffset=%RU64, uSize=%RU32, uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n", 804 uOffset, uSize, uTimeoutMS, pvData, cbData)); 805 int vrc; 806 807 GuestWaitEvent *pEvent = NULL; 808 std::list < VBoxEventType_T > eventTypes; 809 try 810 { 811 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged); 812 eventTypes.push_back(VBoxEventType_OnGuestFileRead); 813 814 vrc = registerEvent(eventTypes, &pEvent); 815 } 816 catch (std::bad_alloc) 817 { 818 vrc = VERR_NO_MEMORY; 819 } 820 821 if (RT_FAILURE(vrc)) 822 return vrc; 823 824 /* Prepare HGCM call. */ 825 VBOXHGCMSVCPARM paParms[4]; 826 int i = 0; 827 paParms[i++].setUInt32(pEvent->ContextID()); 828 paParms[i++].setUInt32(mData.mID /* File handle */); 829 paParms[i++].setUInt64(uOffset /* Offset (in bytes) to start reading */); 830 paParms[i++].setUInt32(uSize /* Size (in bytes) to read */); 831 832 uint32_t cbRead; 833 vrc = sendCommand(HOST_FILE_READ_AT, i, paParms); 834 if (RT_SUCCESS(vrc)) 835 vrc = waitForRead(pEvent, uTimeoutMS, pvData, cbData, &cbRead); 836 837 if (RT_SUCCESS(vrc)) 838 { 839 LogFlowThisFunc(("cbRead=%RU32\n", cbRead)); 840 841 if (pcbRead) 842 *pcbRead = cbRead; 843 } 844 845 unregisterEvent(pEvent); 846 847 LogFlowFuncLeaveRC(vrc); 848 return vrc; 849 } 850 851 int GuestFile::seekAt(uint64_t uOffset, GUEST_FILE_SEEKTYPE eSeekType, 852 uint32_t uTimeoutMS, uint64_t *puOffset) 853 { 854 LogFlowThisFunc(("uOffset=%RU64, uTimeoutMS=%RU32\n", 855 uOffset, uTimeoutMS)); 856 int vrc; 857 858 GuestWaitEvent *pEvent = NULL; 859 std::list < VBoxEventType_T > eventTypes; 860 try 861 { 862 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged); 863 eventTypes.push_back(VBoxEventType_OnGuestFileOffsetChanged); 864 865 vrc = registerEvent(eventTypes, &pEvent); 866 } 867 catch (std::bad_alloc) 868 { 869 vrc = VERR_NO_MEMORY; 870 } 871 872 if (RT_FAILURE(vrc)) 873 return vrc; 874 875 /* Prepare HGCM call. */ 876 VBOXHGCMSVCPARM paParms[4]; 877 int i = 0; 878 paParms[i++].setUInt32(pEvent->ContextID()); 698 879 paParms[i++].setUInt32(mData.mID /* File handle */); 699 880 paParms[i++].setUInt32(eSeekType /* Seek method */); 700 881 paParms[i++].setUInt64(uOffset /* Offset (in bytes) to start reading */); 701 882 702 int vrc = sendCommand(HOST_FILE_SEEK, i, paParms); 703 if (RT_SUCCESS(vrc)) 704 vrc = waitForOffsetChange(uTimeoutMS, puOffset); 883 vrc = sendCommand(HOST_FILE_SEEK, i, paParms); 884 if (RT_SUCCESS(vrc)) 885 vrc = waitForOffsetChange(pEvent, uTimeoutMS, puOffset); 886 887 unregisterEvent(pEvent); 705 888 706 889 LogFlowFuncLeaveRC(vrc); … … 752 935 } 753 936 754 int GuestFile::waitForEvents(uint32_t uTimeoutMS, ComSafeArrayIn(VBoxEventType_T, pEvents), 755 VBoxEventType_T *pType, IEvent **ppEvent) 756 { 757 AssertPtrReturn(pType, VERR_INVALID_POINTER); 758 AssertPtrReturn(ppEvent, VERR_INVALID_POINTER); 759 760 int vrc; 761 762 /** @todo Parameter validation. */ 763 764 com::SafeArray <VBoxEventType_T> arrEventTypes(ComSafeArrayInArg(pEvents)); 765 766 ComPtr<IEventListener> pListener; 767 HRESULT hr = mEventSource->CreateListener(pListener.asOutParam()); 768 if (SUCCEEDED(hr)) 769 { 770 arrEventTypes.push_back(VBoxEventType_OnGuestFileStateChanged); 771 hr = mEventSource->RegisterListener(pListener, ComSafeArrayAsInParam(arrEventTypes), 772 FALSE /* Passive listener */); 773 } 774 else 775 vrc = VERR_COM_UNEXPECTED; 776 777 if (SUCCEEDED(hr)) 778 { 779 LogFlowThisFunc(("Waiting for guest file event(s) (timeout=%RU32ms, %zu events) ...\n", 780 uTimeoutMS, arrEventTypes.size())); 781 782 vrc = VINF_SUCCESS; 783 784 uint64_t u64Started = RTTimeMilliTS(); 785 bool fSignalled = false; 786 do 787 { 788 unsigned cMsWait; 789 if (uTimeoutMS == RT_INDEFINITE_WAIT) 790 cMsWait = 1000; 791 else 937 int GuestFile::waitForOffsetChange(GuestWaitEvent *pEvent, 938 uint32_t uTimeoutMS, uint64_t *puOffset) 939 { 940 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 941 942 VBoxEventType_T evtType; 943 ComPtr<IEvent> pIEvent; 944 int vrc = waitForEvent(pEvent, uTimeoutMS, 945 &evtType, pIEvent.asOutParam()); 946 if (RT_SUCCESS(vrc)) 947 { 948 if (evtType == VBoxEventType_OnGuestFileOffsetChanged) 949 { 950 if (puOffset) 792 951 { 793 uint64_t cMsElapsed = RTTimeMilliTS() - u64Started; 794 if (cMsElapsed >= uTimeoutMS) 795 break; /* timed out */ 796 cMsWait = RT_MIN(1000, uTimeoutMS - (uint32_t)cMsElapsed); 952 ComPtr<IGuestFileOffsetChangedEvent> pFileEvent = pIEvent; 953 Assert(!pFileEvent.isNull()); 954 955 HRESULT hr = pFileEvent->COMGETTER(Offset)((LONG64*)puOffset); 956 ComAssertComRC(hr); 797 957 } 798 799 ComPtr<IEvent> pThisEvent; 800 hr = mEventSource->GetEvent(pListener, cMsWait, pThisEvent.asOutParam()); 801 if ( SUCCEEDED(hr) 802 && !pThisEvent.isNull()) 958 } 959 else 960 vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED; 961 } 962 963 return vrc; 964 } 965 966 int GuestFile::waitForRead(GuestWaitEvent *pEvent, 967 uint32_t uTimeoutMS, void *pvData, size_t cbData, uint32_t *pcbRead) 968 { 969 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 970 971 VBoxEventType_T evtType; 972 ComPtr<IEvent> pIEvent; 973 int vrc = waitForEvent(pEvent, uTimeoutMS, 974 &evtType, pIEvent.asOutParam()); 975 if (RT_SUCCESS(vrc)) 976 { 977 if (evtType == VBoxEventType_OnGuestFileRead) 978 { 979 ComPtr<IGuestFileReadEvent> pFileEvent = pIEvent; 980 Assert(!pFileEvent.isNull()); 981 982 HRESULT hr; 983 if (pvData) 803 984 { 804 VBoxEventType_T type;805 hr = p ThisEvent->COMGETTER(Type)(&type);985 com::SafeArray <BYTE> data; 986 hr = pFileEvent->COMGETTER(Data)(ComSafeArrayAsOutParam(data)); 806 987 ComAssertComRC(hr); 807 808 for (size_t i = 0; i < arrEventTypes.size() && !fSignalled; i++) 988 size_t cbRead = data.size(); 989 if ( cbRead 990 && cbRead <= cbData) 809 991 { 810 if (type == arrEventTypes[i]) 811 { 812 switch (type) 813 { 814 case VBoxEventType_OnGuestFileStateChanged: 815 case VBoxEventType_OnGuestFileOffsetChanged: 816 case VBoxEventType_OnGuestFileRead: 817 case VBoxEventType_OnGuestFileWrite: 818 { 819 ComPtr<IGuestFileEvent> pFileEvent = pThisEvent; 820 Assert(!pFileEvent.isNull()); 821 822 ComPtr<IGuestFile> pFile; 823 pFileEvent->COMGETTER(File)(pFile.asOutParam()); 824 Assert(!pFile.isNull()); 825 826 fSignalled = (pFile == this); 827 break; 828 } 829 830 default: 831 AssertMsgFailed(("Unhandled event %ld\n", type)); 832 break; 833 } 834 835 if (fSignalled) 836 { 837 if (pType) 838 *pType = type; 839 if (ppEvent) 840 pThisEvent.queryInterfaceTo(ppEvent); 841 if ( type == VBoxEventType_OnGuestFileStateChanged 842 && RT_SUCCESS(vrc)) 843 vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED; 844 break; 845 } 846 } 992 memcpy(pvData, data.raw(), data.size()); 847 993 } 994 else 995 vrc = VERR_BUFFER_OVERFLOW; 848 996 } 849 850 } while (!fSignalled); 851 852 if ( RT_SUCCESS(vrc) 853 && !fSignalled) 854 { 855 vrc = VERR_TIMEOUT; 856 } 857 858 hr = mEventSource->UnregisterListener(pListener); 859 ComAssertComRC(hr); 860 } 861 else 862 vrc = VERR_COM_UNEXPECTED; 863 864 LogFlowFuncLeaveRC(vrc); 997 if (pcbRead) 998 { 999 hr = pFileEvent->COMGETTER(Processed)((ULONG*)pcbRead); 1000 ComAssertComRC(hr); 1001 } 1002 } 1003 else 1004 vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED; 1005 } 1006 865 1007 return vrc; 866 1008 } 867 1009 868 int GuestFile::waitForOffsetChange(uint32_t uTimeoutMS, uint64_t *puOffset) 869 { 1010 int GuestFile::waitForStatusChange(GuestWaitEvent *pEvent, 1011 uint32_t uTimeoutMS, FileStatus_T *pFileStatus) 1012 { 1013 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 1014 870 1015 VBoxEventType_T evtType; 871 ComPtr<IEvent> pEvent; 872 com::SafeArray<VBoxEventType_T> eventTypes; 873 eventTypes.push_back(VBoxEventType_OnGuestFileOffsetChanged); 874 int vrc = waitForEvents(uTimeoutMS, ComSafeArrayAsInParam(eventTypes), 875 &evtType, pEvent.asOutParam()); 876 if ( vrc == VINF_SUCCESS /* Can also return VWRN_GSTCTL_OBJECTSTATE_CHANGED. */ 877 && puOffset) 878 { 879 Assert(evtType == VBoxEventType_OnGuestFileOffsetChanged); 880 ComPtr<IGuestFileOffsetChangedEvent> pFileEvent = pEvent; 881 Assert(!pFileEvent.isNull()); 882 883 HRESULT hr = pFileEvent->COMGETTER(Offset)((LONG64*)puOffset); 884 ComAssertComRC(hr); 885 } 886 887 return vrc; 888 } 889 890 int GuestFile::waitForRead(uint32_t uTimeoutMS, void *pvData, size_t cbData, uint32_t *pcbRead) 891 { 892 VBoxEventType_T evtType; 893 ComPtr<IEvent> pEvent; 894 com::SafeArray<VBoxEventType_T> eventTypes; 895 eventTypes.push_back(VBoxEventType_OnGuestFileRead); 896 int vrc = waitForEvents(uTimeoutMS, ComSafeArrayAsInParam(eventTypes), 897 &evtType, pEvent.asOutParam()); 898 if (vrc == VINF_SUCCESS) /* Can also return VWRN_GSTCTL_OBJECTSTATE_CHANGED. */ 899 { 900 Assert(evtType == VBoxEventType_OnGuestFileRead); 901 ComPtr<IGuestFileReadEvent> pFileEvent = pEvent; 902 Assert(!pFileEvent.isNull()); 903 904 HRESULT hr; 905 if (pvData) 906 { 907 com::SafeArray <BYTE> data; 908 hr = pFileEvent->COMGETTER(Data)(ComSafeArrayAsOutParam(data)); 909 ComAssertComRC(hr); 910 size_t cbRead = data.size(); 911 if ( cbRead 912 && cbRead <= cbData) 913 { 914 memcpy(pvData, data.raw(), data.size()); 915 } 916 else 917 vrc = VERR_BUFFER_OVERFLOW; 918 } 919 if (pcbRead) 920 { 921 hr = pFileEvent->COMGETTER(Processed)((ULONG*)pcbRead); 922 ComAssertComRC(hr); 923 } 924 } 925 926 return vrc; 927 } 928 929 int GuestFile::waitForStatusChange(uint32_t uTimeoutMS, FileStatus_T *pFileStatus) 930 { 931 VBoxEventType_T evtType; 932 ComPtr<IEvent> pEvent; 933 com::SafeArray<VBoxEventType_T> eventTypes; 934 /* No own event types needed. VBoxEventType_OnGuestFileStateChanged already will 935 * part of the array when processed in waitForEvents. */ 936 int vrc = waitForEvents(uTimeoutMS, ComSafeArrayAsInParam(eventTypes), 937 &evtType, pEvent.asOutParam()); 938 if ( vrc == VINF_SUCCESS /* Can also return VWRN_GSTCTL_OBJECTSTATE_CHANGED. */ 939 && pFileStatus) 1016 ComPtr<IEvent> pIEvent; 1017 int vrc = waitForEvent(pEvent, uTimeoutMS, 1018 &evtType, pIEvent.asOutParam()); 1019 if (RT_SUCCESS(vrc)) 940 1020 { 941 1021 Assert(evtType == VBoxEventType_OnGuestFileStateChanged); 942 ComPtr<IGuestFileStateChangedEvent> pFileEvent = p Event;1022 ComPtr<IGuestFileStateChangedEvent> pFileEvent = pIEvent; 943 1023 Assert(!pFileEvent.isNull()); 944 1024 … … 950 1030 } 951 1031 952 int GuestFile::waitForWrite(uint32_t uTimeoutMS, uint32_t *pcbWritten) 953 { 1032 int GuestFile::waitForWrite(GuestWaitEvent *pEvent, 1033 uint32_t uTimeoutMS, uint32_t *pcbWritten) 1034 { 1035 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 1036 954 1037 VBoxEventType_T evtType; 955 ComPtr<IEvent> pEvent; 956 com::SafeArray<VBoxEventType_T> eventTypes; 957 eventTypes.push_back(VBoxEventType_OnGuestFileWrite); 958 int vrc = waitForEvents(uTimeoutMS, ComSafeArrayAsInParam(eventTypes), 959 &evtType, pEvent.asOutParam()); 960 if ( vrc == VINF_SUCCESS /* Can also return VWRN_GSTCTL_OBJECTSTATE_CHANGED. */ 961 && pcbWritten) 962 { 963 Assert(evtType == VBoxEventType_OnGuestFileWrite); 964 ComPtr<IGuestFileWriteEvent> pFileEvent = pEvent; 965 Assert(!pFileEvent.isNull()); 966 967 HRESULT hr = pFileEvent->COMGETTER(Processed)((ULONG*)pcbWritten); 968 ComAssertComRC(hr); 1038 ComPtr<IEvent> pIEvent; 1039 int vrc = waitForEvent(pEvent, uTimeoutMS, 1040 &evtType, pIEvent.asOutParam()); 1041 if (RT_SUCCESS(vrc)) 1042 { 1043 if (evtType == VBoxEventType_OnGuestFileWrite) 1044 { 1045 if (pcbWritten) 1046 { 1047 ComPtr<IGuestFileWriteEvent> pFileEvent = pIEvent; 1048 Assert(!pFileEvent.isNull()); 1049 1050 HRESULT hr = pFileEvent->COMGETTER(Processed)((ULONG*)pcbWritten); 1051 ComAssertComRC(hr); 1052 } 1053 } 1054 else 1055 vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED; 969 1056 } 970 1057 … … 980 1067 LogFlowThisFunc(("uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n", 981 1068 uTimeoutMS, pvData, cbData)); 982 983 uint32_t uContextID; 984 int vrc = generateContextID(mSession->getId(), mObjectID, 985 &uContextID); 986 if (RT_SUCCESS(vrc)) 987 { 988 /* Prepare HGCM call. */ 989 VBOXHGCMSVCPARM paParms[8]; 990 int i = 0; 991 paParms[i++].setUInt32(uContextID); 992 paParms[i++].setUInt32(mData.mID /* File handle */); 993 paParms[i++].setUInt32(cbData /* Size (in bytes) to write */); 994 paParms[i++].setPointer(pvData, cbData); 995 996 uint32_t cbWritten; 997 vrc = sendCommand(HOST_FILE_WRITE, i, paParms); 998 if (RT_SUCCESS(vrc)) 999 vrc = waitForWrite(uTimeoutMS, &cbWritten); 1000 1001 if (RT_SUCCESS(vrc)) 1002 { 1003 LogFlowThisFunc(("cbWritten=%RU32\n", cbWritten)); 1004 1005 if (cbWritten) 1006 *pcbWritten = cbWritten; 1007 } 1008 } 1069 int vrc; 1070 1071 GuestWaitEvent *pEvent = NULL; 1072 std::list < VBoxEventType_T > eventTypes; 1073 try 1074 { 1075 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged); 1076 eventTypes.push_back(VBoxEventType_OnGuestFileWrite); 1077 1078 vrc = registerEvent(eventTypes, &pEvent); 1079 } 1080 catch (std::bad_alloc) 1081 { 1082 vrc = VERR_NO_MEMORY; 1083 } 1084 1085 if (RT_FAILURE(vrc)) 1086 return vrc; 1087 1088 /* Prepare HGCM call. */ 1089 VBOXHGCMSVCPARM paParms[8]; 1090 int i = 0; 1091 paParms[i++].setUInt32(pEvent->ContextID()); 1092 paParms[i++].setUInt32(mData.mID /* File handle */); 1093 paParms[i++].setUInt32(cbData /* Size (in bytes) to write */); 1094 paParms[i++].setPointer(pvData, cbData); 1095 1096 uint32_t cbWritten; 1097 vrc = sendCommand(HOST_FILE_WRITE, i, paParms); 1098 if (RT_SUCCESS(vrc)) 1099 vrc = waitForWrite(pEvent, uTimeoutMS, &cbWritten); 1100 1101 if (RT_SUCCESS(vrc)) 1102 { 1103 LogFlowThisFunc(("cbWritten=%RU32\n", cbWritten)); 1104 1105 if (cbWritten) 1106 *pcbWritten = cbWritten; 1107 } 1108 1109 unregisterEvent(pEvent); 1009 1110 1010 1111 LogFlowFuncLeaveRC(vrc); … … 1020 1121 LogFlowThisFunc(("uOffset=%RU64, uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n", 1021 1122 uOffset, uTimeoutMS, pvData, cbData)); 1022 1023 uint32_t uContextID; 1024 int vrc = generateContextID(mSession->getId(), mObjectID, 1025 &uContextID); 1026 if (RT_SUCCESS(vrc)) 1027 { 1028 /* Prepare HGCM call. */ 1029 VBOXHGCMSVCPARM paParms[8]; 1030 int i = 0; 1031 paParms[i++].setUInt32(mData.mID /* File handle */); 1032 paParms[i++].setUInt64(uOffset /* Offset where to starting writing */); 1033 paParms[i++].setUInt32(cbData /* Size (in bytes) to write */); 1034 paParms[i++].setPointer(pvData, cbData); 1035 1036 uint32_t cbWritten; 1037 vrc = sendCommand(HOST_FILE_WRITE_AT, i, paParms); 1038 if (RT_SUCCESS(vrc)) 1039 vrc = waitForWrite(uTimeoutMS, &cbWritten); 1040 1041 if (RT_SUCCESS(vrc)) 1042 { 1043 LogFlowThisFunc(("cbWritten=%RU32\n", cbWritten)); 1044 1045 if (cbWritten) 1046 *pcbWritten = cbWritten; 1047 } 1048 } 1123 int vrc; 1124 1125 GuestWaitEvent *pEvent = NULL; 1126 std::list < VBoxEventType_T > eventTypes; 1127 try 1128 { 1129 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged); 1130 eventTypes.push_back(VBoxEventType_OnGuestFileWrite); 1131 1132 vrc = registerEvent(eventTypes, &pEvent); 1133 } 1134 catch (std::bad_alloc) 1135 { 1136 vrc = VERR_NO_MEMORY; 1137 } 1138 1139 if (RT_FAILURE(vrc)) 1140 return vrc; 1141 1142 /* Prepare HGCM call. */ 1143 VBOXHGCMSVCPARM paParms[8]; 1144 int i = 0; 1145 paParms[i++].setUInt32(pEvent->ContextID()); 1146 paParms[i++].setUInt32(mData.mID /* File handle */); 1147 paParms[i++].setUInt64(uOffset /* Offset where to starting writing */); 1148 paParms[i++].setUInt32(cbData /* Size (in bytes) to write */); 1149 paParms[i++].setPointer(pvData, cbData); 1150 1151 uint32_t cbWritten; 1152 vrc = sendCommand(HOST_FILE_WRITE_AT, i, paParms); 1153 if (RT_SUCCESS(vrc)) 1154 vrc = waitForWrite(pEvent, uTimeoutMS, &cbWritten); 1155 1156 if (RT_SUCCESS(vrc)) 1157 { 1158 LogFlowThisFunc(("cbWritten=%RU32\n", cbWritten)); 1159 1160 if (cbWritten) 1161 *pcbWritten = cbWritten; 1162 } 1163 1164 unregisterEvent(pEvent); 1049 1165 1050 1166 LogFlowFuncLeaveRC(vrc); -
trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp
r45697 r45780 45 45 #include <iprt/getopt.h> 46 46 47 #include <VBox/com/listeners.h> 48 47 49 #include <VBox/com/array.h> 48 50 … … 82 84 }; 83 85 86 /** 87 * Internal listener class to serve events in an 88 * active manner, e.g. without polling delays. 89 */ 90 class GuestProcessListener 91 { 92 public: 93 94 GuestProcessListener(void) 95 { 96 } 97 98 HRESULT init(GuestProcess *pProcess) 99 { 100 mProcess = pProcess; 101 return S_OK; 102 } 103 104 void uninit(void) 105 { 106 mProcess.setNull(); 107 } 108 109 STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent *aEvent) 110 { 111 switch (aType) 112 { 113 case VBoxEventType_OnGuestProcessStateChanged: 114 case VBoxEventType_OnGuestProcessInputNotify: 115 case VBoxEventType_OnGuestProcessOutput: 116 { 117 Assert(!mProcess.isNull()); 118 int rc2 = mProcess->signalWaitEvents(aType, aEvent); 119 #ifdef DEBUG_andy 120 LogFlowFunc(("Signalling events of type=%ld, process=%p resulted in rc=%Rrc\n", 121 aType, mProcess, rc2)); 122 #endif 123 break; 124 } 125 126 default: 127 AssertMsgFailed(("Unhandled event %ld\n", aType)); 128 break; 129 } 130 131 return S_OK; 132 } 133 134 private: 135 136 ComObjPtr<GuestProcess> mProcess; 137 }; 138 typedef ListenerImpl<GuestProcessListener, GuestProcess*> GuestProcessListenerImpl; 139 140 VBOX_LISTENER_DECLARE(GuestProcessListenerImpl) 141 84 142 // constructor / destructor 85 143 ///////////////////////////////////////////////////////////////////////////// … … 121 179 return VINF_SUCCESS; 122 180 #else 181 HRESULT hr; 182 123 183 int vrc = bindToSession(aConsole, aSession, aProcessID /* Object ID */); 124 184 if (RT_SUCCESS(vrc)) … … 126 186 unconst(mEventSource).createObject(); 127 187 Assert(!mEventSource.isNull()); 128 HRESULThr = mEventSource->init(static_cast<IGuestProcess*>(this));188 hr = mEventSource->init(static_cast<IGuestProcess*>(this)); 129 189 if (FAILED(hr)) 130 190 vrc = VERR_COM_UNEXPECTED; 191 } 192 193 if (RT_SUCCESS(vrc)) 194 { 195 try 196 { 197 GuestProcessListener *pListener = new GuestProcessListener(); 198 ComObjPtr<GuestProcessListenerImpl> thisListener; 199 hr = thisListener.createObject(); 200 if (SUCCEEDED(hr)) 201 hr = thisListener->init(pListener, this); 202 203 if (SUCCEEDED(hr)) 204 { 205 mListener = thisListener; 206 207 com::SafeArray <VBoxEventType_T> eventTypes; 208 eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged); 209 eventTypes.push_back(VBoxEventType_OnGuestProcessInputNotify); 210 eventTypes.push_back(VBoxEventType_OnGuestProcessOutput); 211 hr = mEventSource->RegisterListener(mListener, 212 ComSafeArrayAsInParam(eventTypes), 213 TRUE /* Active listener */); 214 if (SUCCEEDED(hr)) 215 { 216 vrc = RTCritSectInit(&mWaitEventCritSect); 217 AssertRC(vrc); 218 } 219 else 220 vrc = VERR_COM_UNEXPECTED; 221 } 222 else 223 vrc = VERR_COM_UNEXPECTED; 224 } 225 catch(std::bad_alloc &) 226 { 227 vrc = VERR_NO_MEMORY; 228 } 131 229 } 132 230 … … 169 267 #ifdef VBOX_WITH_GUEST_CONTROL 170 268 unconst(mEventSource).setNull(); 269 unregisterEventListener(); 171 270 #endif 172 271 … … 775 874 } 776 875 777 uint32_t uContextID; 778 int vrc = generateContextID(mSession->getId(), mObjectID, 779 &uContextID); 876 int vrc; 877 878 GuestWaitEvent *pEvent = NULL; 879 std::list < VBoxEventType_T > eventTypes; 880 try 881 { 882 eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged); 883 eventTypes.push_back(VBoxEventType_OnGuestProcessOutput); 884 885 vrc = registerEvent(eventTypes, &pEvent); 886 } 887 catch (std::bad_alloc) 888 { 889 vrc = VERR_NO_MEMORY; 890 } 891 892 if (RT_FAILURE(vrc)) 893 return vrc; 894 780 895 if (RT_SUCCESS(vrc)) 781 896 { 782 897 VBOXHGCMSVCPARM paParms[8]; 783 898 int i = 0; 784 paParms[i++].setUInt32( uContextID);899 paParms[i++].setUInt32(pEvent->ContextID()); 785 900 paParms[i++].setUInt32(mData.mPID); 786 901 paParms[i++].setUInt32(uHandle); … … 793 908 794 909 if (RT_SUCCESS(vrc)) 795 vrc = waitForOutput( uHandle, uTimeoutMS,910 vrc = waitForOutput(pEvent, uHandle, uTimeoutMS, 796 911 pvData, cbData, pcbRead); 912 913 unregisterEvent(pEvent); 797 914 798 915 LogFlowFuncLeaveRC(vrc); … … 857 974 mData.mStatus = ProcessStatus_Starting; 858 975 859 uint32_t uContextID; 860 int vrc = generateContextID(mSession->getId(), mObjectID, 861 &uContextID); 976 int vrc; 977 978 GuestWaitEvent *pEvent = NULL; 979 std::list < VBoxEventType_T > eventTypes; 980 try 981 { 982 eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged); 983 984 vrc = registerEvent(eventTypes, &pEvent); 985 } 986 catch (std::bad_alloc) 987 { 988 vrc = VERR_NO_MEMORY; 989 } 990 991 if (RT_FAILURE(vrc)) 992 return vrc; 993 994 GuestSession *pSession = mSession; 995 AssertPtr(pSession); 996 997 const GuestCredentials &sessionCreds = pSession->getCredentials(); 998 999 /* Prepare arguments. */ 1000 char *pszArgs = NULL; 1001 size_t cArgs = mData.mProcess.mArguments.size(); 1002 if (cArgs >= UINT32_MAX) 1003 vrc = VERR_BUFFER_OVERFLOW; 1004 1005 if ( RT_SUCCESS(vrc) 1006 && cArgs) 1007 { 1008 char **papszArgv = (char**)RTMemAlloc((cArgs + 1) * sizeof(char*)); 1009 AssertReturn(papszArgv, VERR_NO_MEMORY); 1010 1011 for (size_t i = 0; i < cArgs && RT_SUCCESS(vrc); i++) 1012 { 1013 const char *pszCurArg = mData.mProcess.mArguments[i].c_str(); 1014 AssertPtr(pszCurArg); 1015 vrc = RTStrDupEx(&papszArgv[i], pszCurArg); 1016 } 1017 papszArgv[cArgs] = NULL; 1018 1019 if (RT_SUCCESS(vrc)) 1020 vrc = RTGetOptArgvToString(&pszArgs, papszArgv, RTGETOPTARGV_CNV_QUOTE_MS_CRT); 1021 1022 if (papszArgv) 1023 { 1024 size_t i = 0; 1025 while (papszArgv[i]) 1026 RTStrFree(papszArgv[i++]); 1027 RTMemFree(papszArgv); 1028 } 1029 } 1030 1031 /* Calculate arguments size (in bytes). */ 1032 size_t cbArgs = 0; 862 1033 if (RT_SUCCESS(vrc)) 863 { 864 GuestSession *pSession = mSession; 865 AssertPtr(pSession); 866 867 const GuestCredentials &sessionCreds = pSession->getCredentials(); 868 869 /* Prepare arguments. */ 870 char *pszArgs = NULL; 871 size_t cArgs = mData.mProcess.mArguments.size(); 872 if (cArgs >= UINT32_MAX) 873 vrc = VERR_BUFFER_OVERFLOW; 874 875 if ( RT_SUCCESS(vrc) 876 && cArgs) 877 { 878 char **papszArgv = (char**)RTMemAlloc((cArgs + 1) * sizeof(char*)); 879 AssertReturn(papszArgv, VERR_NO_MEMORY); 880 881 for (size_t i = 0; i < cArgs && RT_SUCCESS(vrc); i++) 882 { 883 const char *pszCurArg = mData.mProcess.mArguments[i].c_str(); 884 AssertPtr(pszCurArg); 885 vrc = RTStrDupEx(&papszArgv[i], pszCurArg); 886 } 887 papszArgv[cArgs] = NULL; 888 889 if (RT_SUCCESS(vrc)) 890 vrc = RTGetOptArgvToString(&pszArgs, papszArgv, RTGETOPTARGV_CNV_QUOTE_MS_CRT); 891 892 if (papszArgv) 893 { 894 size_t i = 0; 895 while (papszArgv[i]) 896 RTStrFree(papszArgv[i++]); 897 RTMemFree(papszArgv); 898 } 899 } 900 901 /* Calculate arguments size (in bytes). */ 902 size_t cbArgs = 0; 903 if (RT_SUCCESS(vrc)) 904 cbArgs = pszArgs ? strlen(pszArgs) + 1 : 0; /* Include terminating zero. */ 905 906 /* Prepare environment. */ 907 void *pvEnv = NULL; 908 size_t cbEnv = 0; 909 if (RT_SUCCESS(vrc)) 910 vrc = mData.mProcess.mEnvironment.BuildEnvironmentBlock(&pvEnv, &cbEnv, NULL /* cEnv */); 911 912 uint32_t uTimeoutMS = mData.mProcess.mTimeoutMS; 913 914 if (RT_SUCCESS(vrc)) 915 { 916 AssertPtr(mSession); 917 uint32_t uProtocol = mSession->getProtocolVersion(); 918 919 /* Prepare HGCM call. */ 920 VBOXHGCMSVCPARM paParms[16]; 921 int i = 0; 922 paParms[i++].setUInt32(uContextID); 923 paParms[i++].setPointer((void*)mData.mProcess.mCommand.c_str(), 924 (ULONG)mData.mProcess.mCommand.length() + 1); 925 paParms[i++].setUInt32(mData.mProcess.mFlags); 926 paParms[i++].setUInt32(mData.mProcess.mArguments.size()); 927 paParms[i++].setPointer((void*)pszArgs, cbArgs); 928 paParms[i++].setUInt32(mData.mProcess.mEnvironment.Size()); 929 paParms[i++].setUInt32(cbEnv); 930 paParms[i++].setPointer((void*)pvEnv, cbEnv); 931 if (uProtocol < 2) 932 { 933 /* In protocol v1 (VBox < 4.3) the credentials were part of the execution 934 * call. In newer protocols these credentials are part of the opened guest 935 * session, so not needed anymore here. */ 936 paParms[i++].setPointer((void*)sessionCreds.mUser.c_str(), (ULONG)sessionCreds.mUser.length() + 1); 937 paParms[i++].setPointer((void*)sessionCreds.mPassword.c_str(), (ULONG)sessionCreds.mPassword.length() + 1); 938 } 939 /* 940 * If the WaitForProcessStartOnly flag is set, we only want to define and wait for a timeout 941 * until the process was started - the process itself then gets an infinite timeout for execution. 942 * This is handy when we want to start a process inside a worker thread within a certain timeout 943 * but let the started process perform lengthly operations then. 944 */ 945 if (mData.mProcess.mFlags & ProcessCreateFlag_WaitForProcessStartOnly) 946 paParms[i++].setUInt32(UINT32_MAX /* Infinite timeout */); 947 else 948 paParms[i++].setUInt32(uTimeoutMS); 949 if (uProtocol >= 2) 950 { 951 paParms[i++].setUInt32(mData.mProcess.mPriority); 952 /* CPU affinity: We only support one CPU affinity block at the moment, 953 * so that makes up to 64 CPUs total. This can be more in the future. */ 954 paParms[i++].setUInt32(1); 955 /* The actual CPU affinity blocks. */ 956 paParms[i++].setPointer((void*)&mData.mProcess.mAffinity, sizeof(mData.mProcess.mAffinity)); 957 } 958 959 alock.release(); /* Drop the write lock before sending. */ 960 961 /* Note: Don't hold the write lock in here. */ 962 vrc = sendCommand(HOST_EXEC_CMD, i, paParms); 963 if (RT_FAILURE(vrc)) 964 { 965 int rc2 = setProcessStatus(ProcessStatus_Error, vrc); 966 AssertRC(rc2); 967 } 968 } 969 970 GuestEnvironment::FreeEnvironmentBlock(pvEnv); 971 if (pszArgs) 972 RTStrFree(pszArgs); 973 974 if (RT_SUCCESS(vrc)) 975 { 976 vrc = waitForStatusChange(ProcessWaitForFlag_Start, uTimeoutMS, 977 NULL /* Process status */, pGuestRc); 978 } 979 } 1034 cbArgs = pszArgs ? strlen(pszArgs) + 1 : 0; /* Include terminating zero. */ 1035 1036 /* Prepare environment. */ 1037 void *pvEnv = NULL; 1038 size_t cbEnv = 0; 1039 if (RT_SUCCESS(vrc)) 1040 vrc = mData.mProcess.mEnvironment.BuildEnvironmentBlock(&pvEnv, &cbEnv, NULL /* cEnv */); 1041 1042 uint32_t uTimeoutMS = mData.mProcess.mTimeoutMS; 1043 1044 if (RT_SUCCESS(vrc)) 1045 { 1046 AssertPtr(mSession); 1047 uint32_t uProtocol = mSession->getProtocolVersion(); 1048 1049 /* Prepare HGCM call. */ 1050 VBOXHGCMSVCPARM paParms[16]; 1051 int i = 0; 1052 paParms[i++].setUInt32(pEvent->ContextID()); 1053 paParms[i++].setPointer((void*)mData.mProcess.mCommand.c_str(), 1054 (ULONG)mData.mProcess.mCommand.length() + 1); 1055 paParms[i++].setUInt32(mData.mProcess.mFlags); 1056 paParms[i++].setUInt32(mData.mProcess.mArguments.size()); 1057 paParms[i++].setPointer((void*)pszArgs, cbArgs); 1058 paParms[i++].setUInt32(mData.mProcess.mEnvironment.Size()); 1059 paParms[i++].setUInt32(cbEnv); 1060 paParms[i++].setPointer((void*)pvEnv, cbEnv); 1061 if (uProtocol < 2) 1062 { 1063 /* In protocol v1 (VBox < 4.3) the credentials were part of the execution 1064 * call. In newer protocols these credentials are part of the opened guest 1065 * session, so not needed anymore here. */ 1066 paParms[i++].setPointer((void*)sessionCreds.mUser.c_str(), (ULONG)sessionCreds.mUser.length() + 1); 1067 paParms[i++].setPointer((void*)sessionCreds.mPassword.c_str(), (ULONG)sessionCreds.mPassword.length() + 1); 1068 } 1069 /* 1070 * If the WaitForProcessStartOnly flag is set, we only want to define and wait for a timeout 1071 * until the process was started - the process itself then gets an infinite timeout for execution. 1072 * This is handy when we want to start a process inside a worker thread within a certain timeout 1073 * but let the started process perform lengthly operations then. 1074 */ 1075 if (mData.mProcess.mFlags & ProcessCreateFlag_WaitForProcessStartOnly) 1076 paParms[i++].setUInt32(UINT32_MAX /* Infinite timeout */); 1077 else 1078 paParms[i++].setUInt32(uTimeoutMS); 1079 if (uProtocol >= 2) 1080 { 1081 paParms[i++].setUInt32(mData.mProcess.mPriority); 1082 /* CPU affinity: We only support one CPU affinity block at the moment, 1083 * so that makes up to 64 CPUs total. This can be more in the future. */ 1084 paParms[i++].setUInt32(1); 1085 /* The actual CPU affinity blocks. */ 1086 paParms[i++].setPointer((void*)&mData.mProcess.mAffinity, sizeof(mData.mProcess.mAffinity)); 1087 } 1088 1089 alock.release(); /* Drop the write lock before sending. */ 1090 1091 vrc = sendCommand(HOST_EXEC_CMD, i, paParms); 1092 if (RT_FAILURE(vrc)) 1093 { 1094 int rc2 = setProcessStatus(ProcessStatus_Error, vrc); 1095 AssertRC(rc2); 1096 } 1097 } 1098 1099 GuestEnvironment::FreeEnvironmentBlock(pvEnv); 1100 if (pszArgs) 1101 RTStrFree(pszArgs); 1102 1103 if (RT_SUCCESS(vrc)) 1104 vrc = waitForStatusChange(pEvent, ProcessWaitForFlag_Start, uTimeoutMS, 1105 NULL /* Process status */, pGuestRc); 1106 unregisterEvent(pEvent); 980 1107 981 1108 LogFlowFuncLeaveRC(vrc); … … 1049 1176 return VINF_SUCCESS; /* Nothing to do (anymore). */ 1050 1177 1051 uint32_t uContextID; 1052 int vrc = generateContextID(mSession->getId(), mObjectID, 1053 &uContextID); 1178 int vrc; 1179 1180 GuestWaitEvent *pEvent = NULL; 1181 std::list < VBoxEventType_T > eventTypes; 1182 try 1183 { 1184 eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged); 1185 1186 vrc = registerEvent(eventTypes, &pEvent); 1187 } 1188 catch (std::bad_alloc) 1189 { 1190 vrc = VERR_NO_MEMORY; 1191 } 1192 1193 if (RT_FAILURE(vrc)) 1194 return vrc; 1195 1196 VBOXHGCMSVCPARM paParms[4]; 1197 int i = 0; 1198 paParms[i++].setUInt32(pEvent->ContextID()); 1199 paParms[i++].setUInt32(mData.mPID); 1200 1201 alock.release(); /* Drop the write lock before sending. */ 1202 1203 vrc = sendCommand(HOST_EXEC_TERMINATE, i, paParms); 1054 1204 if (RT_SUCCESS(vrc)) 1055 { 1056 VBOXHGCMSVCPARM paParms[4]; 1057 int i = 0; 1058 paParms[i++].setUInt32(uContextID); 1059 paParms[i++].setUInt32(mData.mPID); 1060 1061 alock.release(); /* Drop the write lock before sending. */ 1062 1063 vrc = sendCommand(HOST_EXEC_TERMINATE, i, paParms); 1064 } 1065 1066 if (RT_SUCCESS(vrc)) 1067 vrc = waitForStatusChange(ProcessWaitForFlag_Terminate, 1205 vrc = waitForStatusChange(pEvent, ProcessWaitForFlag_Terminate, 1068 1206 30 * 1000 /* 30s timeout */, 1069 1207 NULL /* ProcessStatus */, pGuestRc); 1208 unregisterEvent(pEvent); 1209 1070 1210 LogFlowFuncLeaveRC(vrc); 1071 1211 return vrc; … … 1207 1347 alock.release(); /* Release lock before waiting. */ 1208 1348 1349 int vrc; 1350 1351 GuestWaitEvent *pEvent = NULL; 1352 std::list < VBoxEventType_T > eventTypes; 1353 try 1354 { 1355 eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged); 1356 1357 vrc = registerEvent(eventTypes, &pEvent); 1358 } 1359 catch (std::bad_alloc) 1360 { 1361 vrc = VERR_NO_MEMORY; 1362 } 1363 1364 if (RT_FAILURE(vrc)) 1365 return vrc; 1366 1209 1367 ProcessStatus_T processStatus; 1210 int vrc = waitForStatusChange(fWaitFlags, uTimeoutMS, &processStatus, pGuestRc); 1368 vrc = waitForStatusChange(pEvent, fWaitFlags, 1369 uTimeoutMS, &processStatus, pGuestRc); 1211 1370 if (RT_SUCCESS(vrc)) 1212 1371 { … … 1242 1401 } 1243 1402 1403 unregisterEvent(pEvent); 1404 1244 1405 LogFlowFuncLeaveRC(vrc); 1245 1406 return vrc; 1246 1407 } 1247 1408 1248 int GuestProcess::waitForEvents(uint32_t uTimeoutMS, ComSafeArrayIn(VBoxEventType_T, pEvents), 1249 VBoxEventType_T *pType, IEvent **ppEvent) 1250 { 1251 AssertPtrReturn(pType, VERR_INVALID_POINTER); 1252 AssertPtrReturn(ppEvent, VERR_INVALID_POINTER); 1409 int GuestProcess::waitForInputNotify(GuestWaitEvent *pEvent, uint32_t uHandle, uint32_t uTimeoutMS, 1410 ProcessInputStatus_T *pInputStatus, uint32_t *pcbProcessed) 1411 { 1412 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 1413 1414 VBoxEventType_T evtType; 1415 ComPtr<IEvent> pIEvent; 1416 int vrc = waitForEvent(pEvent, uTimeoutMS, 1417 &evtType, pIEvent.asOutParam()); 1418 if (RT_SUCCESS(vrc)) 1419 { 1420 if (evtType == VBoxEventType_OnGuestProcessInputNotify) 1421 { 1422 ComPtr<IGuestProcessInputNotifyEvent> pProcessEvent = pIEvent; 1423 Assert(!pProcessEvent.isNull()); 1424 1425 if (pInputStatus) 1426 { 1427 HRESULT hr2 = pProcessEvent->COMGETTER(Status)(pInputStatus); 1428 ComAssertComRC(hr2); 1429 } 1430 if (pcbProcessed) 1431 { 1432 HRESULT hr2 = pProcessEvent->COMGETTER(Processed)((ULONG*)pcbProcessed); 1433 ComAssertComRC(hr2); 1434 } 1435 } 1436 else 1437 vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED; 1438 } 1439 1440 LogFlowFuncLeaveRC(vrc); 1441 return vrc; 1442 } 1443 1444 int GuestProcess::waitForOutput(GuestWaitEvent *pEvent, uint32_t uHandle, uint32_t uTimeoutMS, 1445 void *pvData, size_t cbData, uint32_t *pcbRead) 1446 { 1447 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 1253 1448 1254 1449 int vrc; 1255 1450 1256 /** @todo Parameter validation. */ 1257 1258 com::SafeArray <VBoxEventType_T> arrEventTypes(ComSafeArrayInArg(pEvents)); 1259 1260 ComPtr<IEventListener> pListener; 1261 HRESULT hr = mEventSource->CreateListener(pListener.asOutParam()); 1262 if (SUCCEEDED(hr)) 1263 hr = mEventSource->RegisterListener(pListener, ComSafeArrayAsInParam(arrEventTypes), 1264 FALSE /* Passive listener */); 1265 else 1266 vrc = VERR_COM_UNEXPECTED; 1267 1268 if (SUCCEEDED(hr)) 1269 { 1270 LogFlowThisFunc(("Waiting for guest process event(s) (timeout=%RU32ms, %zu events) ...\n", 1271 uTimeoutMS, arrEventTypes.size())); 1272 1273 vrc = VINF_SUCCESS; 1274 1275 uint64_t u64Started = RTTimeMilliTS(); 1276 bool fSignalled = false; 1277 do 1278 { 1279 unsigned cMsWait; 1280 if (uTimeoutMS == RT_INDEFINITE_WAIT) 1281 cMsWait = 1000; 1282 else 1451 VBoxEventType_T evtType; 1452 ComPtr<IEvent> pIEvent; 1453 do 1454 { 1455 vrc = waitForEvent(pEvent, uTimeoutMS, 1456 &evtType, pIEvent.asOutParam()); 1457 if (RT_SUCCESS(vrc)) 1458 { 1459 if (evtType == VBoxEventType_OnGuestProcessOutput) 1283 1460 { 1284 uint64_t cMsElapsed = RTTimeMilliTS() - u64Started; 1285 if (cMsElapsed >= uTimeoutMS) 1286 break; /* timed out */ 1287 cMsWait = RT_MIN(1000, uTimeoutMS - (uint32_t)cMsElapsed); 1288 } 1289 1290 ComPtr<IEvent> pThisEvent; 1291 hr = mEventSource->GetEvent(pListener, cMsWait, pThisEvent.asOutParam()); 1292 if ( SUCCEEDED(hr) 1293 && !pThisEvent.isNull()) 1294 { 1295 VBoxEventType_T type; 1296 hr = pThisEvent->COMGETTER(Type)(&type); 1297 ComAssertComRC(hr); 1298 1299 for (size_t i = 0; i < arrEventTypes.size() && !fSignalled; i++) 1461 ComPtr<IGuestProcessOutputEvent> pProcessEvent = pIEvent; 1462 Assert(!pProcessEvent.isNull()); 1463 1464 ULONG uHandleEvent; 1465 HRESULT hr = pProcessEvent->COMGETTER(Handle)(&uHandleEvent); 1466 if (uHandleEvent == uHandle) 1300 1467 { 1301 if ( type == arrEventTypes[i])1468 if (pvData) 1302 1469 { 1303 switch (type) 1470 com::SafeArray <BYTE> data; 1471 hr = pProcessEvent->COMGETTER(Data)(ComSafeArrayAsOutParam(data)); 1472 ComAssertComRC(hr); 1473 size_t cbRead = data.size(); 1474 if (cbRead) 1304 1475 { 1305 case VBoxEventType_OnGuestProcessStateChanged: 1306 case VBoxEventType_OnGuestProcessInputNotify: 1307 case VBoxEventType_OnGuestProcessOutput: 1476 if (cbRead <= cbData) 1308 1477 { 1309 ComPtr<IGuestProcessEvent> pFileEvent = pThisEvent; 1310 Assert(!pFileEvent.isNull()); 1311 1312 ComPtr<IGuestProcess> pProcess; 1313 pFileEvent->COMGETTER(Process)(pProcess.asOutParam()); 1314 Assert(!pProcess.isNull()); 1315 1316 fSignalled = (pProcess == this); 1317 break; 1478 /* Copy data from event into our buffer. */ 1479 memcpy(pvData, data.raw(), data.size()); 1318 1480 } 1319 1320 default: 1321 AssertMsgFailed(("Unhandled event %ld\n", type)); 1322 break; 1323 } 1324 1325 if (fSignalled) 1326 { 1327 if (pType) 1328 *pType = type; 1329 if (ppEvent) 1330 pThisEvent.queryInterfaceTo(ppEvent); 1331 if ( type == VBoxEventType_OnGuestProcessStateChanged 1332 && RT_SUCCESS(vrc)) 1333 vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED; 1334 break; 1481 else 1482 vrc = VERR_BUFFER_OVERFLOW; 1335 1483 } 1336 1484 } 1485 if (pcbRead) 1486 { 1487 ULONG cbRead; 1488 hr = pProcessEvent->COMGETTER(Processed)(&cbRead); 1489 ComAssertComRC(hr); 1490 *pcbRead = (uint32_t)cbRead; 1491 } 1492 1493 break; 1337 1494 } 1338 1495 } 1339 1340 } while (!fSignalled); 1341 1342 if ( RT_SUCCESS(vrc) 1343 && !fSignalled) 1344 { 1345 vrc = VERR_TIMEOUT; 1346 } 1347 1348 hr = mEventSource->UnregisterListener(pListener); 1349 ComAssertComRC(hr); 1350 } 1351 else 1352 vrc = VERR_COM_UNEXPECTED; 1496 else 1497 vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED; 1498 } 1499 1500 } while (RT_SUCCESS(vrc)); 1353 1501 1354 1502 LogFlowFuncLeaveRC(vrc); … … 1356 1504 } 1357 1505 1358 int GuestProcess::waitForInputNotify(uint32_t uHandle, uint32_t uTimeoutMS, 1359 ProcessInputStatus_T *pInputStatus, uint32_t *pcbProcessed) 1360 { 1506 int GuestProcess::waitForStatusChange(GuestWaitEvent *pEvent, uint32_t fWaitFlags, uint32_t uTimeoutMS, 1507 ProcessStatus_T *pProcessStatus, int *pGuestRc) 1508 { 1509 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 1510 1361 1511 VBoxEventType_T evtType; 1362 ComPtr<IEvent> pEvent; 1363 com::SafeArray<VBoxEventType_T> eventTypes; 1364 eventTypes.push_back(VBoxEventType_OnGuestProcessInputNotify); 1365 int vrc = waitForEvents(uTimeoutMS, ComSafeArrayAsInParam(eventTypes), 1366 &evtType, pEvent.asOutParam()); 1367 if (vrc == VINF_SUCCESS) /* Can also return VWRN_GSTCTL_OBJECTSTATE_CHANGED. */ 1368 { 1369 Assert(evtType == VBoxEventType_OnGuestProcessInputNotify); 1370 ComPtr<IGuestProcessInputNotifyEvent> pProcessEvent = pEvent; 1371 Assert(!pProcessEvent.isNull()); 1372 1373 if (pInputStatus) 1374 { 1375 HRESULT hr2 = pProcessEvent->COMGETTER(Status)(pInputStatus); 1376 ComAssertComRC(hr2); 1377 } 1378 if (pcbProcessed) 1379 { 1380 HRESULT hr2 = pProcessEvent->COMGETTER(Processed)((ULONG*)pcbProcessed); 1381 ComAssertComRC(hr2); 1382 } 1383 } 1384 1385 LogFlowFuncLeaveRC(vrc); 1386 return vrc; 1387 } 1388 1389 int GuestProcess::waitForOutput(uint32_t uHandle, uint32_t uTimeoutMS, 1390 void *pvData, size_t cbData, uint32_t *pcbRead) 1391 { 1392 VBoxEventType_T evtType; 1393 ComPtr<IEvent> pEvent; 1394 com::SafeArray<VBoxEventType_T> eventTypes; 1395 1396 int vrc = VINF_SUCCESS; 1397 1398 try 1399 { 1400 eventTypes.push_back(VBoxEventType_OnGuestProcessOutput); 1401 } 1402 catch (std::bad_alloc) 1403 { 1404 vrc = VERR_NO_MEMORY; 1405 } 1406 1407 if (RT_FAILURE(vrc)) 1408 return vrc; 1409 1410 do 1411 { 1412 vrc = waitForEvents(uTimeoutMS, ComSafeArrayAsInParam(eventTypes), 1413 &evtType, pEvent.asOutParam()); 1414 if (vrc == VINF_SUCCESS) /* Can also return VWRN_GSTCTL_OBJECTSTATE_CHANGED. */ 1415 { 1416 Assert(evtType == VBoxEventType_OnGuestProcessOutput); 1417 ComPtr<IGuestProcessOutputEvent> pProcessEvent = pEvent; 1418 Assert(!pProcessEvent.isNull()); 1419 1420 ULONG uHandleEvent; 1421 HRESULT hr = pProcessEvent->COMGETTER(Handle)(&uHandleEvent); 1422 if (uHandleEvent == uHandle) 1423 { 1424 if (pvData) 1425 { 1426 com::SafeArray <BYTE> data; 1427 hr = pProcessEvent->COMGETTER(Data)(ComSafeArrayAsOutParam(data)); 1428 ComAssertComRC(hr); 1429 size_t cbRead = data.size(); 1430 if (cbRead) 1431 { 1432 if (cbRead <= cbData) 1433 { 1434 /* Copy data from event into our buffer. */ 1435 memcpy(pvData, data.raw(), data.size()); 1436 } 1437 else 1438 vrc = VERR_BUFFER_OVERFLOW; 1439 } 1440 } 1441 if (pcbRead) 1442 { 1443 ULONG cbRead; 1444 hr = pProcessEvent->COMGETTER(Processed)(&cbRead); 1445 ComAssertComRC(hr); 1446 *pcbRead = (uint32_t)cbRead; 1447 } 1448 1449 break; 1450 } 1451 } 1452 1453 } while (RT_SUCCESS(vrc)); 1454 1455 LogFlowFuncLeaveRC(vrc); 1456 return vrc; 1457 } 1458 1459 int GuestProcess::waitForStatusChange(uint32_t fWaitFlags, uint32_t uTimeoutMS, 1460 ProcessStatus_T *pProcessStatus, int *pGuestRc) 1461 { 1462 /* All pointers are optional. */ 1463 1464 VBoxEventType_T evtType; 1465 ComPtr<IEvent> pEvent; 1466 com::SafeArray<VBoxEventType_T> eventTypes(1); 1467 eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged); 1468 int vrc = waitForEvents(uTimeoutMS, ComSafeArrayAsInParam(eventTypes), 1469 &evtType, pEvent.asOutParam()); 1470 if (RT_SUCCESS(vrc)) /* Includes VWRN_GSTCTL_OBJECTSTATE_CHANGED. */ 1512 ComPtr<IEvent> pIEvent; 1513 int vrc = waitForEvent(pEvent, uTimeoutMS, 1514 &evtType, pIEvent.asOutParam()); 1515 if (RT_SUCCESS(vrc)) 1471 1516 { 1472 1517 Assert(evtType == VBoxEventType_OnGuestProcessStateChanged); 1473 ComPtr<IGuestProcessStateChangedEvent> pProcessEvent = p Event;1518 ComPtr<IGuestProcessStateChangedEvent> pProcessEvent = pIEvent; 1474 1519 Assert(!pProcessEvent.isNull()); 1475 1520 … … 1517 1562 } 1518 1563 1519 uint32_t uContextID; 1520 int vrc = generateContextID(mSession->getId(), mObjectID, 1521 &uContextID); 1522 if (RT_SUCCESS(vrc)) 1523 { 1524 VBOXHGCMSVCPARM paParms[5]; 1525 1526 int i = 0; 1527 paParms[i++].setUInt32(uContextID); 1528 paParms[i++].setUInt32(mData.mPID); 1529 paParms[i++].setUInt32(uFlags); 1530 paParms[i++].setPointer(pvData, cbData); 1531 paParms[i++].setUInt32(cbData); 1532 1533 alock.release(); /* Drop the write lock before sending. */ 1534 1535 vrc = sendCommand(HOST_EXEC_SET_INPUT, i, paParms); 1536 } 1537 1564 int vrc; 1565 1566 GuestWaitEvent *pEvent = NULL; 1567 std::list < VBoxEventType_T > eventTypes; 1568 try 1569 { 1570 eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged); 1571 eventTypes.push_back(VBoxEventType_OnGuestProcessInputNotify); 1572 1573 vrc = registerEvent(eventTypes, &pEvent); 1574 } 1575 catch (std::bad_alloc) 1576 { 1577 vrc = VERR_NO_MEMORY; 1578 } 1579 1580 if (RT_FAILURE(vrc)) 1581 return vrc; 1582 1583 VBOXHGCMSVCPARM paParms[5]; 1584 int i = 0; 1585 paParms[i++].setUInt32(pEvent->ContextID()); 1586 paParms[i++].setUInt32(mData.mPID); 1587 paParms[i++].setUInt32(uFlags); 1588 paParms[i++].setPointer(pvData, cbData); 1589 paParms[i++].setUInt32(cbData); 1590 1591 alock.release(); /* Drop the write lock before sending. */ 1592 1593 vrc = sendCommand(HOST_EXEC_SET_INPUT, i, paParms); 1538 1594 if (RT_SUCCESS(vrc)) 1539 1595 { 1540 1596 ProcessInputStatus_T inputStatus; 1541 1597 uint32_t cbProcessed; 1542 vrc = waitForInputNotify( uHandle, uTimeoutMS, &inputStatus, &cbProcessed);1598 vrc = waitForInputNotify(pEvent, uHandle, uTimeoutMS, &inputStatus, &cbProcessed); 1543 1599 if (RT_SUCCESS(vrc)) 1544 1600 { … … 1550 1606 /** @todo Error handling. */ 1551 1607 } 1608 1609 unregisterEvent(pEvent); 1552 1610 1553 1611 LogFlowFuncLeaveRC(vrc); -
trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp
r45697 r45780 84 84 }; 85 85 86 /** 87 * Internal listener class to serve events in an 88 * active manner, e.g. without polling delays. 89 */ 90 class GuestSessionListener 91 { 92 public: 93 94 GuestSessionListener(void) 95 { 96 } 97 98 HRESULT init(GuestSession *pSession) 99 { 100 mSession = pSession; 101 return S_OK; 102 } 103 104 void uninit(void) 105 { 106 mSession.setNull(); 107 } 108 109 STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent *aEvent) 110 { 111 switch (aType) 112 { 113 case VBoxEventType_OnGuestSessionStateChanged: 114 { 115 Assert(!mSession.isNull()); 116 int rc2 = mSession->signalWaitEvents(aType, aEvent); 117 #ifdef DEBUG_andy 118 LogFlowFunc(("Signalling events of type=%ld, session=%p resulted in rc=%Rrc\n", 119 aType, mSession, rc2)); 120 #endif 121 break; 122 } 123 124 default: 125 AssertMsgFailed(("Unhandled event %ld\n", aType)); 126 break; 127 } 128 129 return S_OK; 130 } 131 132 private: 133 134 ComObjPtr<GuestSession> mSession; 135 }; 136 typedef ListenerImpl<GuestSessionListener, GuestSession*> GuestSessionListenerImpl; 137 138 VBOX_LISTENER_DECLARE(GuestProcessListenerImpl) 139 86 140 // constructor / destructor 87 141 ///////////////////////////////////////////////////////////////////////////// … … 148 202 mData.mNumObjects = 0; 149 203 204 HRESULT hr; 205 150 206 int rc = queryInfo(); 151 207 if (RT_SUCCESS(rc)) … … 160 216 if (RT_SUCCESS(rc)) 161 217 { 218 try 219 { 220 GuestSessionListener *pListener = new GuestSessionListener(); 221 ComObjPtr<GuestSessionListenerImpl> thisListener; 222 hr = thisListener.createObject(); 223 if (SUCCEEDED(hr)) 224 hr = thisListener->init(pListener, this); 225 226 if (SUCCEEDED(hr)) 227 { 228 mListener = thisListener; 229 230 com::SafeArray <VBoxEventType_T> eventTypes; 231 eventTypes.push_back(VBoxEventType_OnGuestSessionStateChanged); 232 hr = mEventSource->RegisterListener(mListener, 233 ComSafeArrayAsInParam(eventTypes), 234 TRUE /* Active listener */); 235 if (SUCCEEDED(hr)) 236 { 237 rc = RTCritSectInit(&mWaitEventCritSect); 238 AssertRC(rc); 239 } 240 else 241 rc = VERR_COM_UNEXPECTED; 242 } 243 else 244 rc = VERR_COM_UNEXPECTED; 245 } 246 catch(std::bad_alloc &) 247 { 248 rc = VERR_NO_MEMORY; 249 } 250 } 251 252 if (RT_SUCCESS(rc)) 253 { 162 254 /* Confirm a successful initialization when it's the case. */ 163 255 autoInitSpan.setSucceeded(); … … 217 309 218 310 unconst(mEventSource).setNull(); 311 unregisterEventListener(); 219 312 220 313 #endif /* VBOX_WITH_GUEST_CONTROL */ … … 537 630 return VINF_SUCCESS; 538 631 539 uint32_t uContextID; 540 int vrc = generateContextID(mData.mSession.mID, 0 /* Object ID */, 541 &uContextID); 632 int vrc; 633 634 GuestWaitEvent *pEvent = NULL; 635 std::list < VBoxEventType_T > eventTypes; 636 try 637 { 638 eventTypes.push_back(VBoxEventType_OnGuestSessionStateChanged); 639 640 vrc = registerEvent(mData.mSession.mID, 0 /* Object ID */, 641 eventTypes, &pEvent); 642 } 643 catch (std::bad_alloc) 644 { 645 vrc = VERR_NO_MEMORY; 646 } 647 648 if (RT_FAILURE(vrc)) 649 return vrc; 650 651 LogFlowThisFunc(("Sending closing request to guest session ID=%RU32, uFlags=%x\n", 652 mData.mSession.mID, uFlags)); 653 654 VBOXHGCMSVCPARM paParms[4]; 655 int i = 0; 656 paParms[i++].setUInt32(pEvent->ContextID()); 657 paParms[i++].setUInt32(uFlags); 658 659 vrc = sendCommand(HOST_SESSION_CLOSE, i, paParms); 542 660 if (RT_SUCCESS(vrc)) 543 661 { 544 if (RT_SUCCESS(vrc)) 545 { 546 LogFlowThisFunc(("Sending closing request to guest session ID=%RU32, uFlags=%x\n", 547 mData.mSession.mID, uFlags)); 548 549 VBOXHGCMSVCPARM paParms[4]; 550 int i = 0; 551 paParms[i++].setUInt32(uContextID); 552 paParms[i++].setUInt32(uFlags); 553 554 vrc = sendCommand(HOST_SESSION_CLOSE, i, paParms); 555 } 556 557 if (RT_SUCCESS(vrc)) 558 { 559 alock.release(); /* Drop the write lock before waiting. */ 560 561 vrc = waitForStateChange(GuestSessionWaitForFlag_Terminate, uTimeoutMS, 562 NULL /* Session status */, pGuestRc); 563 } 564 } 662 alock.release(); /* Drop the write lock before waiting. */ 663 664 vrc = waitForStatusChange(pEvent, GuestSessionWaitForFlag_Terminate, uTimeoutMS, 665 NULL /* Session status */, pGuestRc); 666 } 667 668 unregisterEvent(pEvent); 565 669 566 670 LogFlowFuncLeaveRC(vrc); … … 1241 1345 mData.mStatus = GuestSessionStatus_Starting; 1242 1346 1243 uint32_t uContextID; 1244 int vrc = generateContextID(mData.mSession.mID, 0 /* Object ID */, 1245 &uContextID); 1347 int vrc; 1348 1349 GuestWaitEvent *pEvent = NULL; 1350 std::list < VBoxEventType_T > eventTypes; 1351 try 1352 { 1353 eventTypes.push_back(VBoxEventType_OnGuestSessionStateChanged); 1354 1355 vrc = registerEvent(mData.mSession.mID, 0 /* Object ID */, 1356 eventTypes, &pEvent); 1357 } 1358 catch (std::bad_alloc) 1359 { 1360 vrc = VERR_NO_MEMORY; 1361 } 1362 1363 if (RT_FAILURE(vrc)) 1364 return vrc; 1365 1366 VBOXHGCMSVCPARM paParms[8]; 1367 1368 int i = 0; 1369 paParms[i++].setUInt32(pEvent->ContextID()); 1370 paParms[i++].setUInt32(mData.mProtocolVersion); 1371 paParms[i++].setPointer((void*)mData.mCredentials.mUser.c_str(), 1372 (ULONG)mData.mCredentials.mUser.length() + 1); 1373 paParms[i++].setPointer((void*)mData.mCredentials.mPassword.c_str(), 1374 (ULONG)mData.mCredentials.mPassword.length() + 1); 1375 paParms[i++].setPointer((void*)mData.mCredentials.mDomain.c_str(), 1376 (ULONG)mData.mCredentials.mDomain.length() + 1); 1377 paParms[i++].setUInt32(mData.mSession.mOpenFlags); 1378 1379 vrc = sendCommand(HOST_SESSION_CREATE, i, paParms); 1246 1380 if (RT_SUCCESS(vrc)) 1247 1381 { 1248 VBOXHGCMSVCPARM paParms[8];1249 1250 int i = 0;1251 paParms[i++].setUInt32(uContextID);1252 paParms[i++].setUInt32(mData.mProtocolVersion);1253 paParms[i++].setPointer((void*)mData.mCredentials.mUser.c_str(),1254 (ULONG)mData.mCredentials.mUser.length() + 1);1255 paParms[i++].setPointer((void*)mData.mCredentials.mPassword.c_str(),1256 (ULONG)mData.mCredentials.mPassword.length() + 1);1257 paParms[i++].setPointer((void*)mData.mCredentials.mDomain.c_str(),1258 (ULONG)mData.mCredentials.mDomain.length() + 1);1259 paParms[i++].setUInt32(mData.mSession.mOpenFlags);1260 1261 vrc = sendCommand(HOST_SESSION_CREATE, i, paParms);1262 }1263 1264 if (RT_SUCCESS(vrc))1265 {1266 1382 alock.release(); /* Drop write lock before waiting. */ 1267 1383 1268 vrc = waitForStateChange(GuestSessionWaitForFlag_Start, 30 * 1000 /* 30s timeout */, 1269 NULL /* Session status */, pGuestRc); 1270 } 1384 vrc = waitForStatusChange(pEvent, GuestSessionWaitForFlag_Start, 1385 30 * 1000 /* 30s timeout */, 1386 NULL /* Session status */, pGuestRc); 1387 } 1388 1389 unregisterEvent(pEvent); 1271 1390 1272 1391 LogFlowFuncLeaveRC(vrc); … … 1782 1901 alock.release(); /* Release lock before waiting. */ 1783 1902 1903 int vrc; 1904 1905 GuestWaitEvent *pEvent = NULL; 1906 std::list < VBoxEventType_T > eventTypes; 1907 try 1908 { 1909 eventTypes.push_back(VBoxEventType_OnGuestSessionStateChanged); 1910 1911 vrc = registerEvent(mData.mSession.mID, 0 /* Object ID */, 1912 eventTypes, &pEvent); 1913 } 1914 catch (std::bad_alloc) 1915 { 1916 vrc = VERR_NO_MEMORY; 1917 } 1918 1919 if (RT_FAILURE(vrc)) 1920 return vrc; 1921 1784 1922 GuestSessionStatus_T sessionStatus; 1785 int vrc = waitForStateChange(fWaitFlags, uTimeoutMS, &sessionStatus, pGuestRc); 1923 vrc = waitForStatusChange(pEvent, fWaitFlags, 1924 uTimeoutMS, &sessionStatus, pGuestRc); 1786 1925 if (RT_SUCCESS(vrc)) 1787 1926 { … … 1815 1954 } 1816 1955 1956 unregisterEvent(pEvent); 1957 1817 1958 LogFlowFuncLeaveRC(vrc); 1818 1959 return vrc; 1819 1960 } 1820 1961 1821 int GuestSession::waitForStateChange(uint32_t fWaitFlags, uint32_t uTimeoutMS, 1822 GuestSessionStatus_T *pSessionStatus, int *pGuestRc) 1823 { 1824 /** @todo Param validation. */ 1825 1826 int vrc; 1827 1828 ComPtr<IEventListener> pListener; 1829 HRESULT hr = mEventSource->CreateListener(pListener.asOutParam()); 1830 if (SUCCEEDED(hr)) 1831 { 1832 com::SafeArray <VBoxEventType_T> eventTypes(1); 1833 eventTypes.push_back(VBoxEventType_OnGuestSessionStateChanged); 1834 hr = mEventSource->RegisterListener(pListener, ComSafeArrayAsInParam(eventTypes), false); 1835 } 1836 else 1837 vrc = VERR_COM_UNEXPECTED; 1838 1839 if (SUCCEEDED(hr)) 1840 { 1841 LogFlowThisFunc(("Waiting for guest session state changed event (timeout=%RU32ms, flags=%x) ...\n", 1842 uTimeoutMS, fWaitFlags)); 1843 1844 vrc = VINF_SUCCESS; 1845 1846 uint64_t u64Started = RTTimeMilliTS(); 1847 bool fSignalled = false; 1848 do 1849 { 1850 unsigned cMsWait; 1851 if (uTimeoutMS == RT_INDEFINITE_WAIT) 1852 cMsWait = 1000; 1853 else 1854 { 1855 uint64_t cMsElapsed = RTTimeMilliTS() - u64Started; 1856 if (cMsElapsed >= uTimeoutMS) 1857 break; /* timed out */ 1858 cMsWait = RT_MIN(1000, uTimeoutMS - (uint32_t)cMsElapsed); 1859 } 1860 1861 ComPtr<IEvent> pEvent; 1862 hr = mEventSource->GetEvent(pListener, cMsWait, pEvent.asOutParam()); 1863 if ( SUCCEEDED(hr) 1864 && !pEvent.isNull()) 1865 { 1866 VBoxEventType_T aType; 1867 hr = pEvent->COMGETTER(Type)(&aType); 1868 ComAssertComRC(hr); 1869 switch (aType) 1870 { 1871 case VBoxEventType_OnGuestSessionStateChanged: 1872 { 1873 ComPtr<IGuestSessionStateChangedEvent> pChangedEvent = pEvent; 1874 Assert(!pChangedEvent.isNull()); 1875 1876 ULONG uSessionID; 1877 pChangedEvent->COMGETTER(Id)(&uSessionID); 1878 if (uSessionID != mData.mSession.mID) 1879 continue; /* Only our own session is of interest. */ 1880 1881 GuestSessionStatus_T sessionStatus; 1882 pChangedEvent->COMGETTER(Status)(&sessionStatus); 1883 if (pSessionStatus) 1884 *pSessionStatus = sessionStatus; 1885 1886 LogFlowThisFunc(("Got status changed event for session ID=%RU32: %ld\n", 1887 mData.mSession.mID, sessionStatus)); 1888 1889 bool fSignal = false; 1890 if (fWaitFlags) 1891 { 1892 switch (sessionStatus) 1893 { 1894 case GuestSessionStatus_Started: 1895 fSignal = ( fWaitFlags & GuestSessionWaitForFlag_Start 1896 || fWaitFlags & GuestSessionWaitForFlag_Status); 1897 break; 1898 1899 default: 1900 fSignal = true; 1901 break; 1902 } 1903 } 1904 else 1905 fSignal = true; 1906 1907 if (!fSignal) 1908 continue; 1909 1910 ComPtr<IGuestErrorInfo> errorInfo; 1911 hr = pChangedEvent->COMGETTER(Error)(errorInfo.asOutParam()); 1912 ComAssertComRC(hr); 1913 1914 LONG lGuestRc; 1915 hr = errorInfo->COMGETTER(Result)(&lGuestRc); 1916 ComAssertComRC(hr); 1917 if (RT_FAILURE((int)lGuestRc)) 1918 vrc = VERR_GSTCTL_GUEST_ERROR; 1919 if (pGuestRc) 1920 *pGuestRc = (int)lGuestRc; 1921 1922 LogFlowThisFunc(("Status changed event for session ID=%RU32: %ld (%Rrc)\n", 1923 mData.mSession.mID, sessionStatus, 1924 RT_SUCCESS((int)lGuestRc) ? VINF_SUCCESS : (int)lGuestRc)); 1925 1926 fSignalled = true; 1927 break; 1928 } 1929 1930 default: 1931 AssertMsgFailed(("Unhandled event type %ld\n", aType)); 1932 break; 1933 } 1934 } 1935 1936 } while (!fSignalled); 1937 1938 if ( RT_SUCCESS(vrc) 1939 && !fSignalled) 1940 { 1941 vrc = VERR_TIMEOUT; 1942 } 1943 1944 mEventSource->UnregisterListener(pListener); 1945 } 1946 else 1947 vrc = VERR_COM_UNEXPECTED; 1962 int GuestSession::waitForStatusChange(GuestWaitEvent *pEvent, uint32_t fWaitFlags, uint32_t uTimeoutMS, 1963 GuestSessionStatus_T *pSessionStatus, int *pGuestRc) 1964 { 1965 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 1966 1967 VBoxEventType_T evtType; 1968 ComPtr<IEvent> pIEvent; 1969 int vrc = waitForEvent(pEvent, uTimeoutMS, 1970 &evtType, pIEvent.asOutParam()); 1971 if (RT_SUCCESS(vrc)) 1972 { 1973 Assert(evtType == VBoxEventType_OnGuestSessionStateChanged); 1974 1975 ComPtr<IGuestSessionStateChangedEvent> pChangedEvent = pIEvent; 1976 Assert(!pChangedEvent.isNull()); 1977 1978 GuestSessionStatus_T sessionStatus; 1979 pChangedEvent->COMGETTER(Status)(&sessionStatus); 1980 if (pSessionStatus) 1981 *pSessionStatus = sessionStatus; 1982 1983 ComPtr<IGuestErrorInfo> errorInfo; 1984 HRESULT hr = pChangedEvent->COMGETTER(Error)(errorInfo.asOutParam()); 1985 ComAssertComRC(hr); 1986 1987 LONG lGuestRc; 1988 hr = errorInfo->COMGETTER(Result)(&lGuestRc); 1989 ComAssertComRC(hr); 1990 if (RT_FAILURE((int)lGuestRc)) 1991 vrc = VERR_GSTCTL_GUEST_ERROR; 1992 if (pGuestRc) 1993 *pGuestRc = (int)lGuestRc; 1994 1995 LogFlowThisFunc(("Status changed event for session ID=%RU32: %ld (%Rrc)\n", 1996 mData.mSession.mID, sessionStatus, 1997 RT_SUCCESS((int)lGuestRc) ? VINF_SUCCESS : (int)lGuestRc)); 1998 } 1948 1999 1949 2000 LogFlowFuncLeaveRC(vrc);
Note:
See TracChangeset
for help on using the changeset viewer.