204
204
AssertPtrReturn(pThread, VERR_INVALID_POINTER);
206
VBoxServiceVerbose(3, "ControlThread: [PID %u]: Stopping ...\n",
206
VBoxServiceVerbose(3, "[PID %u]: Stopping ...\n",
209
209
int rc = vboxServiceControlThreadRequestCancel(pThread->pRequest);
210
210
if (RT_FAILURE(rc))
211
VBoxServiceError("ControlThread: [PID %u]: Signalling request event failed, rc=%Rrc\n",
211
VBoxServiceError("[PID %u]: Signalling request event failed, rc=%Rrc\n",
212
212
pThread->uPID, rc);
214
214
/* Do *not* set pThread->fShutdown or other stuff here!
235
235
* @return IPRT status code.
236
236
* @param pThread Thread to wait shutting down for.
237
237
* @param RTMSINTERVAL Timeout in ms to wait for shutdown.
238
* @param prc Where to store the thread's return code. Optional.
239
240
int VBoxServiceControlThreadWait(const PVBOXSERVICECTRLTHREAD pThread,
240
RTMSINTERVAL msTimeout)
241
RTMSINTERVAL msTimeout, int *prc)
242
243
AssertPtrReturn(pThread, VERR_INVALID_POINTER);
244
/* prc is optional. */
243
246
int rc = VINF_SUCCESS;
244
247
if ( pThread->Thread != NIL_RTTHREAD
245
248
&& ASMAtomicReadBool(&pThread->fStarted))
247
VBoxServiceVerbose(2, "ControlThread: [PID %u]: Waiting for shutdown ...\n",
250
VBoxServiceVerbose(2, "[PID %u]: Waiting for shutdown of pThread=0x%p = \"%s\"...\n",
251
pThread->uPID, pThread, pThread->pszCmd);
250
253
/* Wait a bit ... */
252
255
rc = RTThreadWait(pThread->Thread, msTimeout, &rcThread);
253
256
if (RT_FAILURE(rc))
255
VBoxServiceError("ControlThread: [PID %u]: Waiting for shutting down thread returned error rc=%Rrc\n",
258
VBoxServiceError("[PID %u]: Waiting for shutting down thread returned error rc=%Rrc\n",
256
259
pThread->uPID, rc);
260
if (RT_FAILURE(rcThread))
262
VBoxServiceError("ControlThread: [PID %u]: Shutdown returned error rc=%Rrc\n",
263
pThread->uPID, rcThread);
263
VBoxServiceVerbose(3, "[PID %u]: Thread reported exit code=%Rrc\n",
264
pThread->uPID, rcThread);
405
406
uint8_t byData[_64K];
406
407
rc = RTPipeRead(*phPipeR,
407
408
byData, sizeof(byData), &cbRead);
408
VBoxServiceVerbose(4, "ControlThread: VBoxServiceControlThreadHandleOutputEvent cbRead=%u, rc=%Rrc\n",
409
VBoxServiceVerbose(4, "VBoxServiceControlThreadHandleOutputEvent cbRead=%u, rc=%Rrc\n",
411
412
/* Make sure we go another poll round in case there was too much data
436
437
int rc = RTPipeRead(pThread->hNotificationPipeR, abBuf, sizeof(abBuf), &cbIgnore);
437
438
if (RT_FAILURE(rc))
438
VBoxServiceError("ControlThread: Draining IPC notification pipe failed with rc=%Rrc\n", rc);
439
VBoxServiceError("Draining IPC notification pipe failed with rc=%Rrc\n", rc);
440
441
int rcReq = VINF_SUCCESS; /* Actual request result. */
442
443
PVBOXSERVICECTRLREQUEST pRequest = pThread->pRequest;
445
VBoxServiceError("ControlThread: IPC request is invalid\n");
446
VBoxServiceError("IPC request is invalid\n");
446
447
return VERR_INVALID_POINTER;
531
532
pRequest->rc = RT_SUCCESS(rc)
534
VBoxServiceVerbose(2, "ControlThread: [PID %u]: Handled req=%u, CID=%u, rc=%Rrc, cbData=%u\n",
535
VBoxServiceVerbose(2, "[PID %u]: Handled req=%u, CID=%u, rc=%Rrc, cbData=%u\n",
535
536
pThread->uPID, pRequest->enmType, pRequest->uCID, pRequest->rc, pRequest->cbData);
537
538
/* In any case, regardless of the result, we notify
597
598
* Before entering the loop, tell the host that we've started the guest
598
599
* and that it's now OK to send input to the process.
600
VBoxServiceVerbose(2, "ControlThread: [PID %u]: Process \"%s\" started, CID=%u, User=%s\n",
601
VBoxServiceVerbose(2, "[PID %u]: Process \"%s\" started, CID=%u, User=%s\n",
601
602
pThread->uPID, pThread->pszCmd, pThread->uContextID, pThread->pszUser);
602
603
rc = VbglR3GuestCtrlExecReportStatus(pThread->uClientID, pThread->uContextID,
603
604
pThread->uPID, PROC_STS_STARTED, 0 /* u32Flags */,
659
VBoxServiceVerbose(4, "ControlThread: [PID %u]: Polling done, pollRC=%Rrc, pollCnt=%u, rc=%Rrc, fShutdown=%RTbool\n",
660
VBoxServiceVerbose(4, "[PID %u]: Polling done, pollRC=%Rrc, pollCnt=%u, rc=%Rrc, fShutdown=%RTbool\n",
660
661
pThread->uPID, rc2, RTPollSetGetCount(hPollSet), rc, pThread->fShutdown);
702
703
uint64_t cMsElapsed = u64Now - MsStart;
703
704
if (cMsElapsed >= cMsTimeout)
705
VBoxServiceVerbose(3, "ControlThread: [PID %u]: Timed out (%ums elapsed > %ums timeout), killing ...",
706
VBoxServiceVerbose(3, "[PID %u]: Timed out (%ums elapsed > %ums timeout), killing ...",
706
707
pThread->uPID, cMsElapsed, cMsTimeout);
708
709
fProcessTimedOut = true;
762
763
for (size_t i = 0; i < 10; i++)
764
VBoxServiceVerbose(4, "ControlThread: [PID %u]: Kill attempt %d/10: Waiting to exit ...\n",
765
VBoxServiceVerbose(4, "[PID %u]: Kill attempt %d/10: Waiting to exit ...\n",
765
766
pThread->uPID, i + 1);
766
767
rc2 = RTProcWait(hProcess, RTPROCWAIT_FLAGS_NOBLOCK, &ProcessStatus);
767
768
if (RT_SUCCESS(rc2))
769
VBoxServiceVerbose(4, "ControlThread: [PID %u]: Kill attempt %d/10: Exited\n",
770
VBoxServiceVerbose(4, "[PID %u]: Kill attempt %d/10: Exited\n",
770
771
pThread->uPID, i + 1);
771
772
fProcessAlive = false;
776
VBoxServiceVerbose(4, "ControlThread: [PID %u]: Kill attempt %d/10: Trying to terminate ...\n",
777
VBoxServiceVerbose(4, "[PID %u]: Kill attempt %d/10: Trying to terminate ...\n",
777
778
pThread->uPID, i + 1);
778
779
RTProcTerminate(hProcess);
796
797
if ( fProcessTimedOut && !fProcessAlive && MsProcessKilled != UINT64_MAX)
798
VBoxServiceVerbose(3, "ControlThread: [PID %u]: Timed out and got killed\n",
799
VBoxServiceVerbose(3, "[PID %u]: Timed out and got killed\n",
800
801
uStatus = PROC_STS_TOK;
802
803
else if (fProcessTimedOut && fProcessAlive && MsProcessKilled != UINT64_MAX)
804
VBoxServiceVerbose(3, "ControlThread: [PID %u]: Timed out and did *not* get killed\n",
805
VBoxServiceVerbose(3, "[PID %u]: Timed out and did *not* get killed\n",
806
807
uStatus = PROC_STS_TOA;
808
809
else if (pThread->fShutdown && (fProcessAlive || MsProcessKilled != UINT64_MAX))
810
VBoxServiceVerbose(3, "ControlThread: [PID %u]: Got terminated because system/service is about to shutdown\n",
811
VBoxServiceVerbose(3, "[PID %u]: Got terminated because system/service is about to shutdown\n",
812
813
uStatus = PROC_STS_DWN; /* Service is stopping, process was killed. */
813
814
uFlags = pThread->uFlags; /* Return handed-in execution flags back to the host. */
815
816
else if (fProcessAlive)
817
VBoxServiceError("ControlThread: [PID %u]: Is alive when it should not!\n",
818
VBoxServiceError("[PID %u]: Is alive when it should not!\n",
820
821
else if (MsProcessKilled != UINT64_MAX)
822
VBoxServiceError("ControlThread: [PID %u]: Has been killed when it should not!\n",
823
VBoxServiceError("[PID %u]: Has been killed when it should not!\n",
825
826
else if (ProcessStatus.enmReason == RTPROCEXITREASON_NORMAL)
827
VBoxServiceVerbose(3, "ControlThread: [PID %u]: Ended with RTPROCEXITREASON_NORMAL (Exit code: %u)\n",
828
VBoxServiceVerbose(3, "[PID %u]: Ended with RTPROCEXITREASON_NORMAL (Exit code: %u)\n",
828
829
pThread->uPID, ProcessStatus.iStatus);
830
831
uStatus = PROC_STS_TEN;
841
842
else if (ProcessStatus.enmReason == RTPROCEXITREASON_ABEND)
843
844
/* ProcessStatus.iStatus will be undefined. */
844
VBoxServiceVerbose(3, "ControlThread: [PID %u]: Ended with RTPROCEXITREASON_ABEND\n",
845
VBoxServiceVerbose(3, "[PID %u]: Ended with RTPROCEXITREASON_ABEND\n",
847
848
uStatus = PROC_STS_TEA;
848
849
uFlags = ProcessStatus.iStatus;
851
VBoxServiceVerbose(1, "ControlThread: [PID %u]: Handling process status %u not implemented\n",
852
VBoxServiceVerbose(1, "[PID %u]: Handling process status %u not implemented\n",
852
853
pThread->uPID, ProcessStatus.enmReason);
854
VBoxServiceVerbose(2, "ControlThread: [PID %u]: Ended, ClientID=%u, CID=%u, Status=%u, Flags=0x%x\n",
855
VBoxServiceVerbose(2, "[PID %u]: Ended, ClientID=%u, CID=%u, Status=%u, Flags=0x%x\n",
855
856
pThread->uPID, pThread->uClientID, pThread->uContextID, uStatus, uFlags);
856
857
rc = VbglR3GuestCtrlExecReportStatus(pThread->uClientID, pThread->uContextID,
857
858
pThread->uPID, uStatus, uFlags,
858
859
NULL /* pvData */, 0 /* cbData */);
859
860
if (RT_FAILURE(rc))
860
VBoxServiceError("ControlThread: [PID %u]: Error reporting final status to host; rc=%Rrc\n",
861
VBoxServiceError("[PID %u]: Error reporting final status to host; rc=%Rrc\n",
861
862
pThread->uPID, rc);
863
VBoxServiceVerbose(3, "ControlThread: [PID %u]: Process loop ended with rc=%Rrc\n",
864
VBoxServiceVerbose(3, "[PID %u]: Process loop ended with rc=%Rrc\n",
864
865
pThread->uPID, rc);
867
VBoxServiceError("ControlThread: [PID %u]: Loop failed with rc=%Rrc\n",
868
VBoxServiceError("[PID %u]: Loop failed with rc=%Rrc\n",
868
869
pThread->uPID, rc);
1010
1011
int rc = RTSemEventMultiWait(pReq->Event, RT_INDEFINITE_WAIT);
1011
1012
if (RT_SUCCESS(rc))
1013
VBoxServiceVerbose(4, "ControlThread: Performed request with rc=%Rrc, cbData=%u\n",
1014
VBoxServiceVerbose(4, "Performed request with rc=%Rrc, cbData=%u\n",
1014
1015
pReq->rc, pReq->cbData);
1016
1017
/* Give back overall request result. */
1020
VBoxServiceError("ControlThread: Waiting for request failed, rc=%Rrc\n", rc);
1021
VBoxServiceError("Waiting for request failed, rc=%Rrc\n", rc);
1128
1129
* Resolves the full path of a specified executable name. This function also
1129
* resolves internal VBoxService tools to its appropriate executable path + name.
1130
* resolves internal VBoxService tools to its appropriate executable path + name if
1131
* VBOXSERVICE_NAME is specified as pszFileName.
1131
1133
* @return IPRT status code.
1132
* @param pszFileName File name to resovle.
1134
* @param pszFileName File name to resolve.
1133
1135
* @param pszResolved Pointer to a string where the resolved file name will be stored.
1134
1136
* @param cbResolved Size (in bytes) of resolved file name string.
1136
1138
static int VBoxServiceControlThreadResolveExecutable(const char *pszFileName,
1137
1139
char *pszResolved, size_t cbResolved)
1141
AssertPtrReturn(pszFileName, VERR_INVALID_POINTER);
1142
AssertPtrReturn(pszResolved, VERR_INVALID_POINTER);
1143
AssertReturn(cbResolved, VERR_INVALID_PARAMETER);
1139
1145
int rc = VINF_SUCCESS;
1141
/* Search the path of our executable. */
1142
char szVBoxService[RTPATH_MAX];
1143
if (RTProcGetExecutablePath(szVBoxService, sizeof(szVBoxService)))
1145
char *pszExecResolved = NULL;
1146
if ( (g_pszProgName && RTStrICmp(pszFileName, g_pszProgName) == 0)
1147
|| !RTStrICmp(pszFileName, VBOXSERVICE_NAME))
1149
/* We just want to execute VBoxService (no toolbox). */
1150
pszExecResolved = RTStrDup(szVBoxService);
1152
else /* Nothing to resolve, copy original. */
1153
pszExecResolved = RTStrDup(pszFileName);
1154
AssertPtr(pszExecResolved);
1156
rc = VBoxServiceControlThreadMakeFullPath(pszExecResolved, pszResolved, cbResolved);
1158
VBoxServiceVerbose(3, "ControlThread: VBoxServiceControlExecResolveExecutable: %s -> %s\n",
1159
pszFileName, pszResolved);
1161
RTStrFree(pszExecResolved);
1147
char szPathToResolve[RTPATH_MAX];
1148
if ( (g_pszProgName && (RTStrICmp(pszFileName, g_pszProgName) == 0))
1149
|| !RTStrICmp(pszFileName, VBOXSERVICE_NAME))
1151
/* Resolve executable name of this process. */
1152
if (!RTProcGetExecutablePath(szPathToResolve, sizeof(szPathToResolve)))
1153
rc = VERR_FILE_NOT_FOUND;
1157
/* Take the raw argument to resolve. */
1158
rc = RTStrCopy(szPathToResolve, sizeof(szPathToResolve), pszFileName);
1163
rc = VBoxServiceControlThreadMakeFullPath(szPathToResolve, pszResolved, cbResolved);
1165
VBoxServiceVerbose(3, "Looked up executable: %s -> %s\n",
1166
pszFileName, pszResolved);
1170
VBoxServiceError("Failed to lookup executable \"%s\" with rc=%Rrc\n",
1169
1178
* and relative paths.
1171
1180
* @return IPRT status code.
1172
* @param pszArgv0 First argument (argv0), either original or modified version.
1181
* @param pszArgv0 First argument (argv0), either original or modified version. Optional.
1173
1182
* @param papszArgs Original argv command line from the host, starting at argv[1].
1174
1183
* @param ppapszArgv Pointer to a pointer with the new argv command line.
1175
1184
* Needs to be freed with RTGetOptArgvFree.
1246
1260
* (usually, if started by SCM) has administrator rights. Because of that a UI
1247
1261
* won't be shown (doesn't have a desktop).
1249
if (RTStrICmp(pszExec, "sysprep") == 0)
1263
if (!RTStrICmp(pszExec, "sysprep"))
1251
1265
/* Use a predefined sysprep path as default. */
1252
1266
char szSysprepCmd[RTPATH_MAX] = "C:\\sysprep\\sysprep.exe";
1325
1348
if (*pszAsUser)
1326
1349
uProcFlags |= RTPROC_FLAGS_SERVICE;
1328
VBoxServiceVerbose(3, "ControlThread: Command: %s\n", szExecExp);
1351
VBoxServiceVerbose(3, "Command: %s\n", szExecExp);
1329
1352
for (size_t i = 0; papszArgsExp[i]; i++)
1330
VBoxServiceVerbose(3, "ControlThread:\targv[%ld]: %s\n", i, papszArgsExp[i]);
1353
VBoxServiceVerbose(3, "\targv[%ld]: %s\n", i, papszArgsExp[i]);
1355
VBoxServiceVerbose(3, "Starting process \"%s\" ...\n", szExecExp);
1332
1357
/* Do normal execution. */
1333
1358
rc = RTProcCreateEx(szExecExp, papszArgsExp, hEnv, uProcFlags,
1334
1359
phStdIn, phStdOut, phStdErr,
1335
1360
*pszAsUser ? pszAsUser : NULL,
1336
1361
*pszPassword ? pszPassword : NULL,
1364
VBoxServiceVerbose(3, "Starting process \"%s\" returned rc=%Rrc\n",
1338
1367
RTGetOptArgvFree(papszArgsExp);
1350
1379
static int VBoxServiceControlThreadProcessWorker(PVBOXSERVICECTRLTHREAD pThread)
1352
1381
AssertPtrReturn(pThread, VERR_INVALID_POINTER);
1353
VBoxServiceVerbose(3, "ControlThread: Thread of process \"%s\" started\n", pThread->pszCmd);
1382
VBoxServiceVerbose(3, "Thread of process pThread=0x%p = \"%s\" started\n",
1383
pThread, pThread->pszCmd);
1355
1385
int rc = VBoxServiceControlListSet(VBOXSERVICECTRLTHREADLIST_RUNNING, pThread);
1358
1388
rc = VbglR3GuestCtrlConnect(&pThread->uClientID);
1359
1389
if (RT_FAILURE(rc))
1361
VBoxServiceError("ControlThread: Thread failed to connect to the guest control service, aborted! Error: %Rrc\n", rc);
1391
VBoxServiceError("Thread failed to connect to the guest control service, aborted! Error: %Rrc\n", rc);
1362
1392
RTThreadUserSignal(RTThreadSelf());
1365
VBoxServiceVerbose(3, "ControlThread: Guest process \"%s\" got client ID=%u, flags=0x%x\n",
1395
VBoxServiceVerbose(3, "Guest process \"%s\" got client ID=%u, flags=0x%x\n",
1366
1396
pThread->pszCmd, pThread->uClientID, pThread->uFlags);
1368
1398
bool fSignalled = false; /* Indicator whether we signalled the thread user event already. */
1447
1477
pThread->pszUser, pThread->pszPassword,
1449
1479
if (RT_FAILURE(rc))
1450
VBoxServiceError("ControlThread: Error starting process, rc=%Rrc\n", rc);
1480
VBoxServiceError("Error starting process, rc=%Rrc\n", rc);
1452
1482
* Tell the control thread that it can continue
1453
1483
* spawning services. This needs to be done after the new
1534
1564
PROC_STS_ERROR, rc,
1535
1565
NULL /* pvData */, 0 /* cbData */);
1536
1566
if (RT_FAILURE(rc2))
1537
VBoxServiceError("ControlThread: Could not report process failure error; rc=%Rrc (process error %Rrc)\n",
1567
VBoxServiceError("Could not report process failure error; rc=%Rrc (process error %Rrc)\n",
1541
VBoxServiceVerbose(3, "ControlThread: [PID %u]: Cancelling pending host requests (client ID=%u)\n",
1571
VBoxServiceVerbose(3, "[PID %u]: Cancelling pending host requests (client ID=%u)\n",
1542
1572
pThread->uPID, pThread->uClientID);
1543
1573
rc2 = VbglR3GuestCtrlCancelPendingWaits(pThread->uClientID);
1544
1574
if (RT_FAILURE(rc2))
1546
VBoxServiceError("ControlThread: [PID %u]: Cancelling pending host requests failed; rc=%Rrc\n",
1576
VBoxServiceError("[PID %u]: Cancelling pending host requests failed; rc=%Rrc\n",
1547
1577
pThread->uPID, rc2);
1548
1578
if (RT_SUCCESS(rc))
1552
1582
/* Disconnect from guest control service. */
1553
VBoxServiceVerbose(3, "ControlThread: [PID %u]: Disconnecting (client ID=%u) ...\n",
1583
VBoxServiceVerbose(3, "[PID %u]: Disconnecting (client ID=%u) ...\n",
1554
1584
pThread->uPID, pThread->uClientID);
1555
1585
VbglR3GuestCtrlDisconnect(pThread->uClientID);
1556
1586
pThread->uClientID = 0;
1559
VBoxServiceVerbose(3, "ControlThread: [PID %u]: Thread of process \"%s\" ended with rc=%Rrc\n",
1589
VBoxServiceVerbose(3, "[PID %u]: Thread of process \"%s\" ended with rc=%Rrc\n",
1560
1590
pThread->uPID, pThread->pszCmd, rc);
1562
1592
/* Update started/stopped status. */
1621
1651
RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "gctl%u", s_uCtrlExecThread);
1622
1652
if (RT_FAILURE(rc))
1624
VBoxServiceError("ControlThread: RTThreadCreate failed, rc=%Rrc\n, pThread=%p\n",
1654
VBoxServiceError("RTThreadCreate failed, rc=%Rrc\n, pThread=%p\n",
1629
VBoxServiceVerbose(4, "ControlThread: Waiting for thread to initialize ...\n");
1659
VBoxServiceVerbose(4, "Waiting for thread to initialize ...\n");
1631
1661
/* Wait for the thread to initialize. */
1632
1662
rc = RTThreadUserWait(pThread->Thread, 60 * 1000 /* 60 seconds max. */);
1690
1720
if ( RT_SUCCESS(rc)
1693
VBoxServiceVerbose(3, "ControlThread: [PID %u]: Waiting for response on enmType=%u, pvData=0x%p, cbData=%u\n",
1723
VBoxServiceVerbose(3, "[PID %u]: Waiting for response on enmType=%u, pvData=0x%p, cbData=%u\n",
1694
1724
uPID, pRequest->enmType, pRequest->pvData, pRequest->cbData);
1696
1726
rc = VBoxServiceControlThreadRequestWait(pRequest);
1702
1732
else /* PID not found! */
1703
1733
rc = VERR_NOT_FOUND;
1705
VBoxServiceVerbose(3, "ControlThread: [PID %u]: Performed enmType=%u, uCID=%u, pvData=0x%p, cbData=%u, rc=%Rrc\n",
1735
VBoxServiceVerbose(3, "[PID %u]: Performed enmType=%u, uCID=%u, pvData=0x%p, cbData=%u, rc=%Rrc\n",
1706
1736
uPID, pRequest->enmType, pRequest->uCID, pRequest->pvData, pRequest->cbData, rc);