Changeset 22744 in vbox
- Timestamp:
- Sep 3, 2009 1:09:02 PM (15 years ago)
- Location:
- trunk/src/VBox/Additions/common/VBoxService
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/Makefile.kmk
r22728 r22744 40 40 VBoxService_DEFS += VBOX_WITH_GUEST_PROPS VBOXSERVICE_VMINFO 41 41 if1of ($(KBUILD_TARGET), win) 42 VBoxService_DEFS += VBOX_WITH_HGCM VBOXSERVICE_ VMEXEC42 VBoxService_DEFS += VBOX_WITH_HGCM VBOXSERVICE_EXEC 43 43 endif 44 44 endif -
trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp
r22530 r22744 83 83 #endif 84 84 #ifdef VBOXSERVICE_VMINFO 85 { &g_VMInfo, NIL_RTTHREAD, false, false, false, true },86 #endif 87 #ifdef VBOXSERVICE_ VMEXEC88 { &g_ VMExec,NIL_RTTHREAD, false, false, false, true },85 { &g_VMInfo, NIL_RTTHREAD, false, false, false, true }, 86 #endif 87 #ifdef VBOXSERVICE_EXEC 88 { &g_Exec, NIL_RTTHREAD, false, false, false, true }, 89 89 #endif 90 90 }; -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceExec.cpp
r22733 r22744 1 1 /* $Id$ */ 2 2 /** @file 3 * VBoxServiceExec - In-VM Command Execution Service. 4 */ 5 /** @todo r=bird: Why is this called VMExec while the filename is VBoxServiceExec.cpp? See VMInfo... */ 6 /** @todo r=bird: Use svn-ps.[sh|cmd] -a when adding new files, please. Then the EOLs and $Id$ won't be messed up all the time. */ 3 * VBoxServiceExec - Host-driven Command Execution. 4 */ 7 5 8 6 /* … … 27 25 *******************************************************************************/ 28 26 #include <iprt/assert.h> 27 #include <iprt/ctype.h> 29 28 #include <iprt/env.h> 30 29 #include <iprt/file.h> 31 30 #include <iprt/mem.h> 31 #include <iprt/path.h> 32 #include <iprt/param.h> 32 33 #include <iprt/process.h> 33 34 #include <iprt/string.h> … … 38 39 #include "VBoxServiceInternal.h" 39 40 #include "VBoxServiceUtils.h" 40 #ifdef VBOX_WITH_GUEST_PROPS41 # include <VBox/HostServices/GuestPropertySvc.h>42 #endif43 41 44 42 … … 47 45 *******************************************************************************/ 48 46 /** The vminfo interval (millseconds). */ 49 uint32_t g_VMExecInterval = 0;47 static uint32_t g_cMsExecInterval = 0; 50 48 /** The semaphore we're blocking on. */ 51 static RTSEMEVENTMULTI g_ VMExecEvent = NIL_RTSEMEVENTMULTI;49 static RTSEMEVENTMULTI g_hExecEvent = NIL_RTSEMEVENTMULTI; 52 50 /** The guest property service client ID. */ 53 static uint32_t g_VMExecGuestPropSvcClientID = 0; 54 /** The maximum of arguments a command can have. */ 55 #define EXEC_MAX_ARGS 32 51 static uint32_t g_uExecGuestPropSvcClientID = 0; 52 56 53 57 54 /** @copydoc VBOXSERVICE::pfnPreInit */ … … 68 65 if (ppszShort) 69 66 /* no short options */; 70 else if (!strcmp(argv[*pi], "-- vmexec-interval"))71 rc = VBoxServiceArgUInt32(argc, argv, "", pi, &g_ VMExecInterval, 1, UINT32_MAX - 1);67 else if (!strcmp(argv[*pi], "--exec-interval")) 68 rc = VBoxServiceArgUInt32(argc, argv, "", pi, &g_cMsExecInterval, 1, UINT32_MAX - 1); 72 69 return rc; 73 70 } … … 81 78 * Then create the event sem to block on. 82 79 */ 83 if (!g_ VMExecInterval)84 g_ VMExecInterval = g_DefaultInterval * 1000;85 if (!g_ VMExecInterval)86 g_ VMExecInterval = 10 * 1000;87 88 int rc = RTSemEventMultiCreate(&g_ VMExecEvent);80 if (!g_cMsExecInterval) 81 g_cMsExecInterval = g_DefaultInterval * 1000; 82 if (!g_cMsExecInterval) 83 g_cMsExecInterval = 10 * 1000; 84 85 int rc = RTSemEventMultiCreate(&g_hExecEvent); 89 86 AssertRCReturn(rc, rc); 90 87 91 rc = VbglR3GuestPropConnect(&g_ VMExecGuestPropSvcClientID);88 rc = VbglR3GuestPropConnect(&g_uExecGuestPropSvcClientID); 92 89 if (RT_SUCCESS(rc)) 93 VBoxServiceVerbose(3, " Property Service Client ID: %#x\n", g_VMExecGuestPropSvcClientID);90 VBoxServiceVerbose(3, "Exec: Property Service Client ID: %#x\n", g_uExecGuestPropSvcClientID); 94 91 else 95 92 { 96 VBoxServiceError(" Failed to connect to the guest property service! Error: %Rrc\n", rc);97 RTSemEventMultiDestroy(g_ VMExecEvent);98 g_ VMExecEvent = NIL_RTSEMEVENTMULTI;93 VBoxServiceError("Exec: Failed to connect to the guest property service! Error: %Rrc\n", rc); 94 RTSemEventMultiDestroy(g_hExecEvent); 95 g_hExecEvent = NIL_RTSEMEVENTMULTI; 99 96 } 100 97 … … 106 103 * Validates flags for executable guest properties. 107 104 * 108 * @returns boolean. 109 * @retval true on success. 110 * @retval false if not valid. 105 * @returns VBox status code. Success means they are valid. 111 106 * 112 107 * @param pszFlags Pointer to flags to be checked. 113 108 */ 114 bool VBoxServiceExecValidateFlags(char* pszFlags) 115 { 116 bool ret = false; 117 118 if ( (NULL != RTStrStr(pszFlags, "TRANSIENT")) 119 && (NULL != RTStrStr(pszFlags, "RDONLYGUEST"))) 109 static int VBoxServiceExecValidateFlags(const char *pszFlags) 110 { 111 if (!pszFlags) 112 return VERR_ACCESS_DENIED; 113 if (!RTStrStr(pszFlags, "TRANSIENT")) 114 return VERR_ACCESS_DENIED; 115 if (!RTStrStr(pszFlags, "RDONLYGUEST")) 116 return VERR_ACCESS_DENIED; 117 return VINF_SUCCESS; 118 } 119 120 121 /** 122 * Reads a host transient property. 123 * 124 * This will validate the flags to make sure it is a transient property that can 125 * only be change by the host. 126 * 127 * @returns VBox status code, fully bitched. 128 * @param pszPropName The property name. 129 * @param ppszValue Where to return the value. This is always set 130 * to NULL. Free it using RTStrFree(). 131 * @param puTimestamp Where to return the timestamp. This is only set 132 * on success. Optional. 133 */ 134 static int VBoxServiceExecReadHostProp(const char *pszPropName, char **ppszValue, uint64_t *puTimestamp) 135 { 136 size_t cbBuf = _1K; 137 void *pvBuf = NULL; 138 int rc; 139 140 *ppszValue = NULL; 141 142 for (unsigned cTries = 0; cTries < 10; cTries++) 120 143 { 121 ret = true; 144 /* 145 * (Re-)Allocate the buffer and try read the property. 146 */ 147 RTMemFree(pvBuf); 148 pvBuf = RTMemAlloc(cbBuf); 149 if (!pvBuf) 150 { 151 VBoxServiceError("Exec: Failed to allocate %zu bytes\n", cbBuf); 152 rc = VERR_NO_MEMORY; 153 break; 154 } 155 char *pszValue; 156 char *pszFlags; 157 uint64_t uTimestamp; 158 rc = VbglR3GuestPropRead(g_uExecGuestPropSvcClientID, pszPropName, 159 pvBuf, cbBuf, 160 &pszValue, &uTimestamp, &pszFlags, NULL); 161 if (RT_FAILURE(rc)) 162 { 163 if (rc == VERR_BUFFER_OVERFLOW) 164 { 165 /* try again with a bigger buffer. */ 166 cbBuf *= 2; 167 continue; 168 } 169 if (rc == VERR_NOT_FOUND) 170 VBoxServiceVerbose(2, "Exec: %s not found\n", pszPropName); 171 else 172 VBoxServiceError("Exec: Failed to query \"%s\": %Rrc\n", pszPropName, rc); 173 break; 174 } 175 176 /* 177 * Validate it and set return values on success. 178 */ 179 rc = VBoxServiceExecValidateFlags(pszFlags); 180 if (RT_FAILURE(rc)) 181 { 182 static uint32_t s_cBitched = 0; 183 if (++s_cBitched < 10) 184 VBoxServiceError("Exec: Flag validation failed for \"%s\": %Rrc; flags=\"%s\"\n", 185 pszPropName, rc, pszFlags); 186 break; 187 } 188 VBoxServiceVerbose(2, "Exec: Read \"%s\" = \"%s\", timestamp %RU64n\n", 189 pszPropName, pszValue, uTimestamp); 190 *ppszValue = RTStrDup(pszValue); 191 if (!*ppszValue) 192 { 193 VBoxServiceError("Exec: RTStrDup failed for \"%s\"\n", pszValue); 194 rc = VERR_NO_MEMORY; 195 break; 196 } 197 198 if (puTimestamp) 199 *puTimestamp = uTimestamp; 200 break; /* done */ 122 201 } 123 VBoxServiceVerbose(3, "Validating flags %s = %s\n", 124 ((pszFlags == NULL) || (RTStrICmp(pszFlags, "") == 0)) ? "<NULL>" : pszFlags, 125 ret ? "true" : "false"); 126 return ret; 202 203 RTMemFree(pvBuf); 204 return rc; 205 } 206 207 208 /** 209 * Frees an argument vector constructed by VBoxServiceExecCreateArgV. 210 * 211 * @param papszArgs The vector to free. 212 */ 213 static void VBoxServiceExecFreeArgV(char **papszArgs) 214 { 215 for (size_t i = 0; papszArgs[i]; i++) 216 { 217 RTStrFree(papszArgs[i]); 218 papszArgs[i] = NULL; 219 } 220 RTMemFree(papszArgs); 221 } 222 223 224 /** 225 * Creates an argument vector out of an executable name and a string containing 226 * the arguments separated by spaces. 227 * 228 * @returns VBox status code. Not bitched. 229 * @param pszExec The executable name. 230 * @param pszArgs The string containging the arguments. 231 * @param ppapszArgs Where to return the argument vector. Not set on 232 * failure. Use VBoxServiceExecFreeArgV to free. 233 * 234 * @todo Quoted strings. Do it unix (bourne shell) fashion. 235 */ 236 static int VBoxServiceExecCreateArgV(const char *pszExec, const char *pszArgs, char ***ppapszArgs) 237 { 238 size_t cAlloc = 1; 239 size_t cUsed = 1; 240 char **papszArgs = (char **)RTMemAlloc(sizeof(char *) * (cAlloc + 1)); 241 if (!papszArgs) 242 return VERR_NO_MEMORY; 243 244 /* 245 * Start by adding the executable name first. 246 * Note! We keep the papszArgs fully terminated at all times to keep cleanup simple. 247 */ 248 int rc = VERR_NO_MEMORY; 249 papszArgs[1] = NULL; 250 papszArgs[0] = RTStrDup(pszExec); 251 if (papszArgs[0]) 252 { 253 /* 254 * Parse the argument string and add any arguments found in it. 255 */ 256 for (;;) 257 { 258 /* skip leading spaces */ 259 char ch; 260 while ((ch = *pszArgs) && RT_C_IS_SPACE(ch)) 261 pszArgs++; 262 if (!*pszArgs) 263 { 264 *ppapszArgs = papszArgs; 265 return VINF_SUCCESS; 266 } 267 268 /* find the of the current word. Quoting is ignored atm. */ 269 char const *pszEnd = pszArgs + 1; 270 while ((ch = *pszEnd) && !RT_C_IS_SPACE(ch)) 271 pszEnd++; 272 273 /* resize the vector. */ 274 if (cUsed == cAlloc) 275 { 276 cAlloc += 10; 277 void *pvNew = RTMemRealloc(papszArgs, sizeof(char *) * (cAlloc + 1)); 278 if (!pvNew) 279 break; 280 papszArgs = (char **)pvNew; 281 for (size_t i = cUsed; i <= cAlloc; i++) 282 papszArgs[i] = NULL; 283 } 284 285 /* add it */ 286 papszArgs[cUsed++] = RTStrDupN(pszArgs, (uintptr_t)pszEnd - (uintptr_t)pszArgs); 287 if (!papszArgs[cUsed++]) 288 break; 289 290 /* advance */ 291 pszArgs = pszEnd; 292 } 293 } 294 295 VBoxServiceExecFreeArgV(papszArgs); 296 return rc; 127 297 } 128 298 … … 131 301 DECLCALLBACK(int) VBoxServiceExecWorker(bool volatile *pfShutdown) 132 302 { 133 using namespace guestProp; 134 int rc = VINF_SUCCESS; 303 int rcRet = VINF_SUCCESS; 135 304 136 305 /* … … 139 308 */ 140 309 RTThreadUserSignal(RTThreadSelf()); 141 Assert(g_ VMExecGuestPropSvcClientID > 0);310 Assert(g_uExecGuestPropSvcClientID > 0); 142 311 143 312 /* 144 313 * Execution loop. 314 * 315 * The thread at the moment does nothing but checking for one specific guest property 316 * for triggering a hard coded sysprep command with parameters given by the host. This 317 * feature was required by the VDI guys. 318 * 319 * Later this thread could become a general host->guest executor.. there are some 320 * sketches for this in the code. 145 321 */ 146 322 #ifdef FULL_FEATURED_EXEC 147 323 uint64_t u64TimestampPrev = UINT64_MAX; 148 324 #endif 149 bool fSysprepDone = false; 325 bool fSysprepDone = false; 326 bool fBitchedAboutMissingSysPrepCmd = false; 150 327 for (;;) 151 328 { 152 /* 153 * The thread at the moment does nothing but checking for one specific guest property 154 * for triggering a hard coded sysprep command with parameters given by the host. This 155 * feature was required by the VDI guys. 156 * 157 * Later this thread could become a general host->guest executor (remote shell?). 158 */ 329 #if 0 /** @todo r=bird: This code needs reviewing and testing before it can be enabled. */ 159 330 if (!fSysprepDone) 160 331 { 161 uint32_t cbBuf = MAX_VALUE_LEN + MAX_FLAGS_LEN + 1024; 162 163 /* Get arguments. */ 164 /** @todo r=bird: How exactly does this work wrt. enabled/disabled? In 165 * ConsoleImpl2.cpp it's now always set to "", which means it will 166 * always be executed. So, if someone adds a bogus 167 * c:\\sysprep\\sysprep.exe to their system and install the latest 168 * additions this will be executed everytime the system starts now - if 169 * I understand the code correctly. Is this intentional? */ 170 void* pvSysprepCmd = RTMemAllocZ(cbBuf); 171 char* pszSysprepCmdValue = NULL; 172 uint64_t u64SysprepCmdTimestamp = 0; 173 char* pszSysprepCmdFlags = NULL; 332 /* 333 * Get the sysprep command and arguments. 334 * 335 * The sysprep executable location is either retrieved from the host 336 * or is in a hard coded location depending on the Windows version. 337 */ 338 char *pszSysprepExec = NULL; 174 339 #ifdef SYSPREP_WITH_CMD 175 /* Get sysprep properties. */ 340 int rc = VBoxServiceExecReadHostProp("/VirtualBox/HostGuest/SysprepExec", &pszSysprepExec, NULL); 341 if (RT_SUCCESS(rc) && !*pszSysprepExec) 342 rc = VERR_NOT_FOUND; 343 #else 344 /* Predefined sys. */ 345 int rc = VINF_SUCCESS; 346 char szSysprepCmd[RTPATH_MAX] = "C:\\sysprep\\sysprep.exe"; 347 OSVERSIONINFOEX OSInfoEx; 348 RT_ZERO(OSInfoEx); 349 OSInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 350 if ( GetVersionEx((LPOSVERSIONINFO) &OSInfoEx) 351 && OSInfoEx.dwPlatformId == VER_PLATFORM_WIN32_NT 352 && OSInfoEx.dwMajorVersion >= 6 /* Vista */) 353 { 354 rc = RTEnvGetEx(RTENV_DEFAULT, "windir", szSysPrepCmd, sizeof(szSysPrepCmd), NULL); 355 if (RT_SUCCESS(rc)) 356 rc = RTPathAppend(szSysPrepCmd, sizeof(szSysPrepCmd), "system32\\sysprep\\sysprep.exe"); 357 } 358 pszSysprepExec = szSysprepCmd; 359 #endif 176 360 if (RT_SUCCESS(rc)) 177 361 { 178 rc = VbglR3GuestPropRead(g_VMExecGuestPropSvcClientID, "/VirtualBox/HostGuest/SysprepCmd", 179 pvSysprepCmd, cbBuf, 180 &pszSysprepCmdValue, &u64SysprepCmdTimestamp, &pszSysprepCmdFlags, NULL); 181 if (RT_FAILURE(rc)) 182 { 183 if (rc == VERR_NOT_FOUND) 184 VBoxServiceVerbose(2, "Sysprep cmd guest property not found\n"); 185 else 186 VBoxServiceError("Sysprep cmd guest property: Error = %Rrc\n", rc); 187 } 188 else 189 { 190 VBoxServiceExecValidateFlags(pszSysprepCmdFlags) ? rc = rc : rc = VERR_ACCESS_DENIED; 191 if (RT_SUCCESS(rc)) 192 { 193 if (RTStrNLen(pszSysprepCmdValue, _MAX_PATH) <= 0) 194 rc = VERR_NOT_FOUND; 195 } 196 VBoxServiceVerbose(2, "Sysprep cmd guest property: %Rrc\n", rc); 197 } 198 } 199 #else 200 /* Choose sysprep image based on OS version. */ 201 char szSysprepCmd[_MAX_PATH] = "c:\\sysprep\\sysprep.exe"; 202 OSVERSIONINFOEX OSInfoEx; 203 memset(&OSInfoEx, '\0', sizeof(OSInfoEx)); 204 OSInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 205 if (GetVersionEx((LPOSVERSIONINFO) &OSInfoEx)) 206 { 207 if (OSInfoEx.dwMajorVersion >= 6) /* Use built-in sysprep on Vista or later. */ 208 RTStrPrintf(szSysprepCmd, sizeof(szSysprepCmd), "%s\\system32\\sysprep\\sysprep.exe", RTEnvGet("windir")); 209 } 210 pszSysprepCmdValue = szSysprepCmd; 211 #endif 212 void* pvSysprepArgs = RTMemAllocZ(cbBuf); 213 char* pszSysprepArgsValue = NULL; 214 uint64_t u64SysprepArgsTimestamp = 0; 215 char* pszSysprepArgsFlags = NULL; 216 217 if (RT_SUCCESS(rc)) 218 { 219 pvSysprepArgs = RTMemAllocZ(cbBuf); 220 char szVal[] = "/VirtualBox/HostGuest/SysprepArgs"; 221 char *pTmp = NULL; 222 rc = RTStrCurrentCPToUtf8(&pTmp, szVal); 223 rc = VbglR3GuestPropRead(g_VMExecGuestPropSvcClientID, pTmp, 224 pvSysprepArgs, cbBuf, 225 &pszSysprepArgsValue, &u64SysprepArgsTimestamp, &pszSysprepArgsFlags, NULL); 226 RTStrFree(pTmp); 227 if (RT_FAILURE(rc)) 228 { 229 if (rc == VERR_NOT_FOUND) 230 VBoxServiceVerbose(2, "Sysprep argument guest property not found\n"); 231 else 232 VBoxServiceError("Sysprep argument guest property: Error = %Rrc\n", rc); 233 } 234 else 235 { 236 VBoxServiceExecValidateFlags(pszSysprepArgsFlags) ? rc = rc : rc = VERR_ACCESS_DENIED; 237 if (RT_SUCCESS(rc)) 238 { 239 if (RTStrNLen(pszSysprepArgsValue, EXEC_MAX_ARGS) <= 0) 240 rc = VERR_NOT_FOUND; 241 } 242 VBoxServiceVerbose(2, "Sysprep argument guest property: %Rrc\n", rc); 243 } 244 } 245 246 if ( RT_SUCCESS(rc) 247 && !RTFileExists(pszSysprepCmdValue)) 248 { 249 VBoxServiceError("Sysprep executable not found! Search path=%s\n", pszSysprepCmdValue); 250 rc = VERR_FILE_NOT_FOUND; 251 } 252 253 if (RT_SUCCESS(rc)) 254 { 255 RTPROCESS pid; 256 257 /* Construct arguments list. */ 258 /** @todo would be handy to have such a function in IPRT. */ 259 int16_t index = 0; 260 char* pszArg = pszSysprepArgsValue; 261 262 const char* pArgs[EXEC_MAX_ARGS]; /* Do we have a #define in IPRT for max args? */ 263 264 VBoxServiceVerbose(3, "Sysprep argument value: %s\n", pszSysprepArgsValue); 265 pArgs[index++] = pszSysprepCmdValue; /* Store image name as first argument. */ 266 while ( (pszArg != NULL) 267 && (*pszArg != NULL)) 268 { 269 char* pCurArg = (char*)RTMemAllocZ(_MAX_PATH); 270 int arg = 0; 271 while ( (*pszArg != ' ') 272 && (*pszArg != NULL)) 273 { 274 pCurArg[arg++] = *pszArg; 275 pszArg++; 276 } 277 pszArg++; /* Skip leading space. */ 278 VBoxServiceVerbose(3, "Sysprep argument %d = %s\n", index, pCurArg); 279 pArgs[index++] = pCurArg; 280 } 281 pArgs[index] = NULL; 282 283 /* Execute ... */ 284 VBoxServiceVerbose(3, "Executing sysprep ...\n"); 285 rc = RTProcCreate(pszSysprepCmdValue, pArgs, RTENV_DEFAULT, 0, &pid); 362 char *pszSysprepArgs; 363 rc = VBoxServiceExecReadHostProp("/VirtualBox/HostGuest/SysprepArgs", &pszSysprepArgs, NULL); 364 if (RT_SUCCESS(rc) && !*pszSysprepArgs) 365 rc = VERR_NOT_FOUND; 286 366 if (RT_SUCCESS(rc)) 287 367 { 288 RTPROCSTATUS Status; 289 rc = RTProcWait(pid, RTPROCWAIT_FLAGS_BLOCK, &Status); 290 291 VBoxServiceVerbose(3, "Sysprep returned: %d\n", Status.iStatus); 292 if (RT_SUCCESS(rc)) 368 if (RTFileExists(pszSysprepExec)) 293 369 { 294 if ( Status.iStatus == 0 295 && Status.enmReason == RTPROCEXITREASON_NORMAL) 370 char **papszArgs; 371 rc = VBoxServiceExecCreateArgV(pszSysprepExec, pszSysprepArgs, &papszArgs); 372 if (RT_SUCCESS(rc)) 296 373 { 297 fSysprepDone = true; /* We're done, no need to repeat the sysprep exec. */ 374 /* 375 * Execute it synchronously and store the result. 376 * 377 * Note that RTProcWait should never fail here and 378 * that (the host is screwed if it does though). 379 */ 380 VBoxServiceVerbose(3, "Exec: Executing sysprep ...\n"); 381 for (size_t i = 0; papszArgs[i]; i++) 382 VBoxServiceVerbose(3, "Exec: sysprep argv[%u]: \"%s\"\n", i, papszArgs[i]); 383 384 RTPROCESS pid; 385 rc = RTProcCreate(pszSysprepExec, papszArgs, RTENV_DEFAULT, 0 /*fFlags*/, &pid); 386 if (RT_SUCCESS(rc)) 387 { 388 RTPROCSTATUS Status; 389 rc = RTProcWait(pid, RTPROCWAIT_FLAGS_BLOCK, &Status); 390 if (RT_SUCCESS(rc)) 391 { 392 VBoxServiceVerbose(1, "Sysprep returned: %d (reason %d)\n", 393 Status.iStatus, Status.enmReason); 394 /** @todo r=bird: Figure out whether you should try re-execute sysprep if it 395 * fails or not. This is not mentioned in the defect. */ 396 fSysprepDone = true; /* paranoia */ 397 398 /* 399 * Store the result in Set return value so the host knows what happend. 400 */ 401 rc = VbglR3GuestPropWriteValueF(g_uExecGuestPropSvcClientID, 402 "/VirtualBox/HostGuest/SysprepRet", 403 "%d", Status.iStatus); 404 if (RT_FAILURE(rc)) 405 VBoxServiceError("Exec: Failed to write SysprepRet: rc=%Rrc\n", rc); 406 } 407 else 408 VBoxServiceError("Exec: RTProcWait failed for sysprep: %Rrc\n", rc); 409 } 410 VBoxServiceExecFreeArgV(papszArgs); 298 411 } 412 else 413 VBoxServiceError("Exec: VBoxServiceExecCreateArgV: %Rrc\n", rc); 299 414 } 300 301 /* Set return value so the host knows what happend. */ 302 rc = VboxServiceWritePropInt(g_VMExecGuestPropSvcClientID, "HostGuest/SysprepRet", Status.iStatus); 303 if (RT_FAILURE(rc)) 304 VBoxServiceError("Failed to write SysprepRet: rc=%Rrc\n", rc); 415 else 416 { 417 if (!fBitchedAboutMissingSysPrepCmd) 418 { 419 VBoxServiceError("Exec: Sysprep executable not found! Search path=%s\n", pszSysprepExec); 420 fBitchedAboutMissingSysPrepCmd = true; 421 } 422 rc = VERR_FILE_NOT_FOUND; 423 } 424 RTStrFree(pszSysprepArgs); 305 425 } 306 307 /* Destroy argument list (all but the first and last arg, it's just a pointer). */ 308 for (int i=1; i<index-1; i++) 309 RTMemFree((void*)pArgs[i]); 426 #ifndef SYSPREP_WITH_CMD 427 RTStrFree(pszSysprepExec); 428 #endif 310 429 } 311 } 430 431 /* 432 * Only continue polling if the guest property value is empty/missing 433 * or if the sysprep command is missing. 434 */ 435 if ( rc != VERR_NOT_FOUND 436 && rc != VERR_FILE_NOT_FOUND) 437 { 438 VBoxServiceVerbose(1, "Exec: Stopping sysprep processing (rc=%Rrc)\n", rc); 439 rc = VbglR3GuestPropWriteValueF(g_uExecGuestPropSvcClientID, "/VirtualBox/HostGuest/SysprepVBoxRC", "%d", rc); 440 if (RT_FAILURE(rc)) 441 VBoxServiceError("Exec: Failed to write SysprepVBoxRC: rc=%Rrc\n", rc); 442 fSysprepDone = true; 443 } 444 } 445 #endif /* temporarily disabled. */ 312 446 313 447 #ifdef FULL_FEATURED_EXEC … … 333 467 Wait for changes to the command value. If that fails for some reason other than timeout / interrupt, fall back on the semaphore. 334 468 #else 335 int rc2 = RTSemEventMultiWait(g_ VMExecEvent, g_VMExecInterval);469 int rc2 = RTSemEventMultiWait(g_hExecEvent, g_cMsExecInterval); 336 470 #endif 337 471 if (*pfShutdown) … … 339 473 if (rc2 != VERR_TIMEOUT && RT_FAILURE(rc2)) 340 474 { 341 VBoxServiceError(" RTSemEventMultiWait failed; rc2=%Rrc\n", rc2);342 rc = rc2;475 VBoxServiceError("Exec: Service terminating - RTSemEventMultiWait: %Rrc\n", rc2); 476 rcRet = rc2; 343 477 break; 344 478 } 345 479 } 346 480 347 RTSemEventMultiDestroy(g_ VMExecEvent);348 g_ VMExecEvent = NIL_RTSEMEVENTMULTI;349 return rc ;481 RTSemEventMultiDestroy(g_hExecEvent); 482 g_hExecEvent = NIL_RTSEMEVENTMULTI; 483 return rcRet; 350 484 } 351 485 … … 356 490 /** @todo Later, figure what to do if we're in RTProcWait(). it's a very 357 491 * annoying call since doesn't support timeouts in the posix world. */ 358 RTSemEventMultiSignal(g_ VMExecEvent);492 RTSemEventMultiSignal(g_hExecEvent); 359 493 #ifdef FULL_FEATURED_EXEC 360 494 Interrupts waits. … … 367 501 { 368 502 /* Nothing here yet. */ 369 VbglR3GuestPropDisconnect(g_ VMExecGuestPropSvcClientID);370 g_ VMExecGuestPropSvcClientID = 0;371 372 RTSemEventMultiDestroy(g_ VMExecEvent);373 g_ VMExecEvent = NIL_RTSEMEVENTMULTI;503 VbglR3GuestPropDisconnect(g_uExecGuestPropSvcClientID); 504 g_uExecGuestPropSvcClientID = 0; 505 506 RTSemEventMultiDestroy(g_hExecEvent); 507 g_hExecEvent = NIL_RTSEMEVENTMULTI; 374 508 } 375 509 … … 378 512 * The 'vminfo' service description. 379 513 */ 380 VBOXSERVICE g_ VMExec =514 VBOXSERVICE g_Exec = 381 515 { 382 516 /* pszName. */ 383 " vmexec",517 "exec", 384 518 /* pszDescription. */ 385 " Virtual Machine RemoteExecution",519 "Host-driven Command Execution", 386 520 /* pszUsage. */ 387 "[-- vmexec-interval <ms>]"521 "[--exec-interval <ms>]" 388 522 , 389 523 /* pszOptions. */ 390 " -- vmexec-intervalSpecifies the interval at which to check for new\n"524 " --exec-interval Specifies the interval at which to check for new\n" 391 525 " remote execution commands. The default is 10000 ms.\n" 392 526 , -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
r22728 r22744 135 135 extern VBOXSERVICE g_Control; 136 136 extern VBOXSERVICE g_VMInfo; 137 extern VBOXSERVICE g_ VMExec;137 extern VBOXSERVICE g_Exec; 138 138 139 139 #ifdef RT_OS_WINDOWS
Note:
See TracChangeset
for help on using the changeset viewer.