Changeset 38290 in vbox
- Timestamp:
- Aug 3, 2011 9:22:12 AM (13 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 2 added
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/VBoxGINA/Helper.cpp
r36447 r38290 17 17 18 18 #include <windows.h> 19 #ifndef TARGET_NT4 20 # include <Wtsapi32.h> 21 #endif 19 22 #include "winwlx.h" 20 23 #include "Helper.h" … … 59 62 bool isRemoteSession(void) 60 63 { 61 return (0 != GetSystemMetrics(SM_REMOTESESSION)) ? true : false; 64 bool fIsRemote = false; 65 66 #if 0 67 #ifndef TARGET_NT4 68 WTS_SESSION_INFO *pSessionInfo = NULL; 69 DWORD dwSessions; 70 if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 71 0 /* Reserved */, 72 1 /* Version */, 73 &pSessionInfo, 74 &dwSessions)) 75 { 76 DWORD dwRemoteSessions = 0; 77 for (DWORD i = 0; i < dwSessions; i++) 78 { 79 switch (pSessionInfo[i].State) 80 { 81 case WTSConnected: 82 case WTSActive: 83 { 84 LPTSTR pBuffer; 85 DWORD cbBuffer; 86 if ( WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, 87 pSessionInfo[i].SessionId, 88 WTSClientProtocolType, 89 &pBuffer, &cbBuffer) 90 && pBuffer 91 && cbBuffer) 92 { 93 USHORT uProto = (USHORT)(pBuffer); 94 /* Only count RDP sessions -- these are the ones we're 95 * interested in here. */ 96 if (uProto == WTS_PROTOCOL_TYPE_RDP) 97 dwRemoteSessions++; 98 WTSFreeMemory(pBuffer); 99 #ifndef DEBUG 100 if (dwRemoteSessions) /* Bail out as soon as possible. */ 101 break; 102 #endif 103 } 104 break; 105 } 106 107 default: 108 break; 109 } 110 } 111 112 #ifdef DEBUG 113 Log(("VBoxGINA: %s connections detected\n", 114 dwRemoteSessions ? "RDP" : "No RDP")); 115 #endif 116 if (pSessionInfo) 117 WTSFreeMemory(pSessionInfo); 118 119 if (dwSessions) 120 fIsRemote = true; 121 } 122 #endif 123 #else 124 LPTSTR pBuffer; 125 DWORD cbBuffer; 126 if ( WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, 127 WTS_CURRENT_SESSION, 128 WTSClientProtocolType, 129 &pBuffer, &cbBuffer) 130 && pBuffer 131 && cbBuffer) 132 { 133 USHORT uProto = (USHORT)(pBuffer); 134 /* Only count RDP sessions -- these are the ones we're 135 * interested in here. */ 136 fIsRemote = uProto == WTS_PROTOCOL_TYPE_RDP; 137 WTSFreeMemory(pBuffer); 138 } 139 else 140 Log(("VBoxGINA: Error %ld querying session information\n", 141 GetLastError())); 142 #endif 143 144 #ifdef DEBUG 145 Log(("VBoxGINA: Is remote session: %s\n", 146 fIsRemote ? "Yes" : "No")); 147 #endif 148 return fIsRemote; 62 149 } 63 150 -
trunk/src/VBox/Additions/WINNT/VBoxGINA/Makefile.kmk
r28800 r38290 31 31 $(VBOX_LIB_IPRT_GUEST_R3) \ 32 32 $(VBOX_LIB_VBGL_R3) 33 ifndef TARGET_NT4 34 VBoxGINA_LIBS += \ 35 WtsApi32.lib 36 endif 33 37 34 38 include $(KBUILD_PATH)/subfooter.kmk -
trunk/src/VBox/Additions/WINNT/VBoxGINA/VBoxGINA.cpp
r37638 r38290 107 107 HINSTANCE hDll; 108 108 109 #ifdef DEBUG 110 /* enable full log output*/111 RTLogGroupSettings(RTLog DefaultInstance(), "all=~0");109 #ifdef DEBUG_andy 110 /* Enable full log output. */ 111 RTLogGroupSettings(RTLogRelDefaultInstance(), "+default.e.l.f.l2.l3"); 112 112 #endif 113 113 -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
r38235 r38290 1204 1204 rc = RTPathAppend(szCurDir, sizeof(szCurDir), pszSubDir); 1205 1205 1206 if (RT_FAILURE(rc)) 1207 return rc; 1208 1206 1209 /* Flag indicating whether the current directory was created on the 1207 1210 * target or not. */ -
trunk/src/VBox/Main/Makefile.kmk
r38235 r38290 677 677 ifdef VBOX_WITH_GUEST_CONTROL 678 678 VBoxC_SOURCES += \ 679 src-client/GuestCtrlImplTasks.cpp 679 src-client/GuestCtrlImplTasks.cpp \ 680 src-client/GuestDirEntryImpl.cpp 680 681 endif 681 682 -
trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h
r38269 r38290 37 37 38 38 /** Structure representing the "value" side of a "key=value" pair. */ 39 typedef struct VBOXGUESTCTRL_STREAM _PAIR39 typedef struct VBOXGUESTCTRL_STREAMPAIR 40 40 { 41 41 char *pszValue; 42 } VBOXGUESTCTRL_STREAM _PAIR, *PVBOXGUESTCTRL_STREAM_PAIR;42 } VBOXGUESTCTRL_STREAMPAIR, *PVBOXGUESTCTRL_STREAM_PAIR; 43 43 44 44 /** Map containing "key=value" pairs of a guest process stream. */ 45 typedef std::map< Utf8Str, VBOXGUESTCTRL_STREAM _PAIR > GuestCtrlStreamPairs;46 typedef std::map< Utf8Str, VBOXGUESTCTRL_STREAM _PAIR >::iterator GuestCtrlStreamPairsIter;47 typedef std::map< Utf8Str, VBOXGUESTCTRL_STREAM _PAIR >::const_iterator GuestCtrlStreamPairsIterConst;45 typedef std::map< Utf8Str, VBOXGUESTCTRL_STREAMPAIR > GuestCtrlStreamPairs; 46 typedef std::map< Utf8Str, VBOXGUESTCTRL_STREAMPAIR >::iterator GuestCtrlStreamPairsIter; 47 typedef std::map< Utf8Str, VBOXGUESTCTRL_STREAMPAIR >::const_iterator GuestCtrlStreamPairsIterConst; 48 48 49 49 /** … … 90 90 /** 91 91 * Class for parsing machine-readable guest process output by VBoxService' 92 * toolbox commands ("vbox_ls", "vbox_stat" etc) .92 * toolbox commands ("vbox_ls", "vbox_stat" etc), aka "guest stream". 93 93 */ 94 94 class GuestProcessStream -
trunk/src/VBox/Main/include/GuestImpl.h
r38269 r38290 141 141 IN_BSTR aUsername, IN_BSTR aPassword, 142 142 IProgress **aProgress, ULONG *aPID); 143 HRESULT executeCollectOutput(ULONG aPID, GuestCtrlStreamObjects &streamObjects);144 143 HRESULT executeProcessInternal(IN_BSTR aCommand, ULONG aFlags, 145 144 ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment), 146 145 IN_BSTR aUsername, IN_BSTR aPassword, 147 146 ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress, int *pRC); 147 HRESULT executeProcessResult(const char *pszCommand, const char *pszUser, ULONG ulTimeout, PCALLBACKDATAEXECSTATUS pExecStatus, ULONG *puPID); 148 HRESULT executeStreamCollectBlock(ULONG aPID, 149 GuestProcessStream &stream, GuestProcessStreamBlock &streamBlock); 150 HRESULT executeStreamCollectOutput(ULONG aPID, GuestCtrlStreamObjects &streamObjects); 151 HRESULT executeWaitForStatusChange(ULONG uPID, ULONG uTimeoutMS, ExecuteProcessStatus_T *pRetStatus, ULONG *puRetExitCode); 148 152 HRESULT fileExistsInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists, int *pRC); 149 153 HRESULT fileQuerySizeInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, LONG64 *aSize, int *pRC); … … 215 219 typedef struct VBOXGUESTCTRL_DIRECTORY 216 220 { 217 char *mpszDirectory;218 char *mpszFilter;219 ULONG mFlags;221 char *mpszDirectory; 222 char *mpszFilter; 223 ULONG mFlags; 220 224 /** Associated PID of started vbox_ls tool. */ 221 uint32_t mPID; 222 /** Offset within the current retrieved stdout buffer. */ 223 uint64_t mOffset; 225 uint32_t mPID; 226 GuestProcessStream mStream; 227 #if 0 228 /** Next enetry in our stream objects vector 229 * to process. */ 230 uint32_t mNextEntry; 231 /** The guest stream object containing all */ 232 GuestCtrlStreamObjects mStream; 233 #endif 224 234 } VBOXGUESTCTRL_DIRECTORY, *PVBOXGUESTCTRL_DIRECTORY; 225 235 typedef std::map< uint32_t, VBOXGUESTCTRL_DIRECTORY > GuestDirectoryMap; … … 230 240 void directoryDestroyHandle(uint32_t uHandle); 231 241 uint32_t directoryGetPID(uint32_t uHandle); 242 int directoryGetNextEntry(uint32_t uHandle, GuestProcessStreamBlock &streamBlock); 232 243 bool directoryHandleExists(uint32_t uHandle); 233 244 … … 240 251 HRESULT handleErrorCompletion(int rc); 241 252 HRESULT handleErrorHGCM(int rc); 242 243 HRESULT waitForProcessStatusChange(ULONG uPID, ExecuteProcessStatus_T *pRetStatus, ULONG *puRetExitCode, ULONG uTimeoutMS);244 HRESULT executeProcessResult(const char *pszCommand, const char *pszUser, ULONG ulTimeout, PCALLBACKDATAEXECSTATUS pExecStatus, ULONG *puPID);245 253 # endif 246 254 -
trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp
r38270 r38290 972 972 return hRC; 973 973 } 974 975 HRESULT Guest::waitForProcessStatusChange(ULONG uPID, ExecuteProcessStatus_T *pRetStatus, ULONG *puRetExitCode, ULONG uTimeoutMS) 976 { 977 AssertPtr(pRetStatus); 978 AssertPtr(puRetExitCode); 979 980 if (uTimeoutMS == 0) 981 uTimeoutMS = UINT32_MAX; 982 983 uint64_t u64StartMS = RTTimeMilliTS(); 984 985 HRESULT hRC; 986 ULONG uRetFlagsIgnored; 987 do 988 { 989 /* 990 * Do some busy waiting within the specified time period (if any). 991 */ 992 if ( uTimeoutMS != UINT32_MAX 993 && RTTimeMilliTS() - u64StartMS > uTimeoutMS) 994 { 995 hRC = setError(VBOX_E_IPRT_ERROR, 996 tr("The process (PID %u) did not change its status within time (%ums)"), 997 uPID, uTimeoutMS); 998 break; 999 } 1000 hRC = GetProcessStatus(uPID, puRetExitCode, &uRetFlagsIgnored, pRetStatus); 1001 if (FAILED(hRC)) 1002 break; 1003 RTThreadSleep(100); 1004 } while(*pRetStatus == ExecuteProcessStatus_Started && SUCCEEDED(hRC)); 1005 return hRC; 974 #endif /* VBOX_WITH_GUEST_CONTROL */ 975 976 STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags, 977 ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment), 978 IN_BSTR aUsername, IN_BSTR aPassword, 979 ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress) 980 { 981 /** @todo r=bird: Eventually we should clean up all the timeout parameters 982 * in the API and have the same way of specifying infinite waits! */ 983 #ifndef VBOX_WITH_GUEST_CONTROL 984 ReturnComNotImplemented(); 985 #else /* VBOX_WITH_GUEST_CONTROL */ 986 using namespace guestControl; 987 988 CheckComArgStrNotEmptyOrNull(aCommand); 989 CheckComArgOutPointerValid(aPID); 990 CheckComArgOutPointerValid(aProgress); 991 992 /* Do not allow anonymous executions (with system rights). */ 993 if (RT_UNLIKELY((aUsername) == NULL || *(aUsername) == '\0')) 994 return setError(E_INVALIDARG, tr("No user name specified")); 995 996 LogRel(("Executing guest process \"%s\" as user \"%s\" ...\n", 997 Utf8Str(aCommand).c_str(), Utf8Str(aUsername).c_str())); 998 999 return executeProcessInternal(aCommand, aFlags, ComSafeArrayInArg(aArguments), 1000 ComSafeArrayInArg(aEnvironment), 1001 aUsername, aPassword, aTimeoutMS, aPID, aProgress, NULL /* rc */); 1002 #endif 1003 } 1004 1005 #ifdef VBOX_WITH_GUEST_CONTROL 1006 /** 1007 * Executes and waits for an internal tool (that is, a tool which is integrated into 1008 * VBoxService, beginning with "vbox_" (e.g. "vbox_ls")) to finish its operation. 1009 * 1010 * @return HRESULT 1011 * @param aTool Name of tool to execute. 1012 * @param aDescription Friendly description of the operation. 1013 * @param aFlags Execution flags. 1014 * @param aUsername Username to execute tool under. 1015 * @param aPassword The user's password. 1016 * @param aProgress Pointer which receives the tool's progress object. Optional. 1017 * @param aPID Pointer which receives the tool's PID. Optional. 1018 */ 1019 HRESULT Guest::executeAndWaitForTool(IN_BSTR aTool, IN_BSTR aDescription, 1020 ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment), 1021 IN_BSTR aUsername, IN_BSTR aPassword, 1022 IProgress **aProgress, ULONG *aPID) 1023 { 1024 ComPtr<IProgress> progressTool; 1025 ULONG uPID; 1026 1027 HRESULT rc = this->ExecuteProcess(aTool, 1028 ExecuteProcessFlag_Hidden, 1029 ComSafeArrayInArg(aArguments), 1030 ComSafeArrayInArg(aEnvironment), 1031 aUsername, aPassword, 1032 5 * 1000 /* Wait 5s for getting the process started. */, 1033 &uPID, progressTool.asOutParam()); 1034 if (SUCCEEDED(rc)) 1035 { 1036 /* Wait for process to exit ... */ 1037 rc = progressTool->WaitForCompletion(-1); 1038 if (FAILED(rc)) return rc; 1039 1040 BOOL fCompleted = FALSE; 1041 BOOL fCanceled = FALSE; 1042 progressTool->COMGETTER(Completed)(&fCompleted); 1043 if (!fCompleted) 1044 progressTool->COMGETTER(Canceled)(&fCanceled); 1045 1046 if (fCompleted) 1047 { 1048 ExecuteProcessStatus_T retStatus; 1049 ULONG uRetExitCode, uRetFlags; 1050 if (SUCCEEDED(rc)) 1051 { 1052 rc = GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus); 1053 if (SUCCEEDED(rc)) 1054 { 1055 if (!uRetExitCode) 1056 { 1057 rc = setError(VBOX_E_IPRT_ERROR, 1058 tr("Error %u occurred while %s"), 1059 uRetExitCode, Utf8Str(aDescription).c_str()); 1060 } 1061 else 1062 { 1063 if (aProgress) 1064 { 1065 /* Return the progress to the caller. */ 1066 progressTool.queryInterfaceTo(aProgress); 1067 } 1068 if (aPID) 1069 *aPID = uPID; 1070 } 1071 } 1072 } 1073 } 1074 else if (fCanceled) 1075 { 1076 rc = setError(VBOX_E_IPRT_ERROR, 1077 tr("%s was aborted"), aDescription); 1078 } 1079 else 1080 AssertReleaseMsgFailed(("Operation \"%s\" neither completed nor canceled!?\n", 1081 Utf8Str(aDescription).c_str())); 1082 } 1083 1084 return rc; 1006 1085 } 1007 1086 … … 1090 1169 return rc; 1091 1170 } 1092 #endif /* VBOX_WITH_GUEST_CONTROL */ 1093 1094 STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags, 1095 ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment), 1096 IN_BSTR aUsername, IN_BSTR aPassword, 1097 ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress) 1098 { 1099 /** @todo r=bird: Eventually we should clean up all the timeout parameters 1100 * in the API and have the same way of specifying infinite waits! */ 1101 #ifndef VBOX_WITH_GUEST_CONTROL 1102 ReturnComNotImplemented(); 1103 #else /* VBOX_WITH_GUEST_CONTROL */ 1104 using namespace guestControl; 1105 1106 CheckComArgStrNotEmptyOrNull(aCommand); 1107 CheckComArgOutPointerValid(aPID); 1108 CheckComArgOutPointerValid(aProgress); 1109 1110 /* Do not allow anonymous executions (with system rights). */ 1111 if (RT_UNLIKELY((aUsername) == NULL || *(aUsername) == '\0')) 1112 return setError(E_INVALIDARG, tr("No user name specified")); 1113 1114 LogRel(("Executing guest process \"%s\" as user \"%s\" ...\n", 1115 Utf8Str(aCommand).c_str(), Utf8Str(aUsername).c_str())); 1116 1117 return executeProcessInternal(aCommand, aFlags, ComSafeArrayInArg(aArguments), 1118 ComSafeArrayInArg(aEnvironment), 1119 aUsername, aPassword, aTimeoutMS, aPID, aProgress, NULL /* rc */); 1120 #endif 1121 } 1122 1123 #ifdef VBOX_WITH_GUEST_CONTROL 1171 1124 1172 /** 1125 * Executes and waits for an internal tool (that is, a tool which is integrated into 1126 * VBoxService, beginning with "vbox_" (e.g. "vbox_ls")) to finish its operation. 1173 * Gets the next stream block from a formerly processed guest stream. Will return 1174 * E_PENDING if not enough guest stream data was read yet, otherwise S_OK or an appropriate 1175 * error. 1127 1176 * 1128 1177 * @return HRESULT 1129 * @param aTool Name of tool to execute. 1130 * @param aDescription Friendly description of the operation. 1131 * @param aFlags Execution flags. 1132 * @param aUsername Username to execute tool under. 1133 * @param aPassword The user's password. 1134 * @param aProgress Pointer which receives the tool's progress object. Optional. 1135 * @param aPID Pointer which receives the tool's PID. Optional. 1178 * @param aPID PID of process to get the next stream block from. 1179 * @param stream Reference to an already filled guest process stream. 1180 * @param streamBlock Reference to a stream block which receives the parsed data. 1136 1181 */ 1137 HRESULT Guest::executeAndWaitForTool(IN_BSTR aTool, IN_BSTR aDescription, 1138 ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment), 1139 IN_BSTR aUsername, IN_BSTR aPassword, 1140 IProgress **aProgress, ULONG *aPID) 1141 { 1142 ComPtr<IProgress> progressTool; 1143 ULONG uPID; 1144 1145 HRESULT rc = this->ExecuteProcess(aTool, 1146 ExecuteProcessFlag_Hidden, 1147 ComSafeArrayInArg(aArguments), 1148 ComSafeArrayInArg(aEnvironment), 1149 aUsername, aPassword, 1150 5 * 1000 /* Wait 5s for getting the process started. */, 1151 &uPID, progressTool.asOutParam()); 1152 if (SUCCEEDED(rc)) 1153 { 1154 /* Wait for process to exit ... */ 1155 rc = progressTool->WaitForCompletion(-1); 1156 if (FAILED(rc)) return rc; 1157 1158 BOOL fCompleted = FALSE; 1159 BOOL fCanceled = FALSE; 1160 progressTool->COMGETTER(Completed)(&fCompleted); 1161 if (!fCompleted) 1162 progressTool->COMGETTER(Canceled)(&fCanceled); 1163 1164 if (fCompleted) 1165 { 1166 ExecuteProcessStatus_T retStatus; 1167 ULONG uRetExitCode, uRetFlags; 1168 if (SUCCEEDED(rc)) 1169 { 1170 rc = GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus); 1171 if (SUCCEEDED(rc)) 1172 { 1173 if (!uRetExitCode) 1174 { 1175 rc = setError(VBOX_E_IPRT_ERROR, 1176 tr("Error %u occurred while %s"), 1177 uRetExitCode, Utf8Str(aDescription).c_str()); 1178 } 1179 else 1180 { 1181 if (aProgress) 1182 { 1183 /* Return the progress to the caller. */ 1184 progressTool.queryInterfaceTo(aProgress); 1185 } 1186 if (aPID) 1187 *aPID = uPID; 1188 } 1189 } 1190 } 1191 } 1192 else if (fCanceled) 1193 { 1194 rc = setError(VBOX_E_IPRT_ERROR, 1195 tr("%s was aborted"), aDescription); 1196 } 1197 else 1198 AssertReleaseMsgFailed(("Operation \"%s\" neither completed nor canceled!?\n", 1199 Utf8Str(aDescription).c_str())); 1200 } 1201 1202 return rc; 1203 } 1204 1205 HRESULT Guest::executeCollectOutput(ULONG aPID, GuestCtrlStreamObjects &streamObjects) 1206 { 1182 HRESULT Guest::executeStreamCollectBlock(ULONG aPID, 1183 GuestProcessStream &stream, GuestProcessStreamBlock &streamBlock) 1184 { 1185 HRESULT rc = S_OK; 1186 1207 1187 SafeArray<BYTE> aOutputData; 1208 1188 ULONG cbOutputData = 0; 1209 1210 int rc = S_OK; 1211 GuestProcessStream guestStream; 1212 1189 int vrc = VINF_SUCCESS; 1213 1190 for (;;) 1214 1191 { … … 1219 1196 && aOutputData.size()) 1220 1197 { 1198 int vrc = stream.AddData(aOutputData.raw(), aOutputData.size()); 1199 if (RT_UNLIKELY(RT_FAILURE(vrc))) 1200 { 1201 rc = setError(VBOX_E_IPRT_ERROR, 1202 tr("Error while adding guest output to stream buffer (%Rrc)"), vrc); 1203 break; 1204 } 1205 else 1206 { 1207 /* Try to parse the stream output we gathered until now. If we still need more 1208 * data the parsing routine will tell us and we just do another poll round. */ 1209 vrc = stream.ParseBlock(streamBlock); 1210 if (RT_SUCCESS(vrc)) 1211 { 1212 /* Yay, we're done! */ 1213 break; 1214 } 1215 else if (vrc == VERR_MORE_DATA) 1216 { 1217 /* We need another poll round. */ 1218 continue; 1219 } 1220 else 1221 rc = setError(VBOX_E_IPRT_ERROR, 1222 tr("Error while parsing guest output (%Rrc)"), vrc); 1223 } 1224 } 1225 else /* No more output! */ 1226 { 1227 if (vrc == VERR_MORE_DATA) 1228 rc = E_PENDING; /** @todo Find a better rc! */ 1229 break; 1230 } 1231 } 1232 1233 return rc; 1234 } 1235 1236 /** 1237 * Gets output from a formerly started guest process, tries to parse all of its guest 1238 * stream (as long as data is available) and returns a stream object which can contain 1239 * multiple stream blocks (which in turn then can contain key=value pairs). 1240 * 1241 * @return HRESULT 1242 * @param aPID PID of process to get/parse the output from. 1243 * @param streamObjects Reference to a guest stream object structure for 1244 * storing the parsed data. 1245 */ 1246 HRESULT Guest::executeStreamCollectOutput(ULONG aPID, GuestCtrlStreamObjects &streamObjects) 1247 { 1248 HRESULT rc = S_OK; 1249 1250 SafeArray<BYTE> aOutputData; 1251 ULONG cbOutputData = 0; 1252 GuestProcessStream guestStream; 1253 1254 for (;;) 1255 { 1256 rc = this->GetProcessOutput(aPID, ProcessOutputFlag_None, 1257 10 * 1000 /* Timeout in ms */, 1258 _64K, ComSafeArrayAsOutParam(aOutputData)); 1259 if ( SUCCEEDED(rc) 1260 && aOutputData.size()) 1261 { 1221 1262 int vrc = guestStream.AddData(aOutputData.raw(), aOutputData.size()); 1222 1263 if (RT_UNLIKELY(RT_FAILURE(vrc))) 1264 { 1223 1265 rc = setError(VBOX_E_IPRT_ERROR, 1224 1266 tr("Error while adding guest output to stream buffer (%Rrc)"), vrc); 1267 break; 1268 } 1225 1269 } 1226 1270 else /* No more output! */ … … 1230 1274 if (SUCCEEDED(rc)) 1231 1275 { 1232 GuestProcessStreamBlock curPairs; 1233 int vrc = guestStream.ParseBlock(curPairs); 1234 if ( RT_SUCCESS(vrc) 1235 || vrc == VERR_MORE_DATA) 1236 { 1237 /** @todo Catch exceptions! */ 1238 if (curPairs.GetCount()) 1239 streamObjects.push_back(curPairs); 1240 } 1241 else 1242 rc = setError(VBOX_E_IPRT_ERROR, 1243 tr("Error while parsing guest output (%Rrc)"), vrc); 1276 for (;;) 1277 { 1278 GuestProcessStreamBlock curBlock; 1279 rc = executeStreamCollectBlock(aPID, 1280 guestStream, curBlock); 1281 if (SUCCEEDED(rc)) 1282 1283 { 1284 if (curBlock.GetCount()) 1285 streamObjects.push_back(curBlock); 1286 else 1287 break; /* No more data. */ 1288 } 1289 else 1290 { 1291 rc = setError(VBOX_E_IPRT_ERROR, 1292 tr("Error while parsing guest stream block")); 1293 break; 1294 } 1295 } 1244 1296 } 1245 1297 1246 1298 return rc; 1299 } 1300 1301 /** 1302 * Does busy waiting on a formerly started guest process. 1303 * 1304 * @return HRESULT 1305 * @param uPID PID of guest process to wait for. 1306 * @param uTimeoutMS Waiting timeout (in ms). Specify 0 for an infinite timeout. 1307 * @param pRetStatus Pointer which receives current process status after the change. 1308 * Optional. 1309 * @param puRetExitCode Pointer which receives the final exit code in case of guest process 1310 * termination. Optional. 1311 */ 1312 HRESULT Guest::executeWaitForStatusChange(ULONG uPID, ULONG uTimeoutMS, 1313 ExecuteProcessStatus_T *pRetStatus, ULONG *puRetExitCode) 1314 { 1315 if (uTimeoutMS == 0) 1316 uTimeoutMS = UINT32_MAX; 1317 1318 uint64_t u64StartMS = RTTimeMilliTS(); 1319 1320 HRESULT hRC; 1321 ULONG uExitCode, uRetFlags; 1322 ExecuteProcessStatus_T curStatus; 1323 hRC = GetProcessStatus(uPID, &uExitCode, &uRetFlags, &curStatus); 1324 if (FAILED(hRC)) 1325 return hRC; 1326 1327 do 1328 { 1329 if ( uTimeoutMS != UINT32_MAX 1330 && RTTimeMilliTS() - u64StartMS > uTimeoutMS) 1331 { 1332 hRC = setError(VBOX_E_IPRT_ERROR, 1333 tr("The process (PID %u) did not change its status within time (%ums)"), 1334 uPID, uTimeoutMS); 1335 break; 1336 } 1337 hRC = GetProcessStatus(uPID, &uExitCode, &uRetFlags, &curStatus); 1338 if (FAILED(hRC)) 1339 break; 1340 RTThreadSleep(100); 1341 } while(*pRetStatus == curStatus); 1342 1343 if (SUCCEEDED(hRC)) 1344 { 1345 if (pRetStatus) 1346 *pRetStatus = curStatus; 1347 if (puRetExitCode) 1348 *puRetExitCode = uExitCode; 1349 } 1350 return hRC; 1247 1351 } 1248 1352 -
trunk/src/VBox/Main/src-client/GuestCtrlImplDir.cpp
r38269 r38290 18 18 #include "GuestImpl.h" 19 19 #include "GuestCtrlImplPrivate.h" 20 #include "GuestDirEntryImpl.h" 20 21 21 22 #include "Global.h" … … 210 211 RTStrFree(it->second.mpszFilter); 211 212 213 /* Destroy raw guest stream buffer - not used 214 * anymore. */ 215 it->second.mStream.Destroy(); 216 212 217 /* Remove callback context (not used anymore). */ 213 218 mGuestDirectoryMap.erase(it); … … 230 235 231 236 return 0; 237 } 238 239 int Guest::directoryGetNextEntry(uint32_t uHandle, GuestProcessStreamBlock &streamBlock) 240 { 241 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 242 243 GuestDirectoryMapIter it = mGuestDirectoryMap.find(uHandle); 244 if (it != mGuestDirectoryMap.end()) 245 { 246 HRESULT hr = executeStreamCollectBlock(it->second.mPID, 247 it->second.mStream, streamBlock); 248 if (FAILED(hr)) 249 return VERR_INVALID_PARAMETER; /** @todo Find better rc! */ 250 251 return VINF_SUCCESS; 252 } 253 254 return VERR_NOT_FOUND; 232 255 } 233 256 … … 363 386 using namespace guestControl; 364 387 365 uint32_t uPID = directoryGetPID(aHandle); 366 if (uPID) 367 { 368 SafeArray<BYTE> aOutputData; 369 ULONG cbOutputData = 0; 370 371 HRESULT rc = this->GetProcessOutput(uPID, ProcessOutputFlag_None, 372 30 * 1000 /* Timeout in ms */, 373 _64K, ComSafeArrayAsOutParam(aOutputData)); 374 if (SUCCEEDED(rc)) 388 CheckComArgOutPointerValid(aDirEntry); 389 390 AutoCaller autoCaller(this); 391 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 392 393 HRESULT rc = S_OK; 394 try 395 { 396 GuestProcessStreamBlock streamBlock; 397 int vrc = directoryGetNextEntry(aHandle, streamBlock); 398 if (RT_SUCCESS(vrc)) 375 399 { 376 400 ComObjPtr <GuestDirEntry> pDirEntry; 401 rc = pDirEntry.createObject(); 402 ComAssertComRC(rc); 403 404 rc = pDirEntry->init(this, streamBlock); 405 if (SUCCEEDED(rc)) 406 { 407 pDirEntry.queryInterfaceTo(aDirEntry); 408 } 409 else 410 rc = setError(VBOX_E_IPRT_ERROR, 411 Guest::tr("Unable to init guest directory entry")); 377 412 } 378 379 return rc; 380 } 381 382 return setError(VBOX_E_IPRT_ERROR, 383 Guest::tr("Directory handle is invalid")); 413 else 414 rc = setError(VBOX_E_IPRT_ERROR, 415 Guest::tr("Directory handle is invalid")); 416 } 417 catch (std::bad_alloc &) 418 { 419 rc = E_OUTOFMEMORY; 420 } 421 return rc; 384 422 #endif 385 423 } -
trunk/src/VBox/Main/src-client/GuestCtrlImplFile.cpp
r38269 r38290 167 167 { 168 168 GuestCtrlStreamObjects streamObjs; 169 rc = execute CollectOutput(uPID, streamObjs);169 rc = executeStreamCollectOutput(uPID, streamObjs); 170 170 if (SUCCEEDED(rc)) 171 171 { -
trunk/src/VBox/Main/src-client/GuestCtrlImplTasks.cpp
r38237 r38290 356 356 ExecuteProcessStatus_T retStatus; 357 357 ULONG uRetExitCode; 358 rc = pGuest->waitForProcessStatusChange(uPID, &retStatus, &uRetExitCode, 10 * 1000 /* 10s timeout. */); 358 rc = pGuest->executeWaitForStatusChange(uPID, 10 * 1000 /* 10s timeout. */, 359 &retStatus, &uRetExitCode); 359 360 if (FAILED(rc)) 360 361 {
Note:
See TracChangeset
for help on using the changeset viewer.