Changeset 49349 in vbox for trunk/src/VBox/Main/src-client
- Timestamp:
- Oct 31, 2013 4:40:46 PM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 90367
- Location:
- trunk/src/VBox/Main/src-client
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp
r48342 r49349 297 297 break; 298 298 299 case GUEST_SESSION_NOTIFY:300 rc = pSession->dispatchToThis(pCtxCb, pSvcCb);301 break;302 303 299 case GUEST_EXEC_STATUS: 304 300 case GUEST_EXEC_OUTPUT: … … 312 308 break; 313 309 310 case GUEST_SESSION_NOTIFY: 311 rc = pSession->dispatchToThis(pCtxCb, pSvcCb); 312 break; 313 314 314 default: 315 rc = VERR_NOT_SUPPORTED; 315 rc = pSession->dispatchToObject(pCtxCb, pSvcCb); 316 if (rc == VERR_NOT_FOUND) 317 { 318 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 319 320 rc = pSession->dispatchGeneric(pCtxCb, pSvcCb); 321 } 322 #ifndef DEBUG_andy 323 if (rc == VERR_NOT_IMPLEMENTED) 324 AssertMsgFailed(("Received not handled function %RU32\n", pCtxCb->uFunction)); 325 #endif 316 326 break; 317 327 } … … 323 333 rc = VERR_NOT_FOUND; 324 334 325 LogFlow ThisFunc(("Returning rc=%Rrc\n", rc));335 LogFlowFuncLeaveRC(rc); 326 336 return rc; 327 337 } … … 329 339 int Guest::sessionRemove(GuestSession *pSession) 330 340 { 341 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 342 331 343 LogFlowThisFuncEnter(); 332 344 … … 364 376 } 365 377 366 LogFlow ThisFunc(("Returning rc=%Rrc\n", rc));378 LogFlowFuncLeaveRC(rc); 367 379 return rc; 368 380 } … … 445 457 } 446 458 447 LogFlow ThisFunc(("Returning rc=%Rrc\n", rc));459 LogFlowFuncLeaveRC(rc); 448 460 return rc; 449 461 } -
trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp
r47627 r49349 680 680 681 681 /** 682 * Returns the current offset of the parser within683 * the internal data buffer.684 *685 * @return uint32_t Parser offset.686 */687 uint32_t GuestProcessStream::GetOffset()688 {689 return m_cbOffset;690 }691 692 uint32_t GuestProcessStream::GetSize()693 {694 return m_cbSize;695 }696 697 /**698 682 * Tries to parse the next upcoming pair block within the internal 699 683 * buffer. … … 814 798 if (RT_SUCCESS(rc)) 815 799 { 816 Guest WaitEventTypes::iterator itEventTypes = mWaitEvents.begin();817 while (itEvent Types != mWaitEvents.end())818 { 819 GuestWaitEvents::iterator itEvents = itEvent Types->second.begin();820 while (itEvents != itEvent Types->second.end())800 GuestEventGroup::iterator itEventGroups = mWaitEventGroups.begin(); 801 while (itEventGroups != mWaitEventGroups.end()) 802 { 803 GuestWaitEvents::iterator itEvents = itEventGroups->second.begin(); 804 while (itEvents != itEventGroups->second.end()) 821 805 { 822 GuestWaitEvent *pEvent = (*itEvents);806 GuestWaitEvent *pEvent = itEvents->second; 823 807 AssertPtr(pEvent); 824 808 825 809 /* 826 * Just cancel the event and remove it from the wait events827 * map. Don't delete it though, this (hopefully) is done by828 * the caller using unregisterWaitEvent().810 * Just cancel the event, but don't remove it from the 811 * wait events map. Don't delete it though, this (hopefully) 812 * is done by the caller using unregisterWaitEvent(). 829 813 */ 830 int rc2 = pEvent-> Signal(NULL /* Cancel */);814 int rc2 = pEvent->Cancel(); 831 815 AssertRC(rc2); 832 itEvents = itEventTypes->second.erase(itEvents); 816 817 itEvents++; 833 818 } 834 819 835 mWaitEvents.erase(itEventTypes); 836 itEventTypes = mWaitEvents.begin(); 820 itEventGroups++; 837 821 } 838 822 … … 846 830 } 847 831 832 int GuestBase::dispatchGeneric(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb) 833 { 834 LogFlowFunc(("pCtxCb=%p, pSvcCb=%p\n", pCtxCb, pSvcCb)); 835 836 AssertPtrReturn(pCtxCb, VERR_INVALID_POINTER); 837 AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER); 838 839 int vrc = VINF_SUCCESS; 840 841 try 842 { 843 LogFlowFunc(("uFunc=%RU32, cParms=%RU32\n", 844 pCtxCb->uFunction, pSvcCb->mParms)); 845 846 switch (pCtxCb->uFunction) 847 { 848 case GUEST_MSG_PROGRESS_UPDATE: 849 break; 850 851 case GUEST_MSG_REPLY: 852 { 853 if (pSvcCb->mParms >= 3) 854 { 855 int idx = 1; /* Current parameter index. */ 856 CALLBACKDATA_MSG_REPLY dataCb; 857 /* pSvcCb->mpaParms[0] always contains the context ID. */ 858 vrc = pSvcCb->mpaParms[idx++].getUInt32(&dataCb.uType); 859 AssertRCReturn(vrc, vrc); 860 vrc = pSvcCb->mpaParms[idx++].getUInt32(&dataCb.rc); 861 AssertRCReturn(vrc, vrc); 862 vrc = pSvcCb->mpaParms[idx++].getPointer(&dataCb.pvPayload, &dataCb.cbPayload); 863 AssertRCReturn(vrc, vrc); 864 865 GuestWaitEventPayload evPayload(dataCb.uType, dataCb.pvPayload, dataCb.cbPayload); 866 int rc2 = signalWaitEventInternal(pCtxCb, dataCb.rc, &evPayload); 867 AssertRC(rc2); 868 } 869 else 870 vrc = VERR_INVALID_PARAMETER; 871 break; 872 } 873 874 default: 875 vrc = VERR_NOT_SUPPORTED; 876 break; 877 } 878 } 879 catch (std::bad_alloc) 880 { 881 vrc = VERR_NO_MEMORY; 882 } 883 catch (int rc) 884 { 885 vrc = rc; 886 } 887 888 LogFlowFuncLeaveRC(vrc); 889 return vrc; 890 } 891 848 892 int GuestBase::generateContextID(uint32_t uSessionID, uint32_t uObjectID, uint32_t *puContextID) 849 893 { … … 869 913 870 914 int GuestBase::registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID, 871 const std::list<VBoxEventType_T> &lstEvents, 915 GuestWaitEvent **ppEvent) 916 { 917 GuestEventTypes eventTypesEmpty; 918 return registerWaitEvent(uSessionID, uObjectID, eventTypesEmpty, ppEvent); 919 } 920 921 int GuestBase::registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID, 922 const GuestEventTypes &lstEvents, 872 923 GuestWaitEvent **ppEvent) 873 924 { … … 887 938 AssertPtr(pEvent); 888 939 889 for (std::list<VBoxEventType_T>::const_iterator itEvents = lstEvents.begin(); 940 /* Insert event into matching event group. This is for faster per-group 941 * lookup of all events later. */ 942 for (GuestEventTypes::const_iterator itEvents = lstEvents.begin(); 890 943 itEvents != lstEvents.end(); itEvents++) 891 944 { 892 mWaitEvents[(*itEvents)].push_back(pEvent); 945 mWaitEventGroups[(*itEvents)].insert( 946 std::pair<uint32_t, GuestWaitEvent*>(uContextID, pEvent)); 947 /** @todo Check for key collision. */ 893 948 } 949 950 /* Register event in regular event list. */ 951 /** @todo Check for key collisions. */ 952 mWaitEvents[uContextID] = pEvent; 894 953 895 954 *ppEvent = pEvent; … … 908 967 } 909 968 910 int GuestBase::signalWaitEvent s(VBoxEventType_T aType, IEvent *aEvent)969 int GuestBase::signalWaitEvent(VBoxEventType_T aType, IEvent *aEvent) 911 970 { 912 971 int rc = RTCritSectEnter(&mWaitEventCritSect); 972 #ifdef DEBUG 973 uint32_t cEvents = 0; 974 #endif 913 975 if (RT_SUCCESS(rc)) 914 976 { 915 Guest WaitEventTypes::iterator itTypes = mWaitEvents.find(aType);916 if (it Types != mWaitEvents.end())917 { 918 for (GuestWaitEvents::iterator itEvents = it Types->second.begin();919 itEvents != it Types->second.end(); itEvents++)977 GuestEventGroup::iterator itGroups = mWaitEventGroups.find(aType); 978 if (itGroups != mWaitEventGroups.end()) 979 { 980 for (GuestWaitEvents::iterator itEvents = itGroups->second.begin(); 981 itEvents != itGroups->second.end(); itEvents++) 920 982 { 921 LogFlowThisFunc(("Signalling event=%p with type=%ld ...\n", 922 (*itEvents), aType)); 923 983 #ifdef DEBUG 984 LogFlowThisFunc(("Signalling event=%p, type=%ld (CID %RU32: Sesion=%RU32, Object=%RU32, Count=%RU32) ...\n", 985 itEvents->second, aType, itEvents->first, 986 VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(itEvents->first), 987 VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(itEvents->first), 988 VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(itEvents->first))); 989 #endif 924 990 ComPtr<IEvent> pThisEvent = aEvent; 925 991 Assert(!pThisEvent.isNull()); 926 int rc2 = (*itEvents)->Signal(aEvent);992 int rc2 = itEvents->second->SignalExternal(aEvent); 927 993 if (RT_SUCCESS(rc)) 928 994 rc = rc2; 995 #ifdef DEBUG 996 cEvents++; 997 #endif 929 998 } 930 999 } … … 935 1004 } 936 1005 937 return rc; 1006 #ifdef DEBUG 1007 LogFlowThisFunc(("Signalled %RU32 events, rc=%Rrc\n", cEvents, rc)); 1008 #endif 1009 return rc; 1010 } 1011 1012 int GuestBase::signalWaitEventInternal(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, 1013 int guestRc, const GuestWaitEventPayload *pPayload) 1014 { 1015 if (RT_SUCCESS(guestRc)) 1016 return signalWaitEventInternalEx(pCbCtx, VINF_SUCCESS, 1017 0 /* Guest rc */, pPayload); 1018 1019 return signalWaitEventInternalEx(pCbCtx, VERR_GSTCTL_GUEST_ERROR, 1020 guestRc, pPayload); 1021 } 1022 1023 int GuestBase::signalWaitEventInternalEx(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, 1024 int rc, int guestRc, 1025 const GuestWaitEventPayload *pPayload) 1026 { 1027 AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER); 1028 /* pPayload is optional. */ 1029 1030 int rc2; 1031 GuestWaitEvents::iterator itEvent = mWaitEvents.find(pCbCtx->uContextID); 1032 if (itEvent != mWaitEvents.end()) 1033 { 1034 LogFlowThisFunc(("Signalling event=%p (CID %RU32, rc=%Rrc, guestRc=%Rrc, pPayload=%p) ...\n", 1035 itEvent->second, itEvent->first, rc, guestRc, pPayload)); 1036 GuestWaitEvent *pEvent = itEvent->second; 1037 AssertPtr(pEvent); 1038 rc2 = pEvent->SignalInternal(rc, guestRc, pPayload); 1039 } 1040 else 1041 rc2 = VERR_NOT_FOUND; 1042 1043 return rc2; 938 1044 } 939 1045 … … 946 1052 if (RT_SUCCESS(rc)) 947 1053 { 948 const std::list<VBoxEventType_T>lstTypes = pEvent->Types();949 for ( std::list<VBoxEventType_T>::const_iterator itEvents = lstTypes.begin();1054 const GuestEventTypes lstTypes = pEvent->Types(); 1055 for (GuestEventTypes::const_iterator itEvents = lstTypes.begin(); 950 1056 itEvents != lstTypes.end(); itEvents++) 951 1057 { 952 1058 /** @todo Slow O(n) lookup. Optimize this. */ 953 GuestWaitEvents::iterator itCurEvent = mWaitEvent s[(*itEvents)].begin();954 while (itCurEvent != mWaitEvent s[(*itEvents)].end())1059 GuestWaitEvents::iterator itCurEvent = mWaitEventGroups[(*itEvents)].begin(); 1060 while (itCurEvent != mWaitEventGroups[(*itEvents)].end()) 955 1061 { 956 if ( (*itCurEvent)== pEvent)1062 if (itCurEvent->second == pEvent) 957 1063 { 958 itCurEvent = mWaitEvent s[(*itEvents)].erase(itCurEvent);1064 itCurEvent = mWaitEventGroups[(*itEvents)].erase(itCurEvent); 959 1065 break; 960 1066 } … … 973 1079 } 974 1080 1081 /** 1082 * Waits for a formerly registered guest event. 1083 * 1084 * @return IPRT status code. 1085 * @param pEvent Pointer to event to wait for. 1086 * @param uTimeoutMS Timeout (in ms) for waiting. 1087 * @param pType Event type of following IEvent. 1088 * Optional. 1089 * @param ppEvent Pointer to IEvent which got triggered 1090 * for this event. Optional. 1091 */ 975 1092 int GuestBase::waitForEvent(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, 976 1093 VBoxEventType_T *pType, IEvent **ppEvent) 977 1094 { 978 1095 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 1096 /* pType is optional. */ 1097 /* ppEvent is optional. */ 979 1098 980 1099 int vrc = pEvent->Wait(uTimeoutMS); … … 982 1101 { 983 1102 const ComPtr<IEvent> pThisEvent = pEvent->Event(); 984 Assert(!pThisEvent.isNull()); 985 986 if (pType) 987 { 988 HRESULT hr = pThisEvent->COMGETTER(Type)(pType); 989 if (FAILED(hr)) 990 vrc = VERR_COM_UNEXPECTED; 991 } 992 if ( RT_SUCCESS(vrc) 993 && ppEvent) 994 pThisEvent.queryInterfaceTo(ppEvent); 995 996 unconst(pThisEvent).setNull(); 1103 if (!pThisEvent.isNull()) /* Having a VBoxEventType_ event is optional. */ 1104 { 1105 if (pType) 1106 { 1107 HRESULT hr = pThisEvent->COMGETTER(Type)(pType); 1108 if (FAILED(hr)) 1109 vrc = VERR_COM_UNEXPECTED; 1110 } 1111 if ( RT_SUCCESS(vrc) 1112 && ppEvent) 1113 pThisEvent.queryInterfaceTo(ppEvent); 1114 1115 unconst(pThisEvent).setNull(); 1116 } 997 1117 } 998 1118 … … 1022 1142 } 1023 1143 1024 int GuestObject::registerWaitEvent(const std::list<VBoxEventType_T>&lstEvents,1144 int GuestObject::registerWaitEvent(const GuestEventTypes &lstEvents, 1025 1145 GuestWaitEvent **ppEvent) 1026 1146 { … … 1058 1178 } 1059 1179 1060 GuestWaitEvent::GuestWaitEvent(uint32_t uCID, 1061 const std::list<VBoxEventType_T> &lstEvents) 1062 : fAborted(false), 1063 mCID(uCID), 1064 mEventTypes(lstEvents), 1065 mEventSem(NIL_RTSEMEVENT) 1066 { 1067 int rc = RTSemEventCreate(&mEventSem); 1068 AssertRC(rc); 1069 /** @todo Throw an exception on failure! */ 1070 } 1071 1072 GuestWaitEvent::~GuestWaitEvent(void) 1073 { 1074 } 1075 1076 /** 1077 * Signals the event. Passing NULL will abort (cancel) 1078 * the event. 1079 * 1080 * @return IPRT status code. 1081 * @param pEvent IEvent to associate. 1082 */ 1083 int GuestWaitEvent::Signal(IEvent *pEvent) 1084 { 1085 AssertReturn(mEventSem != NIL_RTSEMEVENT, VERR_CANCELLED); 1086 1087 if (pEvent) 1088 mEvent = pEvent; 1180 GuestWaitEventBase::GuestWaitEventBase(void) 1181 : mCID(0), 1182 mEventSem(NIL_RTSEMEVENT), 1183 mfAborted(false), 1184 mRc(VINF_SUCCESS), 1185 mGuestRc(VINF_SUCCESS) 1186 { 1187 } 1188 1189 GuestWaitEventBase::~GuestWaitEventBase(void) 1190 { 1191 } 1192 1193 int GuestWaitEventBase::Init(uint32_t uCID) 1194 { 1195 mCID = uCID; 1196 1197 return RTSemEventCreate(&mEventSem); 1198 } 1199 1200 int GuestWaitEventBase::SignalInternal(int rc, int guestRc, 1201 const GuestWaitEventPayload *pPayload) 1202 { 1203 AssertReturn(!mfAborted, VERR_CANCELLED); 1204 1205 #ifdef VBOX_STRICT 1206 if (rc == VERR_GSTCTL_GUEST_ERROR) 1207 AssertMsg(RT_FAILURE(guestRc), ("Guest error indicated but no actual guest error set (%Rrc)\n", guestRc)); 1089 1208 else 1090 ASMAtomicWriteBool(&fAborted, true); 1091 1092 return RTSemEventSignal(mEventSem); 1093 } 1094 1095 int GuestWaitEvent::Wait(RTMSINTERVAL uTimeoutMS) 1209 AssertMsg(RT_SUCCESS(guestRc), ("No guest error indicated but actual guest error set (%Rrc)\n", guestRc)); 1210 #endif 1211 1212 int rc2; 1213 if (pPayload) 1214 rc2 = mPayload.CopyFromDeep(*pPayload); 1215 else 1216 rc2 = VINF_SUCCESS; 1217 if (RT_SUCCESS(rc2)) 1218 { 1219 mRc = rc; 1220 mGuestRc = guestRc; 1221 1222 rc2 = RTSemEventSignal(mEventSem); 1223 } 1224 1225 return rc2; 1226 } 1227 1228 int GuestWaitEventBase::Wait(RTMSINTERVAL uTimeoutMS) 1096 1229 { 1097 1230 int rc = VINF_SUCCESS; 1098 1231 1099 if (ASMAtomicReadBool(& fAborted))1232 if (ASMAtomicReadBool(&mfAborted)) 1100 1233 rc = VERR_CANCELLED; 1101 1234 … … 1108 1241 msInterval = RT_INDEFINITE_WAIT; 1109 1242 rc = RTSemEventWait(mEventSem, msInterval); 1110 if (ASMAtomicReadBool(& fAborted))1243 if (ASMAtomicReadBool(&mfAborted)) 1111 1244 rc = VERR_CANCELLED; 1112 } 1113 1114 return rc; 1115 } 1116 1245 if (RT_SUCCESS(rc)) 1246 { 1247 /* If waiting succeeded, return the overall 1248 * result code. */ 1249 rc = mRc; 1250 } 1251 } 1252 1253 return rc; 1254 } 1255 1256 GuestWaitEvent::GuestWaitEvent(uint32_t uCID, 1257 const GuestEventTypes &lstEvents) 1258 { 1259 int rc2 = Init(uCID); 1260 AssertRC(rc2); /** @todo Throw exception here. */ 1261 1262 mEventTypes = lstEvents; 1263 } 1264 1265 GuestWaitEvent::GuestWaitEvent(uint32_t uCID) 1266 { 1267 int rc2 = Init(uCID); 1268 AssertRC(rc2); /** @todo Throw exception here. */ 1269 } 1270 1271 GuestWaitEvent::~GuestWaitEvent(void) 1272 { 1273 1274 } 1275 1276 /** 1277 * Cancels the event. 1278 */ 1279 int GuestWaitEvent::Cancel(void) 1280 { 1281 AssertReturn(!mfAborted, VERR_CANCELLED); 1282 ASMAtomicWriteBool(&mfAborted, true); 1283 1284 return RTSemEventSignal(mEventSem); 1285 } 1286 1287 int GuestWaitEvent::Init(uint32_t uCID) 1288 { 1289 return GuestWaitEventBase::Init(uCID); 1290 } 1291 1292 /** 1293 * Signals the event. 1294 * 1295 * @return IPRT status code. 1296 * @param pEvent Public IEvent to associate. 1297 * Optional. 1298 */ 1299 int GuestWaitEvent::SignalExternal(IEvent *pEvent) 1300 { 1301 AssertReturn(mEventSem != NIL_RTSEMEVENT, VERR_CANCELLED); 1302 1303 if (pEvent) 1304 mEvent = pEvent; 1305 1306 return RTSemEventSignal(mEventSem); 1307 } 1308 -
trunk/src/VBox/Main/src-client/GuestDirectoryImpl.cpp
r47627 r49349 59 59 ///////////////////////////////////////////////////////////////////////////// 60 60 61 int GuestDirectory::init(GuestSession *aSession, 62 const Utf8Str &strPath, const Utf8Str &strFilter, uint32_t uFlags) 63 { 64 LogFlowThisFunc(("strPath=%s, strFilter=%s, uFlags=%x\n", 65 strPath.c_str(), strFilter.c_str(), uFlags)); 61 int GuestDirectory::init(Console *pConsole, GuestSession *pSession, 62 ULONG uDirID, const GuestDirectoryOpenInfo &openInfo) 63 { 64 LogFlowThisFunc(("pConsole=%p, pSession=%p, uDirID=%RU32, strPath=%s, strFilter=%s, uFlags=%x\n", 65 pConsole, pSession, uDirID, openInfo.mPath.c_str(), openInfo.mFilter.c_str(), 66 openInfo.mFlags)); 67 68 AssertPtrReturn(pConsole, VERR_INVALID_POINTER); 69 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 66 70 67 71 /* Enclose the state transition NotReady->InInit->Ready. */ … … 69 73 AssertReturn(autoInitSpan.isOk(), E_FAIL); 70 74 71 mData.mSession = aSession; 72 mData.mName = strPath; 73 mData.mFilter = strFilter; 74 mData.mFlags = uFlags; 75 76 /* Start the directory process on the guest. */ 77 GuestProcessStartupInfo procInfo; 78 procInfo.mName = Utf8StrFmt(tr("Reading directory \"%s\"", strPath.c_str())); 79 procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_LS); 80 procInfo.mTimeoutMS = 5 * 60 * 1000; /* 5 minutes timeout. */ 81 procInfo.mFlags = ProcessCreateFlag_WaitForStdOut; 82 83 procInfo.mArguments.push_back(Utf8Str("--machinereadable")); 84 /* We want the long output format which contains all the object details. */ 85 procInfo.mArguments.push_back(Utf8Str("-l")); 75 #ifndef VBOX_WITH_GUEST_CONTROL 76 autoInitSpan.setSucceeded(); 77 return VINF_SUCCESS; 78 #else 79 int vrc = bindToSession(pConsole, pSession, uDirID /* Object ID */); 80 if (RT_SUCCESS(vrc)) 81 { 82 mSession = pSession; 83 84 mData.mID = uDirID; 85 mData.mOpenInfo = openInfo; 86 } 87 88 if (RT_SUCCESS(vrc)) 89 { 90 /* Start the directory process on the guest. */ 91 GuestProcessStartupInfo procInfo; 92 procInfo.mName = Utf8StrFmt(tr("Reading directory \"%s\"", openInfo.mPath.c_str())); 93 procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_LS); 94 procInfo.mTimeoutMS = 5 * 60 * 1000; /* 5 minutes timeout. */ 95 procInfo.mFlags = ProcessCreateFlag_WaitForStdOut; 96 97 procInfo.mArguments.push_back(Utf8Str("--machinereadable")); 98 /* We want the long output format which contains all the object details. */ 99 procInfo.mArguments.push_back(Utf8Str("-l")); 86 100 #if 0 /* Flags are not supported yet. */ 87 if (uFlags & DirectoryOpenFlag_NoSymlinks)88 procInfo.mArguments.push_back(Utf8Str("--nosymlinks")); /** @todo What does GNU here? */101 if (uFlags & DirectoryOpenFlag_NoSymlinks) 102 procInfo.mArguments.push_back(Utf8Str("--nosymlinks")); /** @todo What does GNU here? */ 89 103 #endif 90 /** @todo Recursion support? */ 91 procInfo.mArguments.push_back(strPath); /* The directory we want to open. */ 92 93 /* 94 * Start the process asynchronously and keep it around so that we can use 95 * it later in subsequent read() calls. 96 * Note: No guest rc available because operation is asynchronous. 97 */ 98 int rc = mData.mProcessTool.Init(mData.mSession, procInfo, 99 true /* Async */, NULL /* Guest rc */); 100 if (RT_SUCCESS(rc)) 104 /** @todo Recursion support? */ 105 procInfo.mArguments.push_back(openInfo.mPath); /* The directory we want to open. */ 106 107 /* 108 * Start the process asynchronously and keep it around so that we can use 109 * it later in subsequent read() calls. 110 * Note: No guest rc available because operation is asynchronous. 111 */ 112 vrc = mData.mProcessTool.Init(mSession, procInfo, 113 true /* Async */, NULL /* Guest rc */); 114 } 115 116 if (RT_SUCCESS(vrc)) 101 117 { 102 118 /* Confirm a successful initialization when it's the case. */ 103 119 autoInitSpan.setSucceeded(); 104 return rc; 105 } 106 107 autoInitSpan.setFailed(); 108 return rc; 120 return vrc; 121 } 122 else 123 autoInitSpan.setFailed(); 124 125 return vrc; 126 #endif /* VBOX_WITH_GUEST_CONTROL */ 109 127 } 110 128 … … 139 157 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 140 158 141 mData.m Name.cloneTo(aName);159 mData.mOpenInfo.mPath.cloneTo(aName); 142 160 143 161 return S_OK; … … 155 173 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 156 174 157 mData.m Filter.cloneTo(aFilter);175 mData.mOpenInfo.mFilter.cloneTo(aFilter); 158 176 159 177 return S_OK; … … 162 180 // private methods 163 181 ///////////////////////////////////////////////////////////////////////////// 182 183 int GuestDirectory::callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb) 184 { 185 AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER); 186 AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER); 187 188 LogFlowThisFunc(("strPath=%s, uContextID=%RU32, uFunction=%RU32, pSvcCb=%p\n", 189 mData.mOpenInfo.mPath.c_str(), pCbCtx->uContextID, pCbCtx->uFunction, pSvcCb)); 190 191 int vrc; 192 switch (pCbCtx->uFunction) 193 { 194 case GUEST_DIR_NOTIFY: 195 { 196 int idx = 1; /* Current parameter index. */ 197 CALLBACKDATA_DIR_NOTIFY dataCb; 198 /* pSvcCb->mpaParms[0] always contains the context ID. */ 199 pSvcCb->mpaParms[idx++].getUInt32(&dataCb.uType); 200 pSvcCb->mpaParms[idx++].getUInt32(&dataCb.rc); 201 202 int guestRc = (int)dataCb.rc; /* uint32_t vs. int. */ 203 204 LogFlowFunc(("uType=%RU32, guestRc=%Rrc\n", 205 dataCb.uType, guestRc)); 206 207 switch (dataCb.uType) 208 { 209 /* Nothing here yet, nothing to dispatch further. */ 210 211 default: 212 vrc = VERR_NOT_SUPPORTED; 213 break; 214 } 215 break; 216 } 217 218 default: 219 /* Silently ignore not implemented functions. */ 220 vrc = VERR_NOT_SUPPORTED; 221 break; 222 } 223 224 #ifdef DEBUG 225 LogFlowFuncLeaveRC(vrc); 226 #endif 227 return vrc; 228 } 229 230 /* static */ 231 Utf8Str GuestDirectory::guestErrorToString(int guestRc) 232 { 233 Utf8Str strError; 234 235 /** @todo pData->u32Flags: int vs. uint32 -- IPRT errors are *negative* !!! */ 236 switch (guestRc) 237 { 238 case VERR_DIR_NOT_EMPTY: 239 strError += Utf8StrFmt("Directoy is not empty"); 240 break; 241 242 default: 243 strError += Utf8StrFmt("%Rrc", guestRc); 244 break; 245 } 246 247 return strError; 248 } 249 250 /* static */ 251 HRESULT GuestDirectory::setErrorExternal(VirtualBoxBase *pInterface, int guestRc) 252 { 253 AssertPtr(pInterface); 254 AssertMsg(RT_FAILURE(guestRc), ("Guest rc does not indicate a failure when setting error\n")); 255 256 return pInterface->setError(VBOX_E_IPRT_ERROR, GuestDirectory::guestErrorToString(guestRc).c_str()); 257 } 164 258 165 259 // implementation of public methods … … 176 270 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 177 271 178 AssertPtr(m Data.mSession);179 int rc = m Data.mSession->directoryRemoveFromList(this);272 AssertPtr(mSession); 273 int rc = mSession->directoryRemoveFromList(this); 180 274 AssertRC(rc); 181 275 … … 188 282 switch (rc) 189 283 { 190 case VERR_GSTCTL_GUEST_ERROR:284 case VERR_GSTCTL_GUEST_ERROR: 191 285 hr = GuestProcess::setErrorExternal(this, guestRc); 192 286 break; … … 200 294 hr = setError(VBOX_E_IPRT_ERROR, 201 295 tr("Terminating open guest directory \"%s\" failed: %Rrc"), 202 mData.m Name.c_str(), rc);296 mData.mOpenInfo.mPath.c_str(), rc); 203 297 break; 204 298 } … … 293 387 case VERR_ACCESS_DENIED: 294 388 hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: Unable to read / access denied"), 295 mData.m Name.c_str());389 mData.mOpenInfo.mPath.c_str()); 296 390 break; 297 391 298 392 case VERR_PATH_NOT_FOUND: 299 393 hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: Path not found"), 300 mData.m Name.c_str());394 mData.mOpenInfo.mPath.c_str()); 301 395 break; 302 396 … … 304 398 /* See SDK reference. */ 305 399 hr = setError(VBOX_E_OBJECT_NOT_FOUND, tr("No more entries for directory \"%s\""), 306 mData.m Name.c_str());400 mData.mOpenInfo.mPath.c_str()); 307 401 break; 308 402 309 403 default: 310 404 hr = setError(VBOX_E_IPRT_ERROR, tr("Error while reading directory \"%s\": %Rrc\n"), 311 mData.m Name.c_str(), rc);405 mData.mOpenInfo.mPath.c_str(), rc); 312 406 break; 313 407 } -
trunk/src/VBox/Main/src-client/GuestFileImpl.cpp
r49006 r49349 77 77 { 78 78 Assert(!mFile.isNull()); 79 int rc2 = mFile->signalWaitEvent s(aType, aEvent);79 int rc2 = mFile->signalWaitEvent(aType, aEvent); 80 80 #ifdef DEBUG_andy 81 81 LogFlowFunc(("Signalling events of type=%ld, file=%p resulted in rc=%Rrc\n", … … 411 411 int GuestFile::callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb) 412 412 { 413 #ifdef DEBUG 413 AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER); 414 AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER); 415 414 416 LogFlowThisFunc(("strName=%s, uContextID=%RU32, uFunction=%RU32, pSvcCb=%p\n", 415 417 mData.mOpenInfo.mFileName.c_str(), pCbCtx->uContextID, pCbCtx->uFunction, pSvcCb)); 416 #endif417 AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);418 418 419 419 int vrc; … … 447 447 448 448 GuestWaitEvent *pEvent = NULL; 449 std::list < VBoxEventType_T >eventTypes;449 GuestEventTypes eventTypes; 450 450 try 451 451 { … … 539 539 AssertRC(rc2); 540 540 541 rc2 = signalWaitEventInternal(pCbCtx, 542 guestRc, NULL /* pPayload */); 543 AssertRC(rc2); 544 541 545 return VINF_SUCCESS; /* Report to the guest. */ 542 546 } … … 548 552 int rc2 = setFileStatus(FileStatus_Error, guestRc); 549 553 AssertRC(rc2); 554 550 555 break; 551 556 } … … 561 566 AssertMsg(mData.mID == VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID), 562 567 ("File ID %RU32 does not match context ID %RU32\n", mData.mID, 563 568 VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID))); 564 569 565 570 /* Set the initial offset. On the guest the whole opening operation … … 570 575 /* Set the process status. */ 571 576 int rc2 = setFileStatus(FileStatus_Open, guestRc); 572 if (RT_SUCCESS(vrc)) 573 vrc = rc2; 577 AssertRC(rc2); 574 578 } 575 579 else … … 678 682 } 679 683 684 if (RT_SUCCESS(vrc)) 685 { 686 GuestWaitEventPayload payload(dataCb.uType, &dataCb, sizeof(dataCb)); 687 int rc2 = signalWaitEventInternal(pCbCtx, guestRc, &payload); 688 AssertRC(rc2); 689 } 690 680 691 LogFlowThisFunc(("uType=%RU32, guestRc=%Rrc\n", 681 692 dataCb.uType, dataCb.rc)); … … 708 719 709 720 GuestWaitEvent *pEvent = NULL; 710 std::list < VBoxEventType_T >eventTypes;721 GuestEventTypes eventTypes; 711 722 try 712 723 { … … 765 776 766 777 GuestWaitEvent *pEvent = NULL; 767 std::list < VBoxEventType_T >eventTypes;778 GuestEventTypes eventTypes; 768 779 try 769 780 { … … 820 831 821 832 GuestWaitEvent *pEvent = NULL; 822 std::list < VBoxEventType_T >eventTypes;833 GuestEventTypes eventTypes; 823 834 try 824 835 { … … 876 887 877 888 GuestWaitEvent *pEvent = NULL; 878 std::list < VBoxEventType_T >eventTypes;889 GuestEventTypes eventTypes; 879 890 try 880 891 { … … 970 981 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 971 982 972 VBoxEventType_T evtType;973 ComPtr<IEvent> pIEvent;974 983 int vrc = waitForEvent(pEvent, uTimeoutMS, 975 &evtType, pIEvent.asOutParam()); 976 if (RT_SUCCESS(vrc)) 977 { 978 if (evtType == VBoxEventType_OnGuestFileOffsetChanged) 979 { 980 if (puOffset) 981 { 982 ComPtr<IGuestFileOffsetChangedEvent> pFileEvent = pIEvent; 983 Assert(!pFileEvent.isNull()); 984 985 HRESULT hr = pFileEvent->COMGETTER(Offset)((LONG64*)puOffset); 986 ComAssertComRC(hr); 987 } 984 NULL /* Event type */, NULL /* IEvent */); 985 if (RT_SUCCESS(vrc)) 986 { 987 Assert(pEvent->Payload().Size() == sizeof(CALLBACKDATA_FILE_NOTIFY)); 988 const PCALLBACKDATA_FILE_NOTIFY pvCbData = 989 (PCALLBACKDATA_FILE_NOTIFY)pEvent->Payload().Raw(); 990 Assert(pvCbData->uType == GUEST_FILE_NOTIFYTYPE_SEEK); 991 992 if (puOffset) 993 *puOffset = pvCbData->u.seek.uOffActual; 994 } 995 996 return vrc; 997 } 998 999 int GuestFile::waitForRead(GuestWaitEvent *pEvent, 1000 uint32_t uTimeoutMS, 1001 void *pvData, size_t cbData, uint32_t *pcbRead) 1002 { 1003 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 1004 1005 int vrc = waitForEvent(pEvent, uTimeoutMS, 1006 NULL /* Event type */, NULL /* IEvent */); 1007 if (RT_SUCCESS(vrc)) 1008 { 1009 Assert(pEvent->Payload().Size() == sizeof(CALLBACKDATA_FILE_NOTIFY)); 1010 const PCALLBACKDATA_FILE_NOTIFY pvCbData = 1011 (PCALLBACKDATA_FILE_NOTIFY)pEvent->Payload().Raw(); 1012 Assert(pvCbData->uType == GUEST_FILE_NOTIFYTYPE_READ); 1013 1014 uint32_t cbRead = pvCbData->u.read.cbData; 1015 if ( cbRead 1016 && cbRead <= cbData) 1017 { 1018 memcpy(pvData, 1019 pvCbData->u.read.pvData, cbRead); 988 1020 } 989 1021 else 990 vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED; 991 } 992 993 return vrc; 994 } 995 996 int GuestFile::waitForRead(GuestWaitEvent *pEvent, 997 uint32_t uTimeoutMS, void *pvData, size_t cbData, uint32_t *pcbRead) 998 { 999 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 1000 1001 VBoxEventType_T evtType; 1002 ComPtr<IEvent> pIEvent; 1003 int vrc = waitForEvent(pEvent, uTimeoutMS, 1004 &evtType, pIEvent.asOutParam()); 1005 if (RT_SUCCESS(vrc)) 1006 { 1007 if (evtType == VBoxEventType_OnGuestFileRead) 1008 { 1009 ComPtr<IGuestFileReadEvent> pFileEvent = pIEvent; 1010 Assert(!pFileEvent.isNull()); 1011 1012 HRESULT hr; 1013 if (pvData) 1014 { 1015 com::SafeArray <BYTE> data; 1016 hr = pFileEvent->COMGETTER(Data)(ComSafeArrayAsOutParam(data)); 1017 ComAssertComRC(hr); 1018 size_t cbRead = data.size(); 1019 if ( cbRead 1020 && cbRead <= cbData) 1021 { 1022 memcpy(pvData, data.raw(), data.size()); 1023 } 1024 else 1025 vrc = VERR_BUFFER_OVERFLOW; 1026 } 1027 if (pcbRead) 1028 { 1029 hr = pFileEvent->COMGETTER(Processed)((ULONG*)pcbRead); 1030 ComAssertComRC(hr); 1031 } 1032 } 1033 else 1034 vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED; 1022 vrc = VERR_BUFFER_OVERFLOW; 1023 1024 if (pcbRead) 1025 *pcbRead = cbRead; 1035 1026 } 1036 1027 … … 1042 1033 { 1043 1034 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 1044 /* pFileStatus is optional. */ 1045 1046 VBoxEventType_T evtType; 1047 ComPtr<IEvent> pIEvent; 1035 1048 1036 int vrc = waitForEvent(pEvent, uTimeoutMS, 1049 &evtType, pIEvent.asOutParam()); 1050 if (RT_SUCCESS(vrc)) 1051 { 1052 Assert(evtType == VBoxEventType_OnGuestFileStateChanged); 1053 ComPtr<IGuestFileStateChangedEvent> pFileEvent = pIEvent; 1054 Assert(!pFileEvent.isNull()); 1055 1056 HRESULT hr; 1057 if (pFileStatus) 1058 { 1059 hr = pFileEvent->COMGETTER(Status)(pFileStatus); 1060 ComAssertComRC(hr); 1061 } 1062 1063 ComPtr<IVirtualBoxErrorInfo> errorInfo; 1064 hr = pFileEvent->COMGETTER(Error)(errorInfo.asOutParam()); 1065 ComAssertComRC(hr); 1066 1067 LONG lGuestRc; 1068 hr = errorInfo->COMGETTER(ResultDetail)(&lGuestRc); 1069 ComAssertComRC(hr); 1070 1071 LogFlowThisFunc(("resultDetail=%RI32 (rc=%Rrc)\n", 1072 lGuestRc, lGuestRc)); 1073 1074 if (RT_FAILURE((int)lGuestRc)) 1075 vrc = VERR_GSTCTL_GUEST_ERROR; 1037 NULL /* Event type */, NULL /* IEvent */); 1038 if (RT_SUCCESS(vrc)) 1039 { 1040 Assert(pEvent->Payload().Size() == sizeof(CALLBACKDATA_FILE_NOTIFY)); 1041 const PCALLBACKDATA_FILE_NOTIFY pvCbData = 1042 (PCALLBACKDATA_FILE_NOTIFY)pEvent->Payload().Raw(); 1043 /* Note: pvCbData->uType can be different types. */; 1044 1045 1076 1046 1077 1047 if (pGuestRc) 1078 *pGuestRc = (int)lGuestRc;1048 *pGuestRc = pvCbData->rc; /* int vs. uint32_t */ 1079 1049 } 1080 1050 … … 1087 1057 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 1088 1058 1089 VBoxEventType_T evtType;1090 ComPtr<IEvent> pIEvent;1091 1059 int vrc = waitForEvent(pEvent, uTimeoutMS, 1092 &evtType, pIEvent.asOutParam()); 1093 if (RT_SUCCESS(vrc)) 1094 { 1095 if (evtType == VBoxEventType_OnGuestFileWrite) 1096 { 1097 if (pcbWritten) 1098 { 1099 ComPtr<IGuestFileWriteEvent> pFileEvent = pIEvent; 1100 Assert(!pFileEvent.isNull()); 1101 1102 HRESULT hr = pFileEvent->COMGETTER(Processed)((ULONG*)pcbWritten); 1103 ComAssertComRC(hr); 1104 } 1105 } 1106 else 1107 vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED; 1060 NULL /* Event type */, NULL /* IEvent */); 1061 if (RT_SUCCESS(vrc)) 1062 { 1063 Assert(pEvent->Payload().Size() == sizeof(CALLBACKDATA_FILE_NOTIFY)); 1064 const PCALLBACKDATA_FILE_NOTIFY pvCbData = 1065 (PCALLBACKDATA_FILE_NOTIFY)pEvent->Payload().Raw(); 1066 Assert(pvCbData->uType == GUEST_FILE_NOTIFYTYPE_WRITE); 1067 1068 if (pcbWritten) 1069 *pcbWritten = pvCbData->u.write.cbWritten; 1108 1070 } 1109 1071 … … 1125 1087 1126 1088 GuestWaitEvent *pEvent = NULL; 1127 std::list < VBoxEventType_T >eventTypes;1089 GuestEventTypes eventTypes; 1128 1090 try 1129 1091 { … … 1184 1146 1185 1147 GuestWaitEvent *pEvent = NULL; 1186 std::list < VBoxEventType_T >eventTypes;1148 GuestEventTypes eventTypes; 1187 1149 try 1188 1150 { -
trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp
r48770 r49349 116 116 { 117 117 Assert(!mProcess.isNull()); 118 int rc2 = mProcess->signalWaitEvent s(aType, aEvent);119 #ifdef DEBUG _andy118 int rc2 = mProcess->signalWaitEvent(aType, aEvent); 119 #ifdef DEBUG 120 120 LogFlowThisFunc(("Signalling events of type=%ld, process=%p resulted in rc=%Rrc\n", 121 121 aType, mProcess, rc2)); … … 512 512 513 513 #ifdef DEBUG 514 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));514 LogFlowFuncLeaveRC(vrc); 515 515 #endif 516 516 return vrc; … … 647 647 int vrc = setProcessStatus(ProcessStatus_Down, VINF_SUCCESS); 648 648 649 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));649 LogFlowFuncLeaveRC(vrc); 650 650 return vrc; 651 651 } … … 714 714 } 715 715 716 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));716 LogFlowFuncLeaveRC(vrc); 717 717 return vrc; 718 718 } … … 832 832 } 833 833 834 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));834 LogFlowFuncLeaveRC(vrc); 835 835 return vrc; 836 836 } … … 868 868 } 869 869 870 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));870 LogFlowFuncLeaveRC(vrc); 871 871 return vrc; 872 872 } … … 904 904 905 905 GuestWaitEvent *pEvent = NULL; 906 std::list < VBoxEventType_T >eventTypes;906 GuestEventTypes eventTypes; 907 907 try 908 908 { … … 948 948 unregisterWaitEvent(pEvent); 949 949 950 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));950 LogFlowFuncLeaveRC(vrc); 951 951 return vrc; 952 952 } … … 1041 1041 1042 1042 GuestWaitEvent *pEvent = NULL; 1043 std::list < VBoxEventType_T >eventTypes;1043 GuestEventTypes eventTypes; 1044 1044 try 1045 1045 { … … 1168 1168 unregisterWaitEvent(pEvent); 1169 1169 1170 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));1170 LogFlowFuncLeaveRC(vrc); 1171 1171 return vrc; 1172 1172 } … … 1200 1200 } 1201 1201 1202 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));1202 LogFlowFuncLeaveRC(vrc); 1203 1203 return vrc; 1204 1204 } … … 1250 1250 { 1251 1251 GuestWaitEvent *pEvent = NULL; 1252 std::list < VBoxEventType_T >eventTypes;1252 GuestEventTypes eventTypes; 1253 1253 try 1254 1254 { … … 1279 1279 } 1280 1280 1281 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));1281 LogFlowFuncLeaveRC(vrc); 1282 1282 return vrc; 1283 1283 } … … 1285 1285 /* static */ 1286 1286 ProcessWaitResult_T GuestProcess::waitFlagsToResultEx(uint32_t fWaitFlags, 1287 ProcessStatus_T procStatus, uint32_t uProcFlags,1288 uint32_t uPro tocol)1287 ProcessStatus_T oldStatus, ProcessStatus_T newStatus, 1288 uint32_t uProcFlags, uint32_t uProtocol) 1289 1289 { 1290 1290 ProcessWaitResult_T waitResult = ProcessWaitResult_None; 1291 1291 1292 if ( (fWaitFlags & ProcessWaitForFlag_Terminate)1293 || (fWaitFlags & ProcessWaitForFlag_StdIn)1294 || (fWaitFlags & ProcessWaitForFlag_StdOut)1295 || (fWaitFlags & ProcessWaitForFlag_StdErr))1296 {1297 switch (procStatus)1298 {1299 case ProcessStatus_TerminatedNormally:1300 case ProcessStatus_TerminatedSignal:1301 case ProcessStatus_TerminatedAbnormally:1302 case ProcessStatus_Down: 1303 waitResult = ProcessWaitResult_Terminate;1304 break;1305 1306 case ProcessStatus_TimedOutKilled:1307 case ProcessStatus_TimedOutAbnormally:1308 waitResult = ProcessWaitResult_Timeout; 1309 break;1310 1311 case ProcessStatus_Error:1312 /* Handled above. */ 1313 break;1314 1315 case ProcessStatus_Started:1292 switch (newStatus) 1293 { 1294 case ProcessStatus_TerminatedNormally: 1295 case ProcessStatus_TerminatedSignal: 1296 case ProcessStatus_TerminatedAbnormally: 1297 waitResult = ProcessWaitResult_Terminate; 1298 break; 1299 case ProcessStatus_Down: 1300 waitResult = ProcessWaitResult_Terminate; 1301 break; 1302 1303 case ProcessStatus_TimedOutKilled: 1304 /* Fall through is intentional. */ 1305 case ProcessStatus_TimedOutAbnormally: 1306 waitResult = ProcessWaitResult_Timeout; 1307 break; 1308 1309 case ProcessStatus_Error: 1310 waitResult = ProcessWaitResult_Error; 1311 break; 1312 1313 case ProcessStatus_Started: 1314 { 1315 switch (oldStatus) 1316 1316 { 1317 /* 1318 * If ProcessCreateFlag_WaitForProcessStartOnly was specified on process creation the 1319 * caller is not interested in getting further process statuses -- so just don't notify 1320 * anything here anymore and return. 1321 */ 1322 if (uProcFlags & ProcessCreateFlag_WaitForProcessStartOnly) 1323 waitResult = ProcessWaitResult_Start; 1324 break; 1317 case ProcessStatus_Starting: 1318 if (fWaitFlags & ProcessWaitForFlag_Start) 1319 { 1320 waitResult = ProcessWaitResult_Start; 1321 } 1322 else 1323 { 1324 /* 1325 * If ProcessCreateFlag_WaitForProcessStartOnly was specified on process creation the 1326 * caller is not interested in getting further process statuses -- so just don't notify 1327 * anything here anymore and return. 1328 */ 1329 if (uProcFlags & ProcessCreateFlag_WaitForProcessStartOnly) 1330 waitResult = ProcessWaitResult_Start; 1331 } 1332 break; 1333 1334 default: 1335 /* No result available (yet). */ 1336 break; 1325 1337 } 1326 1327 case ProcessStatus_Undefined: 1328 case ProcessStatus_Starting: 1329 /* No result available yet. */ 1330 break; 1331 1332 default: 1333 AssertMsgFailed(("Unhandled process status %ld\n", procStatus)); 1334 break; 1335 } 1336 } 1337 else if (fWaitFlags & ProcessWaitForFlag_Start) 1338 { 1339 switch (procStatus) 1340 { 1341 case ProcessStatus_Started: 1342 case ProcessStatus_Paused: 1343 case ProcessStatus_Terminating: 1344 case ProcessStatus_TerminatedNormally: 1345 case ProcessStatus_TerminatedSignal: 1346 case ProcessStatus_TerminatedAbnormally: 1347 case ProcessStatus_Down: 1348 waitResult = ProcessWaitResult_Start; 1349 break; 1350 1351 case ProcessStatus_Error: 1352 waitResult = ProcessWaitResult_Error; 1353 break; 1354 1355 case ProcessStatus_TimedOutKilled: 1356 case ProcessStatus_TimedOutAbnormally: 1357 waitResult = ProcessWaitResult_Timeout; 1358 break; 1359 1360 case ProcessStatus_Undefined: 1361 case ProcessStatus_Starting: 1362 /* No result available yet. */ 1363 break; 1364 1365 default: 1366 AssertMsgFailed(("Unhandled process status %ld\n", procStatus)); 1367 break; 1368 } 1369 } 1370 1371 /* Filter out waits which are *not* supported using 1372 * older guest control Guest Additions. 1373 * 1374 ** @todo ProcessWaitForFlag_Std* flags are not implemented yet. 1375 */ 1376 if (uProtocol < 99) /* See @todo above. */ 1377 { 1378 if ( waitResult == ProcessWaitResult_None 1379 /* We don't support waiting for stdin, out + err, 1380 * just skip waiting then. */ 1381 && ( (fWaitFlags & ProcessWaitForFlag_StdIn) 1382 || (fWaitFlags & ProcessWaitForFlag_StdOut) 1383 || (fWaitFlags & ProcessWaitForFlag_StdErr) 1338 break; 1339 } 1340 1341 case ProcessStatus_Undefined: 1342 case ProcessStatus_Starting: 1343 /* No result available yet. */ 1344 break; 1345 1346 default: 1347 AssertMsgFailed(("Unhandled process status %ld\n", newStatus)); 1348 break; 1349 } 1350 1351 if (newStatus == ProcessStatus_Started) 1352 { 1353 /* Filter out waits which are *not* supported using 1354 * older guest control Guest Additions. 1355 * 1356 ** @todo ProcessWaitForFlag_Std* flags are not implemented yet. 1357 */ 1358 if (uProtocol < 99) /* See @todo above. */ 1359 { 1360 if ( waitResult == ProcessWaitResult_None 1361 /* We don't support waiting for stdin, out + err, 1362 * just skip waiting then. */ 1363 && ( (fWaitFlags & ProcessWaitForFlag_StdIn) 1364 || (fWaitFlags & ProcessWaitForFlag_StdOut) 1365 || (fWaitFlags & ProcessWaitForFlag_StdErr) 1366 ) 1384 1367 ) 1385 ) 1386 { 1387 /* Use _WaitFlagNotSupported because we don't know what to tell the caller. */ 1388 waitResult = ProcessWaitResult_WaitFlagNotSupported; 1389 } 1390 } 1391 1368 { 1369 /* Use _WaitFlagNotSupported because we don't know what to tell the caller. */ 1370 waitResult = ProcessWaitResult_WaitFlagNotSupported; 1371 } 1372 } 1373 } 1374 1375 #ifdef DEBUG 1376 LogFlowFunc(("oldStatus=%ld, newStatus=%ld, fWaitFlags=0x%x, waitResult=%ld\n", 1377 oldStatus, newStatus, fWaitFlags, waitResult)); 1378 #endif 1392 1379 return waitResult; 1393 1380 } … … 1396 1383 { 1397 1384 AssertPtr(mSession); 1398 return GuestProcess::waitFlagsToResultEx(fWaitFlags, mData.mStatus, mData.mProcess.mFlags, 1399 mSession->getProtocolVersion()); 1400 } 1401 1402 int GuestProcess::waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, ProcessWaitResult_T &waitResult, int *pGuestRc) 1385 return GuestProcess::waitFlagsToResultEx(fWaitFlags, 1386 mData.mStatus /* curStatus */, mData.mStatus /* newStatus */, 1387 mData.mProcess.mFlags, mSession->getProtocolVersion()); 1388 } 1389 1390 int GuestProcess::waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, 1391 ProcessWaitResult_T &waitResult, int *pGuestRc) 1403 1392 { 1404 1393 AssertReturn(fWaitFlags, VERR_INVALID_PARAMETER); 1405 1394 1406 Auto WriteLock alock(this COMMA_LOCKVAL_SRC_POS);1395 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 1407 1396 1408 1397 LogFlowThisFunc(("fWaitFlags=0x%x, uTimeoutMS=%RU32, procStatus=%RU32, procRc=%Rrc, pGuestRc=%p\n", … … 1410 1399 1411 1400 /* Did some error occur before? Then skip waiting and return. */ 1412 if (mData.mStatus == ProcessStatus_Error) 1401 ProcessStatus_T curStatus = mData.mStatus; 1402 if (curStatus == ProcessStatus_Error) 1413 1403 { 1414 1404 waitResult = ProcessWaitResult_Error; … … 1420 1410 1421 1411 waitResult = waitFlagsToResult(fWaitFlags); 1422 LogFlowThisFunc(("waitFlagToResult=%ld\n", waitResult));1423 1412 1424 1413 /* No waiting needed? Return immediately using the last set error. */ … … 1435 1424 1436 1425 GuestWaitEvent *pEvent = NULL; 1437 std::list < VBoxEventType_T >eventTypes;1426 GuestEventTypes eventTypes; 1438 1427 try 1439 1428 { … … 1453 1442 * Do the actual waiting. 1454 1443 */ 1455 ProcessStatus_T processStatus = ProcessStatus_Undefined;1444 ProcessStatus_T newStatus = ProcessStatus_Undefined; 1456 1445 uint64_t u64StartMS = RTTimeMilliTS(); 1457 1446 for (;;) … … 1468 1457 uTimeoutMS == RT_INDEFINITE_WAIT 1469 1458 ? RT_INDEFINITE_WAIT : uTimeoutMS - (uint32_t)u64ElapsedMS, 1470 & processStatus, pGuestRc);1459 &newStatus, pGuestRc); 1471 1460 if (RT_SUCCESS(vrc)) 1472 1461 { 1473 1462 alock.acquire(); 1474 1463 1475 waitResult = waitFlagsToResultEx(fWaitFlags, processStatus,1464 waitResult = waitFlagsToResultEx(fWaitFlags, curStatus, newStatus, 1476 1465 mData.mProcess.mFlags, mSession->getProtocolVersion()); 1477 LogFlowThisFunc(("Got new status change: waitResult=%ld, processStatus=%ld\n", 1478 waitResult, processStatus)); 1466 #ifdef DEBUG 1467 LogFlowThisFunc(("Got new status change: fWaitFlags=0x%x, newStatus=%ld, waitResult=%ld\n", 1468 fWaitFlags, newStatus, waitResult)); 1469 #endif 1479 1470 if (ProcessWaitResult_None != waitResult) /* We got a waiting result. */ 1480 1471 break; … … 1488 1479 unregisterWaitEvent(pEvent); 1489 1480 1490 LogFlowThisFunc(("Returned waitResult=%ld, processStatus=%ld, rc=%Rrc\n",1491 waitResult, processStatus, vrc));1481 LogFlowThisFunc(("Returned waitResult=%ld, newStatus=%ld, rc=%Rrc\n", 1482 waitResult, newStatus, vrc)); 1492 1483 return vrc; 1493 1484 } … … 1501 1492 ComPtr<IEvent> pIEvent; 1502 1493 int vrc = waitForEvent(pEvent, uTimeoutMS, 1503 &evtType, pIEvent.asOutParam());1494 &evtType, pIEvent.asOutParam()); 1504 1495 if (RT_SUCCESS(vrc)) 1505 1496 { … … 1547 1538 { 1548 1539 vrc = waitForEvent(pEvent, uTimeoutMS, 1549 &evtType, pIEvent.asOutParam());1540 &evtType, pIEvent.asOutParam()); 1550 1541 if (RT_SUCCESS(vrc)) 1551 1542 { 1552 #ifdef DEBUG_andy1553 LogFlowThisFunc(("pEvent=%p, evtType=%ld\n", pEvent, evtType));1554 #endif1555 1543 if (evtType == VBoxEventType_OnGuestProcessOutput) 1556 1544 { … … 1560 1548 ULONG uHandleEvent; 1561 1549 HRESULT hr = pProcessEvent->COMGETTER(Handle)(&uHandleEvent); 1562 LogFlowThisFunc(("Received output, uHandle=%RU32\n", uHandleEvent));1563 1550 if ( SUCCEEDED(hr) 1564 1551 && uHandleEvent == uHandle) … … 1579 1566 else 1580 1567 vrc = VERR_BUFFER_OVERFLOW; 1568 1569 LogFlowThisFunc(("Read %zu bytes (uHandle=%RU32), rc=%Rrc\n", 1570 cbRead, uHandleEvent, vrc)); 1581 1571 } 1582 1572 } … … 1608 1598 } 1609 1599 1610 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));1600 LogFlowFuncLeaveRC(vrc); 1611 1601 return vrc; 1612 1602 } … … 1629 1619 Assert(!pProcessEvent.isNull()); 1630 1620 1631 HRESULT hr; 1621 ProcessStatus_T procStatus; 1622 HRESULT hr = pProcessEvent->COMGETTER(Status)(&procStatus); 1623 ComAssertComRC(hr); 1632 1624 if (pProcessStatus) 1633 { 1634 hr = pProcessEvent->COMGETTER(Status)(pProcessStatus); 1635 ComAssertComRC(hr); 1636 } 1625 *pProcessStatus = procStatus; 1637 1626 1638 1627 ComPtr<IVirtualBoxErrorInfo> errorInfo; … … 1644 1633 ComAssertComRC(hr); 1645 1634 1646 LogFlowThisFunc((" resultDetail=%RI32 (rc=%Rrc)\n",1647 lGuestRc, lGuestRc));1635 LogFlowThisFunc(("procStatus=%RU32, resultDetail=%RI32 (rc=%Rrc)\n", 1636 procStatus, lGuestRc, lGuestRc)); 1648 1637 1649 1638 if (RT_FAILURE((int)lGuestRc)) … … 1654 1643 } 1655 1644 1656 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));1645 LogFlowFuncLeaveRC(vrc); 1657 1646 return vrc; 1658 1647 } … … 1710 1699 1711 1700 GuestWaitEvent *pEvent = NULL; 1712 std::list < VBoxEventType_T >eventTypes;1701 GuestEventTypes eventTypes; 1713 1702 try 1714 1703 { … … 1814 1803 LogFlowThisFunc(("rc=%Rrc, cbRead=%RU32\n", vrc, cbRead)); 1815 1804 1816 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));1805 LogFlowFuncLeaveRC(vrc); 1817 1806 return hr; 1818 1807 #endif /* VBOX_WITH_GUEST_CONTROL */ … … 1861 1850 mSession->processRemoveFromList(this); 1862 1851 1863 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));1852 LogFlowFuncLeaveRC(vrc); 1864 1853 return hr; 1865 1854 #endif /* VBOX_WITH_GUEST_CONTROL */ … … 1909 1898 } 1910 1899 1911 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));1900 LogFlowFuncLeaveRC(vrc); 1912 1901 return hr; 1913 1902 #endif /* VBOX_WITH_GUEST_CONTROL */ … … 1978 1967 *aWritten = (ULONG)cbWritten; 1979 1968 1980 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));1969 LogFlowFuncLeaveRC(vrc); 1981 1970 return hr; 1982 1971 #endif /* VBOX_WITH_GUEST_CONTROL */ … … 2029 2018 AssertPtrReturn(pGuestSession, VERR_INVALID_POINTER); 2030 2019 2031 pSession 2020 pSession = pGuestSession; 2032 2021 mStartupInfo = startupInfo; 2033 2022 … … 2050 2039 } 2051 2040 2052 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));2041 LogFlowFuncLeaveRC(vrc); 2053 2042 return vrc; 2054 2043 } … … 2097 2086 } 2098 2087 2088 /* static */ 2089 int GuestProcessTool::Run( GuestSession *pGuestSession, 2090 const GuestProcessStartupInfo &startupInfo, 2091 int *pGuestRc) 2092 { 2093 return RunEx(pGuestSession, startupInfo, 2094 NULL /* pStrmOutObjects */, 0 /* cStrmOutObjects */, 2095 pGuestRc); 2096 } 2097 2098 /* static */ 2099 int GuestProcessTool::RunEx( GuestSession *pGuestSession, 2100 const GuestProcessStartupInfo &startupInfo, 2101 GuestCtrlStreamObjects *pStrmOutObjects, 2102 uint32_t cStrmOutObjects, 2103 int *pGuestRc) 2104 { 2105 GuestProcessTool procTool; int guestRc; 2106 int vrc = procTool.Init(pGuestSession, startupInfo, false /* Async */, &guestRc); 2107 if (RT_SUCCESS(vrc)) 2108 { 2109 while (cStrmOutObjects--) 2110 { 2111 try 2112 { 2113 GuestProcessStreamBlock strmBlk; 2114 vrc = procTool.WaitEx( pStrmOutObjects 2115 ? GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK 2116 : GUESTPROCESSTOOL_FLAG_NONE, &strmBlk, &guestRc); 2117 if (pStrmOutObjects) 2118 pStrmOutObjects->push_back(strmBlk); 2119 } 2120 catch (std::bad_alloc) 2121 { 2122 vrc = VERR_NO_MEMORY; 2123 } 2124 } 2125 } 2126 2127 if (RT_SUCCESS(vrc)) 2128 { 2129 /* Make sure the process runs until completion. */ 2130 vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc); 2131 2132 Assert(RT_SUCCESS(guestRc)); 2133 guestRc = procTool.TerminatedOk(NULL /* Exit code */); 2134 if (pGuestRc) 2135 *pGuestRc = guestRc; 2136 } 2137 else if (vrc == VERR_GSTCTL_GUEST_ERROR) 2138 { 2139 if (pGuestRc) 2140 *pGuestRc = guestRc; 2141 } 2142 2143 LogFlowFunc(("Returned rc=%Rrc, guestRc=%Rrc\n", vrc, guestRc)); 2144 return vrc; 2145 } 2146 2099 2147 int GuestProcessTool::TerminatedOk(LONG *pExitCode) 2100 2148 { … … 2102 2150 /* pExitCode is optional. */ 2103 2151 2152 int vrc; 2104 2153 if (!IsRunning()) 2105 2154 { … … 2111 2160 *pExitCode = exitCode; 2112 2161 2113 if (exitCode != 0) 2114 return VERR_NOT_EQUAL; /** @todo Special guest control rc needed! */ 2115 return VINF_SUCCESS; 2116 } 2117 2118 return VERR_INVALID_STATE; /** @todo Special guest control rc needed! */ 2162 vrc = (exitCode != 0) 2163 /** @todo Special guest control rc needed! */ 2164 ? VERR_NOT_EQUAL : VINF_SUCCESS; 2165 } 2166 else 2167 vrc = VERR_INVALID_STATE; /** @todo Special guest control rc needed! */ 2168 2169 LogFlowFuncLeaveRC(vrc); 2170 return vrc; 2119 2171 } 2120 2172 2121 2173 int GuestProcessTool::Wait(uint32_t fFlags, int *pGuestRc) 2122 2174 { 2123 return WaitEx(fFlags, NULL /* pStreamBlock */, pGuestRc); 2124 } 2125 2126 int GuestProcessTool::WaitEx(uint32_t fFlags, GuestProcessStreamBlock *pStreamBlock, int *pGuestRc) 2127 { 2128 LogFlowThisFunc(("pSession=%p, fFlags=0x%x, pStreamBlock=%p, pGuestRc=%p\n", 2129 pSession, fFlags, pStreamBlock, pGuestRc)); 2130 2131 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 2132 Assert(!pProcess.isNull()); 2133 /* Other parameters are optional. */ 2175 return WaitEx(fFlags, NULL /* pStrmBlkOut */, pGuestRc); 2176 } 2177 2178 int GuestProcessTool::WaitEx(uint32_t fFlags, GuestProcessStreamBlock *pStrmBlkOut, int *pGuestRc) 2179 { 2180 LogFlowThisFunc(("fFlags=0x%x, pStreamBlock=%p, pGuestRc=%p\n", 2181 fFlags, pStrmBlkOut, pGuestRc)); 2134 2182 2135 2183 /* Can we parse the next block without waiting? */ … … 2137 2185 if (fFlags & GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK) 2138 2186 { 2139 AssertPtr(pStr eamBlock);2140 vrc = GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, *pStr eamBlock);2187 AssertPtr(pStrmBlkOut); 2188 vrc = GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, *pStrmBlkOut); 2141 2189 if (RT_SUCCESS(vrc)) 2142 2190 return vrc; … … 2151 2199 fWaitFlags |= ProcessWaitForFlag_StdErr; 2152 2200 2153 LogFlowThisFunc(("waitFlags=0x%x\n", fWaitFlags));2154 2155 2201 /** @todo Decrease timeout while running. */ 2202 uint64_t u64StartMS = RTTimeMilliTS(); 2156 2203 uint32_t uTimeoutMS = mStartupInfo.mTimeoutMS; 2157 2204 … … 2165 2212 bool fHandleStdErr = false; 2166 2213 2214 /** 2215 * Updates the elapsed time and checks if a 2216 * timeout happened, then breaking out of the loop. 2217 */ 2218 #define UPDATE_AND_CHECK_ELAPSED_TIME() \ 2219 u64ElapsedMS = RTTimeMilliTS() - u64StartMS; \ 2220 if ( uTimeoutMS != RT_INDEFINITE_WAIT \ 2221 && u64ElapsedMS >= uTimeoutMS) \ 2222 { \ 2223 vrc = VERR_TIMEOUT; \ 2224 break; \ 2225 } 2226 2227 /** 2228 * Returns the remaining time (in ms). 2229 */ 2230 #define GET_REMAINING_TIME \ 2231 uTimeoutMS == RT_INDEFINITE_WAIT \ 2232 ? RT_INDEFINITE_WAIT : uTimeoutMS - (uint32_t)u64ElapsedMS \ 2233 2167 2234 ProcessWaitResult_T waitRes; 2168 2235 do 2169 2236 { 2170 vrc = pProcess->waitFor(fWaitFlags, 2171 uTimeoutMS, waitRes, &guestRc); 2237 uint64_t u64ElapsedMS; 2238 UPDATE_AND_CHECK_ELAPSED_TIME(); 2239 2240 vrc = pProcess->waitFor(fWaitFlags, GET_REMAINING_TIME, 2241 waitRes, &guestRc); 2172 2242 if (RT_FAILURE(vrc)) 2173 2243 break; … … 2219 2289 } 2220 2290 2291 if (RT_FAILURE(vrc)) 2292 break; 2293 2221 2294 if (fHandleStdOut) 2222 2295 { 2296 UPDATE_AND_CHECK_ELAPSED_TIME(); 2297 2223 2298 cbRead = 0; 2224 2299 vrc = pProcess->readData(OUTPUT_HANDLE_ID_STDOUT, sizeof(byBuf), 2225 uTimeoutMS, byBuf, sizeof(byBuf), 2300 GET_REMAINING_TIME, 2301 byBuf, sizeof(byBuf), 2226 2302 &cbRead, &guestRc); 2227 if (RT_FAILURE(vrc)) 2303 if ( RT_FAILURE(vrc) 2304 || vrc == VWRN_GSTCTL_OBJECTSTATE_CHANGED) 2228 2305 break; 2229 2306 … … 2236 2313 && (fFlags & GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK)) 2237 2314 { 2238 AssertPtr(pStreamBlock); 2239 vrc = GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, *pStreamBlock); 2315 AssertPtr(pStrmBlkOut); 2316 vrc = GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, *pStrmBlkOut); 2317 2318 /* When successful, break out of the loop because we're done 2319 * with reading the first stream block. */ 2240 2320 if (RT_SUCCESS(vrc)) 2241 2321 fDone = true; … … 2248 2328 if (fHandleStdErr) 2249 2329 { 2330 UPDATE_AND_CHECK_ELAPSED_TIME(); 2331 2250 2332 cbRead = 0; 2251 2333 vrc = pProcess->readData(OUTPUT_HANDLE_ID_STDERR, sizeof(byBuf), 2252 uTimeoutMS, byBuf, sizeof(byBuf), 2334 GET_REMAINING_TIME, 2335 byBuf, sizeof(byBuf), 2253 2336 &cbRead, &guestRc); 2254 if (RT_FAILURE(vrc)) 2337 if ( RT_FAILURE(vrc) 2338 || vrc == VWRN_GSTCTL_OBJECTSTATE_CHANGED) 2255 2339 break; 2256 2340 … … 2266 2350 } while (!fDone && RT_SUCCESS(vrc)); 2267 2351 2352 #undef UPDATE_AND_CHECK_ELAPSED_TIME 2353 #undef GET_REMAINING_TIME 2354 2268 2355 LogFlowThisFunc(("Loop ended with rc=%Rrc, guestRc=%Rrc, waitRes=%ld\n", 2269 2356 vrc, guestRc, waitRes)); … … 2271 2358 *pGuestRc = guestRc; 2272 2359 2273 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));2360 LogFlowFuncLeaveRC(vrc); 2274 2361 return vrc; 2275 2362 } -
trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp
r48342 r49349 114 114 { 115 115 Assert(!mSession.isNull()); 116 int rc2 = mSession->signalWaitEvent s(aType, aEvent);116 int rc2 = mSession->signalWaitEvent(aType, aEvent); 117 117 #ifdef DEBUG_andy 118 118 LogFlowFunc(("Signalling events of type=%ld, session=%p resulted in rc=%Rrc\n", … … 289 289 itDirs != mData.mDirectories.end(); ++itDirs) 290 290 { 291 (*itDirs)->Release();291 itDirs->second->Release(); 292 292 } 293 293 mData.mDirectories.clear(); … … 665 665 666 666 GuestWaitEvent *pEvent = NULL; 667 std::list < VBoxEventType_T >eventTypes;667 GuestEventTypes eventTypes; 668 668 try 669 669 { … … 702 702 } 703 703 704 int GuestSession::directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode, 705 uint32_t uFlags, int *pGuestRc) 706 { 707 LogFlowThisFunc(("strPath=%s, uMode=%x, uFlags=%x\n", 708 strPath.c_str(), uMode, uFlags)); 709 710 int vrc = VINF_SUCCESS; 711 712 GuestProcessStartupInfo procInfo; 713 procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_MKDIR); 714 procInfo.mFlags = ProcessCreateFlag_Hidden; 715 716 try 717 { 718 /* Construct arguments. */ 719 if (uFlags & DirectoryCreateFlag_Parents) 720 procInfo.mArguments.push_back(Utf8Str("--parents")); /* We also want to create the parent directories. */ 721 if (uMode) 722 { 723 procInfo.mArguments.push_back(Utf8Str("--mode")); /* Set the creation mode. */ 724 725 char szMode[16]; 726 if (RTStrPrintf(szMode, sizeof(szMode), "%o", uMode)) 727 { 728 procInfo.mArguments.push_back(Utf8Str(szMode)); 729 } 730 else 731 vrc = VERR_BUFFER_OVERFLOW; 732 } 733 procInfo.mArguments.push_back(strPath); /* The directory we want to create. */ 734 } 735 catch (std::bad_alloc) 736 { 737 vrc = VERR_NO_MEMORY; 738 } 739 740 if (RT_SUCCESS(vrc)) 741 vrc = GuestProcessTool::Run(this, procInfo, pGuestRc); 742 743 LogFlowFuncLeaveRC(vrc); 744 return vrc; 745 } 746 747 inline bool GuestSession::directoryExists(uint32_t uDirID, ComObjPtr<GuestDirectory> *pDir) 748 { 749 SessionDirectories::const_iterator it = mData.mDirectories.find(uDirID); 750 if (it != mData.mDirectories.end()) 751 { 752 if (pDir) 753 *pDir = it->second; 754 return true; 755 } 756 return false; 757 } 758 759 int GuestSession::directoryQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc) 760 { 761 LogFlowThisFunc(("strPath=%s\n", strPath.c_str())); 762 763 int vrc = fsQueryInfoInternal(strPath, objData, pGuestRc); 764 if (RT_SUCCESS(vrc)) 765 { 766 vrc = objData.mType == FsObjType_Directory 767 ? VINF_SUCCESS : VERR_NOT_A_DIRECTORY; 768 } 769 770 LogFlowFuncLeaveRC(vrc); 771 return vrc; 772 } 773 704 774 int GuestSession::directoryRemoveFromList(GuestDirectory *pDirectory) 705 775 { … … 709 779 itDirs != mData.mDirectories.end(); ++itDirs) 710 780 { 711 if (pDirectory == (*itDirs))781 if (pDirectory == itDirs->second) 712 782 { 713 783 Bstr strName; 714 HRESULT hr = (*itDirs)->COMGETTER(DirectoryName)(strName.asOutParam());784 HRESULT hr = itDirs->second->COMGETTER(DirectoryName)(strName.asOutParam()); 715 785 ComAssertComRC(hr); 716 786 … … 727 797 } 728 798 729 int GuestSession::directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode, uint32_t uFlags, int *pGuestRc) 730 { 731 /* pGuestRc is optional. */ 732 733 LogFlowThisFunc(("strPath=%s, uMode=%x, uFlags=%x\n", 734 strPath.c_str(), uMode, uFlags)); 735 736 GuestProcessStartupInfo procInfo; 737 procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_MKDIR); 738 procInfo.mFlags = ProcessCreateFlag_Hidden; 739 740 int vrc = VINF_SUCCESS; 741 742 /* Construct arguments. */ 743 if (uFlags & DirectoryCreateFlag_Parents) 744 procInfo.mArguments.push_back(Utf8Str("--parents")); /* We also want to create the parent directories. */ 745 if (uMode) 746 { 747 procInfo.mArguments.push_back(Utf8Str("--mode")); /* Set the creation mode. */ 748 749 char szMode[16]; 750 if (RTStrPrintf(szMode, sizeof(szMode), "%o", uMode)) 751 { 752 procInfo.mArguments.push_back(Utf8Str(szMode)); 753 } 754 else 755 vrc = VERR_BUFFER_OVERFLOW; 756 } 757 procInfo.mArguments.push_back(strPath); /* The directory we want to create. */ 758 799 int GuestSession::directoryRemoveInternal(const Utf8Str &strPath, uint32_t uFlags, 800 int *pGuestRc) 801 { 802 AssertReturn(!(uFlags & ~DIRREMOVE_FLAG_VALID_MASK), VERR_INVALID_PARAMETER); 803 804 LogFlowThisFunc(("strPath=%s, uFlags=0x%x\n", strPath.c_str(), uFlags)); 805 806 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 807 808 GuestWaitEvent *pEvent = NULL; 809 int vrc = registerWaitEvent(mData.mSession.mID, 0 /* Object ID */, 810 &pEvent); 811 if (RT_FAILURE(vrc)) 812 return vrc; 813 814 /* Prepare HGCM call. */ 815 VBOXHGCMSVCPARM paParms[8]; 816 int i = 0; 817 paParms[i++].setUInt32(pEvent->ContextID()); 818 paParms[i++].setPointer((void*)strPath.c_str(), 819 (ULONG)strPath.length() + 1); 820 paParms[i++].setUInt32(uFlags); 821 822 alock.release(); /* Drop write lock before sending. */ 823 824 vrc = sendCommand(HOST_DIR_REMOVE, i, paParms); 759 825 if (RT_SUCCESS(vrc)) 760 826 { 761 int guestRc; 762 GuestProcessTool procTool; 763 vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc); 764 if (RT_SUCCESS(vrc)) 765 { 766 if (RT_SUCCESS(guestRc)) 767 vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc); 768 } 769 770 if (RT_SUCCESS(vrc)) 771 { 772 if (RT_SUCCESS(guestRc)) 773 guestRc = procTool.TerminatedOk(NULL /* Exit code */); 774 } 775 827 vrc = pEvent->Wait(30 * 1000); 776 828 if ( vrc == VERR_GSTCTL_GUEST_ERROR 777 829 && pGuestRc) 778 {779 *pGuestRc = guestRc;780 } 781 }830 *pGuestRc = pEvent->GuestResult(); 831 } 832 833 unregisterWaitEvent(pEvent); 782 834 783 835 LogFlowFuncLeaveRC(vrc); … … 785 837 } 786 838 787 int GuestSession::directoryQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc)788 {789 LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));790 791 int vrc = fsQueryInfoInternal(strPath, objData, pGuestRc);792 if (RT_SUCCESS(vrc))793 {794 vrc = objData.mType == FsObjType_Directory795 ? VINF_SUCCESS : VERR_NOT_A_DIRECTORY;796 }797 798 LogFlowFuncLeaveRC(vrc);799 return vrc;800 }801 802 839 int GuestSession::objectCreateTempInternal(const Utf8Str &strTemplate, const Utf8Str &strPath, 803 840 bool fDirectory, const Utf8Str &strName, int *pGuestRc) 804 841 { 842 LogFlowThisFunc(("strTemplate=%s, strPath=%s, fDirectory=%RTbool, strName=%s\n", 843 strTemplate.c_str(), strPath.c_str(), fDirectory, strName.c_str())); 844 845 int vrc = VINF_SUCCESS; 846 805 847 GuestProcessStartupInfo procInfo; 806 848 procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_MKTEMP); 807 849 procInfo.mFlags = ProcessCreateFlag_WaitForStdOut; 808 procInfo.mArguments.push_back(Utf8Str("--machinereadable")); 809 if (fDirectory) 810 procInfo.mArguments.push_back(Utf8Str("-d")); 811 if (strPath.length()) /* Otherwise use /tmp or equivalent. */ 812 { 813 procInfo.mArguments.push_back(Utf8Str("-t")); 814 procInfo.mArguments.push_back(strPath); 815 } 816 procInfo.mArguments.push_back(strTemplate); 817 818 GuestProcessTool procTool; int guestRc; 819 int vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc); 850 851 try 852 { 853 procInfo.mArguments.push_back(Utf8Str("--machinereadable")); 854 if (fDirectory) 855 procInfo.mArguments.push_back(Utf8Str("-d")); 856 if (strPath.length()) /* Otherwise use /tmp or equivalent. */ 857 { 858 procInfo.mArguments.push_back(Utf8Str("-t")); 859 procInfo.mArguments.push_back(strPath); 860 } 861 procInfo.mArguments.push_back(strTemplate); 862 } 863 catch (std::bad_alloc) 864 { 865 vrc = VERR_NO_MEMORY; 866 } 867 820 868 if (RT_SUCCESS(vrc)) 821 { 822 if (RT_SUCCESS(guestRc)) 823 vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc); 824 } 825 826 if (RT_SUCCESS(vrc)) 827 { 828 if (RT_SUCCESS(guestRc)) 829 guestRc = procTool.TerminatedOk(NULL /* Exit code */); 830 } 831 832 if ( vrc == VERR_GSTCTL_GUEST_ERROR 833 && pGuestRc) 834 { 835 *pGuestRc = guestRc; 836 } 869 vrc = GuestProcessTool::Run(this, procInfo, pGuestRc); 837 870 838 871 LogFlowFuncLeaveRC(vrc); … … 840 873 } 841 874 842 int GuestSession::directoryOpenInternal(const Utf8Str &strPath, const Utf8Str &strFilter,843 uint32_t uFlags, ComObjPtr<GuestDirectory> &pDirectory)875 int GuestSession::directoryOpenInternal(const GuestDirectoryOpenInfo &openInfo, 876 ComObjPtr<GuestDirectory> &pDirectory, int *pGuestRc) 844 877 { 845 878 LogFlowThisFunc(("strPath=%s, strPath=%s, uFlags=%x\n", 846 strPath.c_str(), strFilter.c_str(), uFlags));879 openInfo.mPath.c_str(), openInfo.mFilter.c_str(), openInfo.mFlags)); 847 880 848 881 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 882 883 int rc = VERR_MAX_PROCS_REACHED; 884 if (mData.mNumObjects >= VBOX_GUESTCTRL_MAX_OBJECTS) 885 return rc; 886 887 /* Create a new (host-based) directory ID and assign it. */ 888 uint32_t uNewDirID = 0; 889 ULONG uTries = 0; 890 891 for (;;) 892 { 893 /* Is the directory ID already used? */ 894 if (!directoryExists(uNewDirID, NULL /* pDirectory */)) 895 { 896 /* Callback with context ID was not found. This means 897 * we can use this context ID for our new callback we want 898 * to add below. */ 899 rc = VINF_SUCCESS; 900 break; 901 } 902 uNewDirID++; 903 if (uNewDirID == VBOX_GUESTCTRL_MAX_OBJECTS) 904 uNewDirID = 0; 905 906 if (++uTries == UINT32_MAX) 907 break; /* Don't try too hard. */ 908 } 909 910 if (RT_FAILURE(rc)) 911 return rc; 849 912 850 913 /* Create the directory object. */ … … 853 916 return VERR_COM_UNEXPECTED; 854 917 855 int vrc = pDirectory->init(this /* Parent */, 856 strPath, strFilter, uFlags); 918 Console *pConsole = mParent->getConsole(); 919 AssertPtr(pConsole); 920 921 int vrc = pDirectory->init(pConsole, this /* Parent */, 922 uNewDirID, openInfo); 857 923 if (RT_FAILURE(vrc)) 858 924 return vrc; 859 925 860 /* Add the created directory to our vector. */ 861 mData.mDirectories.push_back(pDirectory); 862 863 LogFlowFunc(("Added new directory \"%s\" (Session: %RU32)\n", 864 strPath.c_str(), mData.mSession.mID)); 926 /* 927 * Since this is a synchronous guest call we have to 928 * register the file object first, releasing the session's 929 * lock and then proceed with the actual opening command 930 * -- otherwise the file's opening callback would hang 931 * because the session's lock still is in place. 932 */ 933 try 934 { 935 /* Add the created directory to our map. */ 936 mData.mDirectories[uNewDirID] = pDirectory; 937 mData.mNumObjects++; 938 Assert(mData.mNumObjects <= VBOX_GUESTCTRL_MAX_OBJECTS); 939 940 LogFlowFunc(("Added new guest directory \"%s\" (Session: %RU32) (now total %ld dirs, %ld objects)\n", 941 openInfo.mPath.c_str(), mData.mSession.mID, mData.mFiles.size(), mData.mNumObjects)); 942 943 alock.release(); /* Release lock before firing off event. */ 944 945 /** @todo Fire off a VBoxEventType_OnGuestDirectoryRegistered event? */ 946 } 947 catch (std::bad_alloc &) 948 { 949 rc = VERR_NO_MEMORY; 950 } 951 952 if (RT_SUCCESS(rc)) 953 { 954 /* Nothing further to do here yet. */ 955 if (pGuestRc) 956 *pGuestRc = VINF_SUCCESS; 957 } 865 958 866 959 LogFlowFuncLeaveRC(vrc); 867 960 return vrc; 961 } 962 963 int GuestSession::dispatchToDirectory(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb) 964 { 965 LogFlowFunc(("pCtxCb=%p, pSvcCb=%p\n", pCtxCb, pSvcCb)); 966 967 AssertPtrReturn(pCtxCb, VERR_INVALID_POINTER); 968 AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER); 969 970 if (pSvcCb->mParms < 3) 971 return VERR_INVALID_PARAMETER; 972 973 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 974 975 uint32_t uDirID = VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCtxCb->uContextID); 976 #ifdef DEBUG 977 LogFlowFunc(("uDirID=%RU32 (%RU32 total)\n", 978 uDirID, mData.mFiles.size())); 979 #endif 980 int rc; 981 SessionDirectories::const_iterator itDir 982 = mData.mDirectories.find(uDirID); 983 if (itDir != mData.mDirectories.end()) 984 { 985 ComObjPtr<GuestDirectory> pDirectory(itDir->second); 986 Assert(!pDirectory.isNull()); 987 988 alock.release(); 989 990 rc = pDirectory->callbackDispatcher(pCtxCb, pSvcCb); 991 } 992 else 993 rc = VERR_NOT_FOUND; 994 995 LogFlowFuncLeaveRC(rc); 996 return rc; 868 997 } 869 998 … … 901 1030 } 902 1031 1032 int GuestSession::dispatchToObject(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb) 1033 { 1034 LogFlowFunc(("pCtxCb=%p, pSvcCb=%p\n", pCtxCb, pSvcCb)); 1035 1036 AssertPtrReturn(pCtxCb, VERR_INVALID_POINTER); 1037 AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER); 1038 1039 int rc; 1040 uint32_t uObjectID = VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCtxCb->uContextID); 1041 1042 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 1043 1044 /* Since we don't know which type the object is, we need to through all 1045 * all objects. */ 1046 /** @todo Speed this up by adding an object type to the callback context! */ 1047 SessionProcesses::const_iterator itProc = mData.mProcesses.find(uObjectID); 1048 if (itProc == mData.mProcesses.end()) 1049 { 1050 SessionFiles::const_iterator itFile = mData.mFiles.find(uObjectID); 1051 if (itFile != mData.mFiles.end()) 1052 { 1053 alock.release(); 1054 1055 rc = dispatchToFile(pCtxCb, pSvcCb); 1056 } 1057 else 1058 { 1059 SessionDirectories::const_iterator itDir = mData.mDirectories.find(uObjectID); 1060 if (itDir != mData.mDirectories.end()) 1061 { 1062 alock.release(); 1063 1064 rc = dispatchToDirectory(pCtxCb, pSvcCb); 1065 } 1066 else 1067 rc = VERR_NOT_FOUND; 1068 } 1069 } 1070 else 1071 { 1072 alock.release(); 1073 1074 rc = dispatchToProcess(pCtxCb, pSvcCb); 1075 } 1076 1077 LogFlowFuncLeaveRC(rc); 1078 return rc; 1079 } 1080 903 1081 int GuestSession::dispatchToProcess(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb) 904 1082 { … … 949 1127 #endif 950 1128 951 int rc = VINF_SUCCESS;1129 int rc; 952 1130 switch (pCbCtx->uFunction) 953 1131 { … … 956 1134 break; 957 1135 958 case GUEST_SESSION_NOTIFY: 1136 case GUEST_SESSION_NOTIFY: /* Guest Additions >= 4.3.0. */ 959 1137 { 960 1138 rc = onSessionStatusChange(pCbCtx, pSvcCb); … … 1024 1202 int GuestSession::fileRemoveInternal(const Utf8Str &strPath, int *pGuestRc) 1025 1203 { 1204 LogFlowThisFunc(("strPath=%s\n", strPath.c_str())); 1205 1206 int vrc = VINF_SUCCESS; 1207 1026 1208 GuestProcessStartupInfo procInfo; 1027 1209 GuestProcessStream streamOut; … … 1029 1211 procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_RM); 1030 1212 procInfo.mFlags = ProcessCreateFlag_WaitForStdOut; 1031 procInfo.mArguments.push_back(Utf8Str("--machinereadable")); 1032 procInfo.mArguments.push_back(strPath); /* The file we want to remove. */ 1033 1034 GuestProcessTool procTool; int guestRc; 1035 int vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc); 1213 1214 try 1215 { 1216 procInfo.mArguments.push_back(Utf8Str("--machinereadable")); 1217 procInfo.mArguments.push_back(strPath); /* The file we want to remove. */ 1218 } 1219 catch (std::bad_alloc) 1220 { 1221 vrc = VERR_NO_MEMORY; 1222 } 1223 1036 1224 if (RT_SUCCESS(vrc)) 1037 vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc); 1038 1039 if (RT_SUCCESS(vrc)) 1040 { 1041 if (RT_SUCCESS(guestRc)) 1042 guestRc = procTool.TerminatedOk(NULL /* Exit code */); 1043 } 1044 1045 if ( vrc == VERR_GSTCTL_GUEST_ERROR 1046 && pGuestRc) 1047 { 1048 *pGuestRc = guestRc; 1049 } 1225 vrc = GuestProcessTool::Run(this, procInfo, pGuestRc); 1050 1226 1051 1227 LogFlowFuncLeaveRC(vrc); … … 1053 1229 } 1054 1230 1055 int GuestSession::fileOpenInternal(const GuestFileOpenInfo &openInfo, ComObjPtr<GuestFile> &pFile, int *pGuestRc) 1231 int GuestSession::fileOpenInternal(const GuestFileOpenInfo &openInfo, 1232 ComObjPtr<GuestFile> &pFile, int *pGuestRc) 1056 1233 { 1057 1234 LogFlowThisFunc(("strPath=%s, strOpenMode=%s, strDisposition=%s, uCreationMode=%x, uOffset=%RU64\n", … … 1080 1257 { 1081 1258 /* Is the file ID already used? */ 1082 if (!fileExists(uNewFileID, NULL /* p Progress*/))1259 if (!fileExists(uNewFileID, NULL /* pFile */)) 1083 1260 { 1084 1261 /* Callback with context ID was not found. This means … … 1185 1362 LogFlowThisFunc(("strPath=%s\n", strPath.c_str())); 1186 1363 1364 int vrc = VINF_SUCCESS; 1365 1187 1366 /** @todo Merge this with IGuestFile::queryInfo(). */ 1188 1367 GuestProcessStartupInfo procInfo; … … 1190 1369 procInfo.mFlags = ProcessCreateFlag_WaitForStdOut; 1191 1370 1192 /* Construct arguments. */ 1193 procInfo.mArguments.push_back(Utf8Str("--machinereadable")); 1194 procInfo.mArguments.push_back(strPath); 1195 1196 GuestProcessTool procTool; int guestRc; 1197 int vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc); 1371 try 1372 { 1373 /* Construct arguments. */ 1374 procInfo.mArguments.push_back(Utf8Str("--machinereadable")); 1375 procInfo.mArguments.push_back(strPath); 1376 } 1377 catch (std::bad_alloc) 1378 { 1379 vrc = VERR_NO_MEMORY; 1380 } 1381 1382 int guestRc; GuestCtrlStreamObjects stdOut; 1198 1383 if (RT_SUCCESS(vrc)) 1199 vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc); 1200 if (RT_SUCCESS(vrc)) 1201 { 1202 guestRc = procTool.TerminatedOk(NULL /* Exit code */); 1203 if (RT_SUCCESS(guestRc)) 1204 { 1205 GuestProcessStreamBlock curBlock; 1206 vrc = procTool.GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, curBlock); 1207 /** @todo Check for more / validate blocks! */ 1208 if (RT_SUCCESS(vrc)) 1209 vrc = objData.FromStat(curBlock); 1210 } 1211 } 1212 1213 if ( vrc == VERR_GSTCTL_GUEST_ERROR 1214 && pGuestRc) 1215 { 1216 *pGuestRc = guestRc; 1384 vrc = GuestProcessTool::RunEx(this, procInfo, 1385 &stdOut, 1 /* cStrmOutObjects */, 1386 &guestRc); 1387 if ( RT_SUCCESS(vrc) 1388 && RT_SUCCESS(guestRc)) 1389 { 1390 if (!stdOut.empty()) 1391 vrc = objData.FromStat(stdOut.at(0)); 1392 else 1393 vrc = VERR_NO_DATA; 1217 1394 } 1218 1395 … … 1403 1580 /* Set current session status. */ 1404 1581 mData.mStatus = GuestSessionStatus_Starting; 1582 mData.mRC = VINF_SUCCESS; /* Clear previous error, if any. */ 1405 1583 1406 1584 int vrc; 1407 1585 1408 1586 GuestWaitEvent *pEvent = NULL; 1409 std::list < VBoxEventType_T >eventTypes;1587 GuestEventTypes eventTypes; 1410 1588 try 1411 1589 { … … 1440 1618 vrc = sendCommand(HOST_SESSION_CREATE, i, paParms); 1441 1619 if (RT_SUCCESS(vrc)) 1620 { 1442 1621 vrc = waitForStatusChange(pEvent, GuestSessionWaitForFlag_Start, 1443 1622 30 * 1000 /* 30s timeout */, 1444 1623 NULL /* Session status */, pGuestRc); 1624 } 1625 else 1626 { 1627 /* 1628 * Unable to start guest session - update its current state. 1629 * Since there is no (official API) way to recover a failed guest session 1630 * this also marks the end state. Internally just calling this 1631 * same function again will work though. 1632 */ 1633 mData.mStatus = GuestSessionStatus_Error; 1634 mData.mRC = vrc; 1635 } 1445 1636 1446 1637 unregisterWaitEvent(pEvent); … … 1498 1689 int vrc = pSession->startSessionInternal(NULL /* Guest rc, ignored */); 1499 1690 /* Nothing to do here anymore. */ 1691 1692 LogFlowFuncLeaveRC(vrc); 1693 return vrc; 1694 } 1695 1696 int GuestSession::pathRenameInternal(const Utf8Str &strSource, const Utf8Str &strDest, 1697 uint32_t uFlags, int *pGuestRc) 1698 { 1699 AssertReturn(!(uFlags & ~PATHRENAME_FLAG_VALID_MASK), VERR_INVALID_PARAMETER); 1700 1701 LogFlowThisFunc(("strSource=%s, strDest=%s, uFlags=0x%x\n", 1702 strSource.c_str(), strDest.c_str(), uFlags)); 1703 1704 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 1705 1706 GuestWaitEvent *pEvent = NULL; 1707 int vrc = registerWaitEvent(mData.mSession.mID, 0 /* Object ID */, 1708 &pEvent); 1709 if (RT_FAILURE(vrc)) 1710 return vrc; 1711 1712 /* Prepare HGCM call. */ 1713 VBOXHGCMSVCPARM paParms[8]; 1714 int i = 0; 1715 paParms[i++].setUInt32(pEvent->ContextID()); 1716 paParms[i++].setPointer((void*)strSource.c_str(), 1717 (ULONG)strSource.length() + 1); 1718 paParms[i++].setPointer((void*)strDest.c_str(), 1719 (ULONG)strDest.length() + 1); 1720 paParms[i++].setUInt32(uFlags); 1721 1722 alock.release(); /* Drop write lock before sending. */ 1723 1724 vrc = sendCommand(HOST_PATH_RENAME, i, paParms); 1725 if (RT_SUCCESS(vrc)) 1726 { 1727 vrc = pEvent->Wait(30 * 1000); 1728 if ( vrc == VERR_GSTCTL_GUEST_ERROR 1729 && pGuestRc) 1730 *pGuestRc = pEvent->GuestResult(); 1731 } 1732 1733 unregisterWaitEvent(pEvent); 1500 1734 1501 1735 LogFlowFuncLeaveRC(vrc); … … 1625 1859 { 1626 1860 /* Is the context ID already used? */ 1627 if (!processExists(uNewProcessID, NULL /* pPro gress */))1861 if (!processExists(uNewProcessID, NULL /* pProcess */)) 1628 1862 { 1629 1863 /* Callback with context ID was not found. This means … … 1988 2222 1989 2223 GuestWaitEvent *pEvent = NULL; 1990 std::list < VBoxEventType_T >eventTypes;2224 GuestEventTypes eventTypes; 1991 2225 try 1992 2226 { … … 2110 2344 /* Remove ourselves from the session list. */ 2111 2345 int rc2 = mParent->sessionRemove(this); 2346 if (rc2 == VERR_NOT_FOUND) /* Not finding the session anymore isn't critical. */ 2347 rc2 = VINF_SUCCESS; 2348 2112 2349 if (RT_SUCCESS(rc)) 2113 2350 rc = rc2; … … 2418 2655 HRESULT hr = S_OK; 2419 2656 2420 ComObjPtr <GuestDirectory> pDirectory; 2421 int rc = directoryOpenInternal(Utf8Str(aPath), Utf8Str(aFilter), fFlags, pDirectory); 2657 GuestDirectoryOpenInfo openInfo; 2658 openInfo.mPath = Utf8Str(aPath); 2659 openInfo.mFilter = Utf8Str(aFilter); 2660 openInfo.mFlags = fFlags; 2661 2662 ComObjPtr <GuestDirectory> pDirectory; int guestRc; 2663 int rc = directoryOpenInternal(openInfo, pDirectory, &guestRc); 2422 2664 if (RT_SUCCESS(rc)) 2423 2665 { … … 2433 2675 Utf8Str(aPath).c_str())); 2434 2676 break; 2677 2678 case VERR_GSTCTL_GUEST_ERROR: 2679 hr = GuestDirectory::setErrorExternal(this, guestRc); 2680 break; 2435 2681 2436 2682 default: … … 2511 2757 LogFlowThisFuncEnter(); 2512 2758 2513 AutoCaller autoCaller(this); 2514 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 2515 2516 ReturnComNotImplemented(); 2759 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0')) 2760 return setError(E_INVALIDARG, tr("No directory to remove specified")); 2761 2762 AutoCaller autoCaller(this); 2763 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 2764 2765 HRESULT hr = isReadyExternal(); 2766 if (FAILED(hr)) 2767 return hr; 2768 2769 /* No flags; only remove the directory when empty. */ 2770 uint32_t uFlags = 0; 2771 2772 int guestRc; 2773 int vrc = directoryRemoveInternal(Utf8Str(aPath), uFlags, &guestRc); 2774 if (RT_FAILURE(vrc)) 2775 { 2776 switch (vrc) 2777 { 2778 case VERR_NOT_SUPPORTED: 2779 hr = setError(VBOX_E_IPRT_ERROR, 2780 tr("Handling removing guest directories not supported by installed Guest Additions")); 2781 break; 2782 2783 case VERR_GSTCTL_GUEST_ERROR: 2784 hr = GuestDirectory::setErrorExternal(this, guestRc); 2785 break; 2786 2787 default: 2788 hr = setError(VBOX_E_IPRT_ERROR, tr("Removing guest directory \"%s\" failed: %Rrc"), 2789 Utf8Str(aPath).c_str(), vrc); 2790 break; 2791 } 2792 } 2793 2794 return hr; 2517 2795 #endif /* VBOX_WITH_GUEST_CONTROL */ 2518 2796 } … … 2525 2803 LogFlowThisFuncEnter(); 2526 2804 2527 AutoCaller autoCaller(this); 2528 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 2529 2530 ReturnComNotImplemented(); 2805 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0')) 2806 return setError(E_INVALIDARG, tr("No directory to remove recursively specified")); 2807 2808 AutoCaller autoCaller(this); 2809 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 2810 2811 HRESULT hr = isReadyExternal(); 2812 if (FAILED(hr)) 2813 return hr; 2814 2815 ComObjPtr<Progress> pProgress; 2816 hr = pProgress.createObject(); 2817 if (SUCCEEDED(hr)) 2818 hr = pProgress->init(static_cast<IGuestSession *>(this), 2819 Bstr(tr("Removing guest directory")).raw(), 2820 TRUE /*aCancelable*/); 2821 if (FAILED(hr)) 2822 return hr; 2823 2824 /* Note: At the moment we don't supply progress information while 2825 * deleting a guest directory recursively. So just complete 2826 * the progress object right now. */ 2827 /** @todo Implement progress reporting on guest directory deletion! */ 2828 hr = pProgress->notifyComplete(S_OK); 2829 if (FAILED(hr)) 2830 return hr; 2831 2832 /* Remove the directory + all its contents. */ 2833 uint32_t uFlags = DIRREMOVE_FLAG_RECURSIVE 2834 | DIRREMOVE_FLAG_CONTENT_AND_DIR; 2835 int guestRc; 2836 int vrc = directoryRemoveInternal(Utf8Str(aPath), uFlags, &guestRc); 2837 if (RT_FAILURE(vrc)) 2838 { 2839 switch (vrc) 2840 { 2841 case VERR_NOT_SUPPORTED: 2842 hr = setError(VBOX_E_IPRT_ERROR, 2843 tr("Handling removing guest directories recursively not supported by installed Guest Additions")); 2844 break; 2845 2846 case VERR_GSTCTL_GUEST_ERROR: 2847 hr = GuestFile::setErrorExternal(this, guestRc); 2848 break; 2849 2850 default: 2851 hr = setError(VBOX_E_IPRT_ERROR, tr("Recursively removing guest directory \"%s\" failed: %Rrc"), 2852 Utf8Str(aPath).c_str(), vrc); 2853 break; 2854 } 2855 } 2856 else 2857 { 2858 pProgress.queryInterfaceTo(aProgress); 2859 } 2860 2861 return hr; 2531 2862 #endif /* VBOX_WITH_GUEST_CONTROL */ 2532 2863 } … … 2539 2870 LogFlowThisFuncEnter(); 2540 2871 2541 AutoCaller autoCaller(this); 2542 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 2543 2544 ReturnComNotImplemented(); 2872 if (RT_UNLIKELY((aSource) == NULL || *(aSource) == '\0')) 2873 return setError(E_INVALIDARG, tr("No source directory to rename specified")); 2874 2875 if (RT_UNLIKELY((aDest) == NULL || *(aDest) == '\0')) 2876 return setError(E_INVALIDARG, tr("No destination directory to rename the source to specified")); 2877 2878 AutoCaller autoCaller(this); 2879 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 2880 2881 HRESULT hr = isReadyExternal(); 2882 if (FAILED(hr)) 2883 return hr; 2884 2885 /* No flags; only remove the directory when empty. */ 2886 uint32_t uFlags = 0; 2887 2888 int guestRc; 2889 int vrc = pathRenameInternal(Utf8Str(aSource), Utf8Str(aDest), uFlags, &guestRc); 2890 if (RT_FAILURE(vrc)) 2891 { 2892 switch (vrc) 2893 { 2894 case VERR_NOT_SUPPORTED: 2895 hr = setError(VBOX_E_IPRT_ERROR, 2896 tr("Handling renaming guest directories not supported by installed Guest Additions")); 2897 break; 2898 2899 case VERR_GSTCTL_GUEST_ERROR: 2900 hr = setError(VBOX_E_IPRT_ERROR, 2901 tr("Renaming guest directory failed: %Rrc"), guestRc); 2902 break; 2903 2904 default: 2905 hr = setError(VBOX_E_IPRT_ERROR, tr("Renaming guest directory \"%s\" failed: %Rrc"), 2906 Utf8Str(aSource).c_str(), vrc); 2907 break; 2908 } 2909 } 2910 2911 return hr; 2545 2912 #endif /* VBOX_WITH_GUEST_CONTROL */ 2546 2913 } … … 2930 3297 LogFlowThisFuncEnter(); 2931 3298 2932 AutoCaller autoCaller(this); 2933 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 2934 2935 ReturnComNotImplemented(); 3299 if (RT_UNLIKELY((aSource) == NULL || *(aSource) == '\0')) 3300 return setError(E_INVALIDARG, tr("No source file to rename specified")); 3301 3302 if (RT_UNLIKELY((aDest) == NULL || *(aDest) == '\0')) 3303 return setError(E_INVALIDARG, tr("No destination file to rename the source to specified")); 3304 3305 AutoCaller autoCaller(this); 3306 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 3307 3308 HRESULT hr = isReadyExternal(); 3309 if (FAILED(hr)) 3310 return hr; 3311 3312 /* No flags; only remove the directory when empty. */ 3313 uint32_t uFlags = 0; 3314 3315 int guestRc; 3316 int vrc = pathRenameInternal(Utf8Str(aSource), Utf8Str(aDest), uFlags, &guestRc); 3317 if (RT_FAILURE(vrc)) 3318 { 3319 switch (vrc) 3320 { 3321 case VERR_NOT_SUPPORTED: 3322 hr = setError(VBOX_E_IPRT_ERROR, 3323 tr("Handling renaming guest files not supported by installed Guest Additions")); 3324 break; 3325 3326 case VERR_GSTCTL_GUEST_ERROR: 3327 /** @todo Proper guestRc to text translation needed. */ 3328 hr = setError(VBOX_E_IPRT_ERROR, 3329 tr("Renaming guest file failed: %Rrc"), guestRc); 3330 break; 3331 3332 default: 3333 hr = setError(VBOX_E_IPRT_ERROR, tr("Renaming guest file \"%s\" failed: %Rrc"), 3334 Utf8Str(aSource).c_str(), vrc); 3335 break; 3336 } 3337 } 3338 3339 return hr; 2936 3340 #endif /* VBOX_WITH_GUEST_CONTROL */ 2937 3341 } -
trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp
r47905 r49349 627 627 { 628 628 GuestProcessStartupInfo procInfo; 629 procInfo.mName = Utf8StrFmt(GuestSession::tr("Copying file \"%s\" from guest to the host to \"%s\" (%RI64 bytes)"),630 mSource.c_str(), mDest.c_str(), objData.mObjectSize);629 procInfo.mName = Utf8StrFmt(GuestSession::tr("Copying file \"%s\" from guest to the host to \"%s\" (%RI64 bytes)"), 630 mSource.c_str(), mDest.c_str(), objData.mObjectSize); 631 631 procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_CAT); 632 632 procInfo.mFlags = ProcessCreateFlag_Hidden | ProcessCreateFlag_WaitForStdOut;
Note:
See TracChangeset
for help on using the changeset viewer.