Changeset 36099 in vbox
- Timestamp:
- Feb 28, 2011 2:20:13 PM (14 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/HostServices/GuestControlSvc.h
r34556 r36099 44 44 /** 45 45 * Process status when executed in the guest. 46 * Note: Has to match Main's ExecuteProcessStatus_*! 46 47 */ 47 48 enum eProcessStatus -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
r36035 r36099 80 80 * started guest process to the command line VBoxManage was started from. 81 81 * Useful for e.g. scripting. 82 * @todo r=bird: RTEXITCODE is using the RT prefix, that is reserved for IPRT 83 * use only. 84 */ 85 enum RTEXITCODE_EXEC 86 { 87 RTEXITCODE_EXEC_SUCCESS = RTEXITCODE_SUCCESS, 88 RTEXITCODE_EXEC_FAILED = 16, 89 RTEXITCODE_EXEC_TERM_SIGNAL = 17, 90 RTEXITCODE_EXEC_TERM_ABEND = 18, 91 RTEXITCODE_EXEC_TIMEOUT = 19, 92 RTEXITCODE_EXEC_CANCELED = 20 82 */ 83 enum EXITCODE_EXEC 84 { 85 EXITCODE_EXEC_SUCCESS = RTEXITCODE_SUCCESS, 86 /* Process exited normally but with an exit code <> 0. */ 87 EXITCODE_EXEC_CODE = 16, 88 EXITCODE_EXEC_FAILED = 17, 89 EXITCODE_EXEC_TERM_SIGNAL = 18, 90 EXITCODE_EXEC_TERM_ABEND = 19, 91 EXITCODE_EXEC_TIMEOUT = 20, 92 EXITCODE_EXEC_DOWN = 21, 93 EXITCODE_EXEC_CANCELED = 22 93 94 }; 94 95 95 96 /** 96 97 * RTGetOpt-IDs for the guest execution control command line. 97 * @todo r=bird: RTGETOPTDEF_EXEC is using the RT prefix, that is reserved for 98 * IPRT use only. 99 */ 100 enum RTGETOPTDEF_EXEC 101 { 102 RTGETOPTDEF_EXEC_IGNOREORPHANEDPROCESSES = 1000, 103 RTGETOPTDEF_EXEC_OUTPUTFORMAT, 104 RTGETOPTDEF_EXEC_OUTPUTTYPE, 105 RTGETOPTDEF_EXEC_WAITFOREXIT, 106 RTGETOPTDEF_EXEC_WAITFORSTDOUT, 107 RTGETOPTDEF_EXEC_WAITFORSTDERR, 108 RTGETOPTDEF_EXEC_ARGS 98 */ 99 enum GETOPTDEF_EXEC 100 { 101 GETOPTDEF_EXEC_IGNOREORPHANEDPROCESSES = 1000, 102 GETOPTDEF_EXEC_OUTPUTFORMAT, 103 GETOPTDEF_EXEC_DOS2UNIX, 104 GETOPTDEF_EXEC_UNIX2DOS, 105 GETOPTDEF_EXEC_WAITFOREXIT, 106 GETOPTDEF_EXEC_WAITFORSTDOUT, 107 GETOPTDEF_EXEC_WAITFORSTDERR 108 }; 109 110 enum OUTPUT_TYPE 111 { 112 OUTPUT_TYPE_UNDEFINED = 0, 113 OUTPUT_TYPE_DOS2UNIX = 10, 114 OUTPUT_TYPE_UNIX2DOS = 20 109 115 }; 110 116 … … 117 123 " --image <path to program>\n" 118 124 " --username <name> --password <password>\n" 125 " [--dos2unix]\n" 119 126 " [--environment \"<NAME>=<VALUE> [<NAME>=<VALUE>]\"]\n" 120 " [--timeout <msec>] [-- verbose]\n"127 " [--timeout <msec>] [--unix2dos] [--verbose]\n" 121 128 " [--wait-exit] [--wait-stdout] [--wait-stdout]" 122 129 //" [--output-format=<dos>|<unix>]\n" … … 183 190 * string. 184 191 */ 185 static const char *ctrlExecProcessStatusToText( ULONG uStatus)186 { 187 switch ( uStatus)188 { 189 case guestControl::PROC_STS_STARTED:192 static const char *ctrlExecProcessStatusToText(ExecuteProcessStatus enmStatus) 193 { 194 switch (enmStatus) 195 { 196 case ExecuteProcessStatus_Started: 190 197 return "started"; 191 case guestControl::PROC_STS_TEN:198 case ExecuteProcessStatus_TerminatedNormally: 192 199 return "successfully terminated"; 193 case guestControl::PROC_STS_TES:200 case ExecuteProcessStatus_TerminatedSignal: 194 201 return "terminated by signal"; 195 case guestControl::PROC_STS_TEA:202 case ExecuteProcessStatus_TerminatedAbnormally: 196 203 return "abnormally aborted"; 197 case guestControl::PROC_STS_TOK:204 case ExecuteProcessStatus_TimedOutKilled: 198 205 return "timed out"; 199 case guestControl::PROC_STS_TOA:206 case ExecuteProcessStatus_TimedOutAbnormally: 200 207 return "timed out, hanging"; 201 case guestControl::PROC_STS_DWN:208 case ExecuteProcessStatus_Down: 202 209 return "killed"; 203 case guestControl::PROC_STS_ERROR:210 case ExecuteProcessStatus_Error: 204 211 return "error"; 205 212 default: … … 209 216 } 210 217 211 static int ctrlExecProcessStatusToExitCode(ULONG uStatus) 212 { 213 int rc = RTEXITCODE_EXEC_SUCCESS; 214 switch (uStatus) 215 { 216 /** @todo r=bird: Why do you use guestControl status codes here? Is the Main 217 * API not exposing these constants? If so, it's something that 218 * needs fixing. */ 219 case guestControl::PROC_STS_STARTED: 220 rc = RTEXITCODE_EXEC_SUCCESS; 218 static int ctrlExecProcessStatusToExitCode(ExecuteProcessStatus enmStatus, ULONG uExitCode) 219 { 220 int rc = EXITCODE_EXEC_SUCCESS; 221 switch (enmStatus) 222 { 223 case ExecuteProcessStatus_Started: 224 rc = EXITCODE_EXEC_SUCCESS; 221 225 break; 222 case guestControl::PROC_STS_TEN: 223 /** @todo check the exit code, 0 is success, !0 should be indicated 224 * by a specail VBoxManage exit code. */ 225 rc = RTEXITCODE_EXEC_SUCCESS; 226 case ExecuteProcessStatus_TerminatedNormally: 227 rc = !uExitCode ? EXITCODE_EXEC_SUCCESS : EXITCODE_EXEC_CODE; 226 228 break; 227 case guestControl::PROC_STS_TES:228 rc = RTEXITCODE_EXEC_TERM_SIGNAL;229 case ExecuteProcessStatus_TerminatedSignal: 230 rc = EXITCODE_EXEC_TERM_SIGNAL; 229 231 break; 230 case guestControl::PROC_STS_TEA:231 rc = RTEXITCODE_EXEC_TERM_ABEND;232 case ExecuteProcessStatus_TerminatedAbnormally: 233 rc = EXITCODE_EXEC_TERM_ABEND; 232 234 break; 233 case guestControl::PROC_STS_TOK:234 rc = RTEXITCODE_EXEC_TIMEOUT;235 case ExecuteProcessStatus_TimedOutKilled: 236 rc = EXITCODE_EXEC_TIMEOUT; 235 237 break; 236 case guestControl::PROC_STS_TOA:237 rc = RTEXITCODE_EXEC_TIMEOUT;238 case ExecuteProcessStatus_TimedOutAbnormally: 239 rc = EXITCODE_EXEC_TIMEOUT; 238 240 break; 239 case guestControl::PROC_STS_DWN:241 case ExecuteProcessStatus_Down: 240 242 /* Service/OS is stopping, process was killed, so 241 243 * not exactly an error of the started process ... */ 242 rc = RTEXITCODE_EXEC_SUCCESS; /** @todo r=bird: return failure if you don't know what happend. No false positives, please. */244 rc = EXITCODE_EXEC_DOWN; 243 245 break; 244 case guestControl::PROC_STS_ERROR:245 rc = RTEXITCODE_EXEC_FAILED;246 case ExecuteProcessStatus_Error: 247 rc = EXITCODE_EXEC_FAILED; 246 248 break; 247 249 default: 248 AssertMsgFailed(("Unknown exit code (%u) from guest process returned!\n", uStatus));250 AssertMsgFailed(("Unknown exit code (%u) from guest process returned!\n", enmStatus)); 249 251 break; 250 252 } … … 373 375 static const RTGETOPTDEF s_aOptions[] = 374 376 { 375 { "--environment", 'e', RTGETOPT_REQ_STRING }, 376 { "--flags", 'f', RTGETOPT_REQ_STRING }, 377 { "--ignore-operhaned-processes", RTGETOPTDEF_EXEC_IGNOREORPHANEDPROCESSES, RTGETOPT_REQ_NOTHING }, 378 { "--image", 'i', RTGETOPT_REQ_STRING }, 379 //{ "--output-format", RTGETOPTDEF_EXEC_OUTPUTFORMAT, RTGETOPT_REQ_STRING }, 380 { "--output-type", RTGETOPTDEF_EXEC_OUTPUTTYPE, RTGETOPT_REQ_STRING }, 381 /** @todo r=bird: output-type and output-format are the same thing. 382 * Please just call it --dos2unix and --unix2dos and 383 * implement it them. (If you insist on flexibility, it would 384 * be --input-type <x> and --output-type <y>, where x and y 385 * could indicate line ending styles (CR/LF/CRLF), encodings 386 * (UTF-8, UTF-16, ++), code pages and plugin provided 387 * conversions. See the conv option of dd and iconv for 388 * inspiration.) 389 * 390 * The default must be no conversion at all, i.e. 391 * --output-type=binary. */ 392 { "--password", 'p', RTGETOPT_REQ_STRING }, 393 { "--timeout", 't', RTGETOPT_REQ_UINT32 }, 394 { "--username", 'u', RTGETOPT_REQ_STRING }, 395 { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, 396 { "--wait-exit", RTGETOPTDEF_EXEC_WAITFOREXIT, RTGETOPT_REQ_NOTHING }, 397 { "--wait-stdout", RTGETOPTDEF_EXEC_WAITFORSTDOUT, RTGETOPT_REQ_NOTHING }, 398 { "--wait-stderr", RTGETOPTDEF_EXEC_WAITFORSTDERR, RTGETOPT_REQ_NOTHING }, 399 /* @todo r=bird: '--' is interpreted by RTGetOpt() to indicate the 400 * end of arguments, you don't need to handle this specially. 401 * RTGetOpt() will return VINF_GETOPT_NOT_OPTION for anything following 402 * a '--' argument. So, let me give you some other examples for illustrating 403 * what I mean should work now (all the same, userid/pw missing): 404 * VBoxManage guestcontrol myvm exec --image /bin/busybox cp /foo /bar 405 * VBoxManage guestcontrol myvm exec --image /bin/busybox -- cp /foo /bar 406 * VBoxManage guestcontrol myvm exec --image /bin/busybox cp -- /foo /bar 407 * VBoxManage guestcontrol myvm exec --image /bin/busybox cp /foo -- /bar 408 * 409 * Same, but with standard cp (image defaults to /bin/cp): 410 * VBoxManage guestcontrol myvm exec /bin/cp /foo /bar 411 * VBoxManage guestcontrol myvm exec -- /bin/cp /foo /bar 412 * VBoxManage guestcontrol myvm exec /bin/cp -- /foo /bar 413 * VBoxManage guestcontrol myvm exec /bin/cp /foo -- /bar 414 * 415 * The old example: 416 * VBoxManage guestcontrol myvm exec --image /bin/busybox -- ln -s /foo /bar 417 * 418 * As an example of where '--' is used by standard linux utils, try delete a 419 * file named '-f' without specifying the directory: 420 * > -f # creates the file 421 * rm -v -f # does nothing because '-f' is a rm option. 422 * rm -v -- -f # does the trick because '--' tells rm to not read '-f' as an option. 423 */ 424 { "--", RTGETOPTDEF_EXEC_ARGS, RTGETOPT_REQ_STRING } 377 { "--dos2unix", GETOPTDEF_EXEC_DOS2UNIX, RTGETOPT_REQ_NOTHING }, 378 { "--environment", 'e', RTGETOPT_REQ_STRING }, 379 { "--flags", 'f', RTGETOPT_REQ_STRING }, 380 { "--ignore-operhaned-processes", GETOPTDEF_EXEC_IGNOREORPHANEDPROCESSES, RTGETOPT_REQ_NOTHING }, 381 { "--image", 'i', RTGETOPT_REQ_STRING }, 382 { "--password", 'p', RTGETOPT_REQ_STRING }, 383 { "--timeout", 't', RTGETOPT_REQ_UINT32 }, 384 { "--unix2dos", GETOPTDEF_EXEC_UNIX2DOS, RTGETOPT_REQ_NOTHING }, 385 { "--username", 'u', RTGETOPT_REQ_STRING }, 386 { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, 387 { "--wait-exit", GETOPTDEF_EXEC_WAITFOREXIT, RTGETOPT_REQ_NOTHING }, 388 { "--wait-stdout", GETOPTDEF_EXEC_WAITFORSTDOUT, RTGETOPT_REQ_NOTHING }, 389 { "--wait-stderr", GETOPTDEF_EXEC_WAITFORSTDERR, RTGETOPT_REQ_NOTHING } 425 390 }; 426 391 … … 437 402 Utf8Str Utf8Password; 438 403 uint32_t cMsTimeout = 0; 404 OUTPUT_TYPE eOutputType = OUTPUT_TYPE_UNDEFINED; 439 405 bool fOutputBinary = false; 440 406 bool fWaitForExit = false; … … 450 416 switch (ch) 451 417 { 418 case GETOPTDEF_EXEC_DOS2UNIX: 419 if (eOutputType != OUTPUT_TYPE_UNDEFINED) 420 return errorSyntax(USAGE_GUESTCONTROL, "More than one output type (dos2unix/unix2dos) specified!"); 421 eOutputType = OUTPUT_TYPE_DOS2UNIX; 422 break; 423 452 424 case 'e': /* Environment */ 453 425 { … … 465 437 } 466 438 467 case RTGETOPTDEF_EXEC_IGNOREORPHANEDPROCESSES:439 case GETOPTDEF_EXEC_IGNOREORPHANEDPROCESSES: 468 440 fFlags |= ExecuteProcessFlag_IgnoreOrphanedProcesses; 469 441 break; … … 473 445 break; 474 446 475 /** @todo Add DOS2UNIX and vice versa handling!476 case RTGETOPTDEF_EXEC_OUTPUTFORMAT:477 break;*/478 479 case RTGETOPTDEF_EXEC_OUTPUTTYPE:480 if (!RTStrICmp(ValueUnion.psz, "binary"))481 fOutputBinary = true;482 else if (!RTStrICmp(ValueUnion.psz, "text"))483 fOutputBinary = false;484 else485 {486 AssertPtr(GetState.pDef->pszLong);487 return errorSyntax(USAGE_GUESTCONTROL, "Unknown value for '%s' specified! Use either 'binary' or 'text'",488 GetState.pDef->pszLong);489 }490 break;491 492 447 /** @todo Add a hidden flag. */ 493 448 … … 500 455 break; 501 456 457 case GETOPTDEF_EXEC_UNIX2DOS: 458 if (eOutputType != OUTPUT_TYPE_UNDEFINED) 459 return errorSyntax(USAGE_GUESTCONTROL, "More than one output type (dos2unix/unix2dos) specified!"); 460 eOutputType = OUTPUT_TYPE_UNIX2DOS; 461 break; 462 502 463 case 'u': /* User name */ 503 464 Utf8UserName = ValueUnion.psz; … … 508 469 break; 509 470 510 case RTGETOPTDEF_EXEC_WAITFOREXIT:471 case GETOPTDEF_EXEC_WAITFOREXIT: 511 472 fWaitForExit = true; 512 473 break; 513 474 514 case RTGETOPTDEF_EXEC_WAITFORSTDOUT:475 case GETOPTDEF_EXEC_WAITFORSTDOUT: 515 476 fWaitForExit = true; 516 477 fWaitForStdOut = true; 517 478 break; 518 479 519 case RTGETOPTDEF_EXEC_WAITFORSTDERR:480 case GETOPTDEF_EXEC_WAITFORSTDERR: 520 481 fWaitForExit = true; 521 482 fWaitForStdErr = true; 522 483 break; 523 484 524 case RTGETOPTDEF_EXEC_ARGS:485 case VINF_GETOPT_NOT_OPTION: 525 486 { 526 /* Push current parameter to vector. */527 args.push_back(Bstr(ValueUnion.psz).raw());528 529 /*530 * Add all following parameters after this one to our guest process531 * argument vector.532 */533 while ( (ch = RTGetOpt(&GetState, &ValueUnion))534 && RT_SUCCESS(vrc))535 {536 /*537 * Is this option unknown or not recognized an option? Then just538 * add the raw string value to our argument vector.539 */540 if ( ch == VINF_GETOPT_NOT_OPTION541 || ch == VERR_GETOPT_UNKNOWN_OPTION)542 args.push_back(Bstr(ValueUnion.psz).raw());543 /*544 * If this is an option/parameter we already defined for our actual545 * execution command we need to take the pDef->pszLong value instead.546 */547 else if (ValueUnion.pDef)548 args.push_back(Bstr(ValueUnion.pDef->pszLong).raw());549 else550 AssertMsgFailed(("Unknown parameter type detected!\n"));551 }552 break;553 }554 555 case VINF_GETOPT_NOT_OPTION:556 487 if (Utf8Cmd.isEmpty()) 557 488 Utf8Cmd = ValueUnion.psz; 558 489 else 559 return RTGetOptPrintError(ch, &ValueUnion); 560 break; 490 { 491 /* Push current parameter to vector. */ 492 args.push_back(Bstr(ValueUnion.psz).raw()); 493 494 /* 495 * Add all following parameters after this one to our guest process 496 * argument vector. 497 */ 498 while ( (ch = RTGetOpt(&GetState, &ValueUnion)) 499 && RT_SUCCESS(vrc)) 500 { 501 /* 502 * Is this option unknown or not recognized an option? Then just 503 * add the raw string value to our argument vector. 504 */ 505 if ( ch == VINF_GETOPT_NOT_OPTION 506 || ch == VERR_GETOPT_UNKNOWN_OPTION) 507 args.push_back(Bstr(ValueUnion.psz).raw()); 508 /* 509 * If this is an option/parameter we already defined for our actual 510 * execution command we need to take the pDef->pszLong value instead. 511 */ 512 else if (ValueUnion.pDef) 513 args.push_back(Bstr(ValueUnion.pDef->pszLong).raw()); 514 else 515 AssertMsgFailed(("Unknown parameter type detected!\n")); 516 } 517 } 518 break; 519 } 561 520 562 521 default: 563 522 return RTGetOptPrintError(ch, &ValueUnion); 564 523 } 565 }566 567 if (RT_FAILURE(vrc)) /** @todo r=bird: You don't need to check vrc here or in any of the two while conditions above because you are now returning directly in those cases. Drop the checks, this will keep things simpler. */568 {569 RTMsgError("Failed to parse argument '%c', rc=%Rrc", ch, vrc);570 return RTEXITCODE_FAILURE;571 524 } 572 525 … … 593 546 594 547 /* Execute the process. */ 595 int rcProc = RTEXITCODE_EXEC_SUCCESS; /** @todo r=bird: Don't initialize this, please, set it explicitly in the various branches. It's easier to see what it's going to be that way. */548 int rcProc; 596 549 ComPtr<IProgress> progress; 597 550 ULONG uPID = 0; … … 606 559 progress.asOutParam()); 607 560 if (FAILED(rc)) 608 vrc = ctrlPrintError(guest, COM_IIDOF(IGuest)); /** @todo return straight away and drop state (e.g. rcProc) confusion. */561 return ctrlPrintError(guest, COM_IIDOF(IGuest)); 609 562 else 610 563 { … … 692 645 if (cbOutputData > 0) 693 646 { 694 /** @todo r=bird: Adding exec options to convert unix2dos 695 * and dos2unix. Use a VFS I/O stream filter for doing this, it's a 647 /** @todo r=bird: Use a VFS I/O stream filter for doing this, it's a 696 648 * generic problem and the new VFS APIs will handle it more 697 649 * transparently. (requires writing dos2unix/unix2dos filters ofc) */ 698 if ( !fOutputBinary)650 if (eOutputType != OUTPUT_TYPE_UNDEFINED) 699 651 { 700 652 /* … … 769 721 if (fVerbose) 770 722 RTPrintf("Process execution canceled!\n"); 771 rcProc = RTEXITCODE_EXEC_CANCELED;723 rcProc = EXITCODE_EXEC_CANCELED; 772 724 } 773 725 else if ( fCompleted … … 780 732 else 781 733 { 782 ULONG uRetStatus, uRetExitCode, uRetFlags; 783 rc = guest->GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &uRetStatus); 734 ExecuteProcessStatus retStatus; 735 ULONG uRetExitCode, uRetFlags; 736 rc = guest->GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus); 784 737 if (SUCCEEDED(rc) && fVerbose) 785 RTPrintf("Exit code=%u (Status=%u [%s], Flags=%u)\n", uRetExitCode, uRetStatus, ctrlExecProcessStatusToText(uRetStatus), uRetFlags); 786 /** @todo r=bird: This isn't taking uRetExitCode into 787 * account. We MUST give the users a way to indicate 788 * whether the guest program terminated with an 0 or 789 * non-zero exit code. */ 790 rcProc = ctrlExecProcessStatusToExitCode(uRetStatus); 738 RTPrintf("Exit code=%u (Status=%u [%s], Flags=%u)\n", uRetExitCode, retStatus, ctrlExecProcessStatusToText(retStatus), uRetFlags); 739 rcProc = ctrlExecProcessStatusToExitCode(retStatus, uRetExitCode); 791 740 } 792 741 } … … 795 744 if (fVerbose) 796 745 RTPrintf("Process execution aborted!\n"); 797 /** @todo r=bird: Should set rcProc here, this is not a 798 * success branch. */ 746 rcProc = EXITCODE_EXEC_TERM_ABEND; 799 747 } 800 748 } … … 1197 1145 AssertPtrReturn(pArg, VERR_INVALID_PARAMETER); 1198 1146 1199 /*1200 * Check the syntax.1201 */1202 if (pArg->argc < 2) /* At least the source + destination should be present :-). */1203 return errorSyntax(USAGE_GUESTCONTROL, "Incorrect parameters");1204 1205 1147 static const RTGETOPTDEF s_aOptions[] = 1206 1148 { … … 1229 1171 int vrc = VINF_SUCCESS; 1230 1172 uint32_t idxNonOption = 0; 1231 bool fUsageOK = true; 1232 while ( (ch = RTGetOpt(&GetState, &ValueUnion)) 1233 && RT_SUCCESS(vrc)) 1173 while (ch = RTGetOpt(&GetState, &ValueUnion)) 1234 1174 { 1235 1175 /* For options that require an argument, ValueUnion has received the value. */ … … 1274 1214 1275 1215 default: 1276 /** @todo r=bird: {2..UINT32_MAX-1} goes unnoticed 1277 * to /dev/null? That doesn't make much 1278 * sense... Why not just return with a syntax 1279 * error straight away? */ 1216 return errorSyntax(USAGE_GUESTCONTROL, "Too many parameters specified, only source and destination allowed!"); 1217 /* Never reached. */ 1280 1218 break; 1281 1219 } 1282 1220 idxNonOption++; 1283 1221 if (idxNonOption == UINT32_MAX) 1284 { 1285 RTMsgError("Too many files specified! Aborting.\n"); 1286 vrc = VERR_TOO_MUCH_DATA; /** @todo r=bird: return straight away, drop the RT_SUCCESS(vrc) from the while condition. Keep things simple. */ 1287 } 1222 return errorSyntax(USAGE_GUESTCONTROL, "Too many files specified!"); 1288 1223 break; 1289 1224 } … … 1293 1228 } 1294 1229 } 1295 1296 if (!fUsageOK) /** @todo r=bird: fUsageOK - never set to false, just drop it. Keep the state simple. */1297 return errorSyntax(USAGE_GUESTCONTROL, "Incorrect parameters");1298 1230 1299 1231 if (Utf8Source.isEmpty()) … … 1388 1320 AssertPtrReturn(pArg, VERR_INVALID_PARAMETER); 1389 1321 1390 /*1391 * Check the syntax. We can deduce the correct syntax from the number of1392 * arguments.1393 */1394 if (pArg->argc < 2) /* At least the directory we want to create should be present :-). */1395 return errorSyntax(USAGE_GUESTCONTROL, "Incorrect parameters");1396 1397 1322 static const RTGETOPTDEF s_aOptions[] = 1398 1323 { … … 1512 1437 * arguments. 1513 1438 */ 1514 if (pArg->argc < 1) /* At least the VM name should be present :-). */ /** @todo r=bird: This is no longer correct. Ditto for all other handlers. */1515 return errorSyntax(USAGE_GUESTCONTROL, "Incorrect parameters");1516 1517 1439 Utf8Str Utf8Source; 1518 1440 bool fVerbose = false; … … 1621 1543 AssertPtrReturn(pArg, VERR_INVALID_PARAMETER); 1622 1544 1623 /* At least the VM name + sub command needs to be specified. */1624 if (pArg->argc <= 2)1625 return errorSyntax(USAGE_GUESTCONTROL, "Incorrect parameters");1626 1627 1545 HandlerArg arg = *pArg; 1628 1546 arg.argc = pArg->argc - 2; /* Skip VM name and sub command. */ -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r36082 r36099 8076 8076 8077 8077 <enum 8078 name="ExecuteProcessStatus" 8079 uuid="153768d9-d971-4098-8b5a-c5cb1ab9ea88" 8080 > 8081 <desc> 8082 Guest process execution status. 8083 </desc> 8084 8085 <const name="Undefined" value="0"> 8086 <desc>Process is in an undefined state.</desc> 8087 </const> 8088 8089 <const name="Started" value="1"> 8090 <desc>Process has been started.</desc> 8091 </const> 8092 8093 <const name="TerminatedNormally" value="2"> 8094 <desc>Process terminated normally.</desc> 8095 </const> 8096 8097 <const name="TerminatedSignal" value="3"> 8098 <desc>Process terminated via signal.</desc> 8099 </const> 8100 8101 <const name="TerminatedAbnormally" value="4"> 8102 <desc>Process terminated abnormally.</desc> 8103 </const> 8104 8105 <const name="TimedOutKilled" value="5"> 8106 <desc>Process timed out and was killed.</desc> 8107 </const> 8108 8109 <const name="TimedOutAbnormally" value="6"> 8110 <desc>Process timed out and was not killed successfully.</desc> 8111 </const> 8112 8113 <const name="Down" value="7"> 8114 <desc>Service/OS is stopping, process was killed.</desc> 8115 </const> 8116 8117 <const name="Error" value="8"> 8118 <desc>Something went wrong (error code in flags).</desc> 8119 </const> 8120 </enum> 8121 8122 <enum 8078 8123 name="ProcessInputFlag" 8079 8124 uuid="5d38c1dd-2604-4ddf-92e5-0c0cdd3bdbd5" … … 8086 8131 <desc>No flag set.</desc> 8087 8132 </const> 8133 8088 8134 <const name="EndOfFile" value="1"> 8089 8135 <desc>End of file (input) reached.</desc> … … 8136 8182 <interface 8137 8183 name="IGuest" extends="$unknown" 8138 uuid="4 db4f806-0a20-4772-9419-14563b662f93"8184 uuid="4e78f7dd-8ca1-47e5-a344-5207f793df71" 8139 8185 wsmap="managed" 8140 8186 > … … 8424 8470 </desc> 8425 8471 </param> 8426 <param name="reason" type=" unsigned long" dir="return">8472 <param name="reason" type="ExecuteProcessStatus" dir="return"> 8427 8473 <desc> 8428 8474 The current process status. -
trunk/src/VBox/Main/include/GuestImpl.h
r35967 r36099 94 94 STDMETHOD(GetProcessOutput)(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS, LONG64 aSize, ComSafeArrayOut(BYTE, aData)); 95 95 STDMETHOD(SetProcessInput)(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS, ComSafeArrayIn(BYTE, aData), ULONG *aBytesWritten); 96 STDMETHOD(GetProcessStatus)(ULONG aPID, ULONG *aExitCode, ULONG *aFlags, ULONG*aStatus);96 STDMETHOD(GetProcessStatus)(ULONG aPID, ULONG *aExitCode, ULONG *aFlags, ExecuteProcessStatus *aStatus); 97 97 STDMETHOD(CopyToGuest)(IN_BSTR aSource, IN_BSTR aDest, IN_BSTR aUserName, IN_BSTR aPassword, ULONG aFlags, IProgress **aProgress); 98 98 STDMETHOD(CreateDirectory)(IN_BSTR aDirectory, IN_BSTR aUserName, IN_BSTR aPassword, ULONG aMode, ULONG aFlags, IProgress **aProgress); … … 154 154 struct GuestProcess 155 155 { 156 uint32_tmStatus;156 ExecuteProcessStatus mStatus; 157 157 uint32_t mFlags; 158 158 uint32_t mExitCode; … … 179 179 void destroyCtrlCallbackContext(CallbackMapIter it); 180 180 uint32_t addCtrlCallbackContext(eVBoxGuestCtrlCallbackType enmType, void *pvData, uint32_t cbData, Progress* pProgress); 181 HRESULT waitForProcessStatusChange(ULONG uPID, ULONG *puRetStatus, ULONG *puRetExitCode, ULONG uTimeoutMS);181 HRESULT waitForProcessStatusChange(ULONG uPID, ExecuteProcessStatus *pRetStatus, ULONG *puRetExitCode, ULONG uTimeoutMS); 182 182 # endif 183 183 -
trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp
r35869 r36099 379 379 * canceled or we simply got all stuff transferred. 380 380 */ 381 ULONG uRetStatus, uRetExitCode; 382 rc = pGuest->waitForProcessStatusChange(uPID, &uRetStatus, &uRetExitCode, 10 * 1000 /* 10s timeout. */); 381 ExecuteProcessStatus retStatus; 382 ULONG uRetExitCode; 383 rc = pGuest->waitForProcessStatusChange(uPID, &retStatus, &uRetExitCode, 10 * 1000 /* 10s timeout. */); 383 384 if (FAILED(rc)) 384 385 { … … 388 389 { 389 390 if ( uRetExitCode != 0 390 || uRetStatus != PROC_STS_TEN)391 || retStatus != ExecuteProcessStatus_TerminatedNormally) 391 392 { 392 393 rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress, … … 786 787 } 787 788 788 ULONG uRetStatus, uRetExitCode, uRetFlags; 789 rc = pGuest->GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &uRetStatus); 789 ExecuteProcessStatus retStatus; 790 ULONG uRetExitCode, uRetFlags; 791 rc = pGuest->GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus); 790 792 if (SUCCEEDED(rc)) 791 793 { … … 802 804 { 803 805 LogRel(("Guest Additions update failed (Exit code=%u, Status=%u, Flags=%u)\n", 804 uRetExitCode, uRetStatus, uRetFlags));806 uRetExitCode, retStatus, uRetFlags)); 805 807 rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress, 806 808 Guest::tr("Guest Additions update failed with exit code=%u (status=%u, flags=%u)"), 807 uRetExitCode, uRetStatus, uRetFlags);809 uRetExitCode, retStatus, uRetFlags); 808 810 } 809 811 } … … 814 816 rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress, 815 817 Guest::tr("Guest Additions update was canceled by the guest with exit code=%u (status=%u, flags=%u)"), 816 uRetExitCode, uRetStatus, uRetFlags);818 uRetExitCode, retStatus, uRetFlags); 817 819 } 818 820 else … … 1113 1115 /* Not found, add to map. */ 1114 1116 GuestProcess newProcess; 1115 newProcess.mStatus = pCBData->u32Status;1117 newProcess.mStatus = (ExecuteProcessStatus)pCBData->u32Status; 1116 1118 newProcess.mExitCode = pCBData->u32Flags; /* Contains exit code. */ 1117 1119 newProcess.mFlags = 0; … … 1121 1123 else /* Update map. */ 1122 1124 { 1123 it_proc->second.mStatus = pCBData->u32Status;1125 it_proc->second.mStatus = (ExecuteProcessStatus)pCBData->u32Status; 1124 1126 it_proc->second.mExitCode = pCBData->u32Flags; /* Contains exit code. */ 1125 1127 it_proc->second.mFlags = 0; … … 1425 1427 } 1426 1428 1427 HRESULT Guest::waitForProcessStatusChange(ULONG uPID, ULONG *puRetStatus, ULONG *puRetExitCode, ULONG uTimeoutMS)1428 { 1429 AssertPtr(p uRetStatus);1429 HRESULT Guest::waitForProcessStatusChange(ULONG uPID, ExecuteProcessStatus *pRetStatus, ULONG *puRetExitCode, ULONG uTimeoutMS) 1430 { 1431 AssertPtr(pRetStatus); 1430 1432 AssertPtr(puRetExitCode); 1431 1433 … … 1450 1452 break; 1451 1453 } 1452 hRC = GetProcessStatus(uPID, puRetExitCode, &uRetFlagsIgnored, p uRetStatus);1454 hRC = GetProcessStatus(uPID, puRetExitCode, &uRetFlagsIgnored, pRetStatus); 1453 1455 if (FAILED(hRC)) 1454 1456 break; 1455 1457 RTThreadSleep(100); 1456 } while(*p uRetStatus == PROC_STS_STARTED&& SUCCEEDED(hRC));1458 } while(*pRetStatus == ExecuteProcessStatus_Started && SUCCEEDED(hRC)); 1457 1459 return hRC; 1458 1460 } … … 1849 1851 { 1850 1852 /* PID exists; check if process is still running. */ 1851 if (itProc->second.mStatus != PROC_STS_STARTED)1853 if (itProc->second.mStatus != ExecuteProcessStatus_Started) 1852 1854 rc = setError(VBOX_E_IPRT_ERROR, 1853 1855 Guest::tr("Cannot inject input to not running process (PID %u)"), aPID); … … 2200 2202 } 2201 2203 2202 STDMETHODIMP Guest::GetProcessStatus(ULONG aPID, ULONG *aExitCode, ULONG *aFlags, ULONG*aStatus)2204 STDMETHODIMP Guest::GetProcessStatus(ULONG aPID, ULONG *aExitCode, ULONG *aFlags, ExecuteProcessStatus *aStatus) 2203 2205 { 2204 2206 #ifndef VBOX_WITH_GUEST_CONTROL … … 2440 2442 if (fCompleted) 2441 2443 { 2442 ULONG uRetStatus, uRetExitCode, uRetFlags; 2444 ExecuteProcessStatus retStatus; 2445 ULONG uRetExitCode, uRetFlags; 2443 2446 if (SUCCEEDED(rc)) 2444 2447 { 2445 rc = GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, & uRetStatus);2448 rc = GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus); 2446 2449 if (SUCCEEDED(rc) && uRetExitCode != 0) 2447 2450 {
Note:
See TracChangeset
for help on using the changeset viewer.