- Timestamp:
- Apr 3, 2009 8:15:26 PM (16 years ago)
- Location:
- trunk/src/VBox/Additions/common/VBoxService
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp
r18672 r18712 1 /* *$Id$ */1 /* $Id$ */ 2 2 /** @file 3 3 * VBoxService - Guest Additions Service Skeleton. … … 5 5 6 6 /* 7 * Copyright (C) 200 9 Sun Microsystems, Inc.7 * Copyright (C) 2007-2009 Sun Microsystems, Inc. 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 25 25 * Header Files * 26 26 *******************************************************************************/ 27 /** @todo LOG_GROUP*/ 27 28 #ifndef _MSC_VER 28 29 # include <unistd.h> … … 40 41 #include "VBoxServiceInternal.h" 41 42 43 42 44 /******************************************************************************* 43 45 * Global Variables * 44 46 *******************************************************************************/ 45 47 /** The program name (derived from argv[0]). */ 46 char *g_pszProgName ;48 char *g_pszProgName = (char *)""; 47 49 /** The current verbosity level. */ 48 50 int g_cVerbosity = 0; 49 51 /** The default service interval (the -i | --interval) option). */ 50 52 uint32_t g_DefaultInterval = 0; 51 /** Shutdown the main thread. (later, for signals ).*/53 /** Shutdown the main thread. (later, for signals.) */ 52 54 bool volatile g_fShutdown; 53 55 … … 90 92 static int VBoxServiceUsage(void) 91 93 { 92 RTPrintf("usage: %s [-f|--foreground] [-i|--interval <seconds>]" 93 " [--disable-<service>] [--enable-<service>] [-h|-?|--help] [-v|--verbose]", g_pszProgName); 94 95 #if defined(RT_OS_WINDOWS) 96 RTPrintf(" [-r|--register] [-u|--unregister]"); 97 #endif 98 99 for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++) 100 RTPrintf(" %s\n", g_aServices[j].pDesc->pszUsage); 101 94 RTPrintf("usage: %s [-f|--foreground] [-v|--verbose] [-i|--interval <seconds>]\n" 95 " [--disable-<service>] [--enable-<service>] [-h|-?|--help]\n", g_pszProgName); 96 #ifdef RT_OS_WINDOWS 97 RTPrintf(" [-r|--register] [-u|--unregister]\n"); 98 #endif 99 for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++) 100 RTPrintf(" %s\n", g_aServices[j].pDesc->pszUsage); 102 101 RTPrintf("\n" 103 102 "Options:\n" 104 #if !defined(RT_OS_WINDOWS)105 " -h | -? | --help Show this message and exit with status 1.\n"106 #else107 " -h | -? | /? | --help Show this message and exit with status 1.\n"108 #endif109 103 " -i | --interval The default interval.\n" 110 104 " -f | --foreground Don't daemonzie the program. For debugging.\n" 111 #if defined(RT_OS_WINDOWS) 112 " -r | --register Installs the service.\n" 113 " -u | --unregister Uninstall service.\n" 114 #endif 115 " -v | --verbose Increment the verbosity level. For debugging.\n"); 105 " -v | --verbose Increment the verbosity level. For debugging.\n" 106 " -h | -? | --help Show this message and exit with status 1.\n" 107 ); 108 #ifdef RT_OS_WINDOWS 109 RTPrintf(" -r | --register Installs the service.\n" 110 " -u | --unregister Uninstall service.\n"); 111 #endif 116 112 117 113 RTPrintf("\n" … … 159 155 int VBoxServiceError(const char *pszFormat, ...) 160 156 { 161 char szBuffer[1024] = { 0 };162 157 RTStrmPrintf(g_pStdErr, "%s: error: ", g_pszProgName); 163 158 … … 165 160 va_start(va, pszFormat); 166 161 RTStrmPrintfV(g_pStdErr, pszFormat, va); 167 168 RTStrPrintfV(szBuffer, sizeof(szBuffer), pszFormat, va);169 LogRel((szBuffer));170 171 162 va_end(va); 163 164 #if 0 /* enable after 2.2 */ 165 va_start(va, pszFormat); 166 LogRel(("%s: error: %N", g_pszProgName, pszFormat, &va)); 167 va_end(va); 168 #endif 172 169 173 170 return 1; … … 190 187 va_start(va, pszFormat); 191 188 RTStrmPrintfV(g_pStdOut, pszFormat, va); 192 193 #ifdef _DEBUG194 char szBuffer[1024] = { 0 };195 RTStrPrintfV(szBuffer, sizeof(szBuffer), pszFormat, va);196 LogRel((szBuffer));197 #endif198 199 189 va_end(va); 190 191 #if 0 /* enable after 2.2 */ 192 Log(("%s: %N", g_pszProgName, pszFormat, &va)); 193 #endif 200 194 } 201 195 } … … 252 246 } 253 247 254 int VBoxServiceStartServices(int iMain) 255 { 256 int rc = 0; 248 249 /** 250 * Starts the service. 251 * 252 * @returns VBox status code, errors are fully bitched. 253 * 254 * @param iMain The index of the service that belongs to the main 255 * thread. Pass ~0U if none does. 256 */ 257 int VBoxServiceStartServices(unsigned iMain) 258 { 259 int rc; 257 260 258 261 /* … … 263 266 rc = g_aServices[j].pDesc->pfnInit(); 264 267 if (RT_FAILURE(rc)) 265 return VBoxServiceError("Service '%s' failed pre-init: %Rrc\n", g_aServices[j].pDesc->pszName);266 }267 268 if (iMain == 0) /* If 0 is specified, start all services. Useful for the Windows SCM stuff. */269 iMain = RT_ELEMENTS(g_aServices);268 { 269 VBoxServiceError("Service '%s' failed pre-init: %Rrc\n", g_aServices[j].pDesc->pszName); 270 return rc; 271 } 272 } 270 273 271 274 /* 272 275 * Start the service(s). 273 276 */ 277 rc = VINF_SUCCESS; 274 278 for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++) 275 279 { … … 303 307 } 304 308 305 /* 309 310 /** 306 311 * Stops and terminates the services. 307 */ 308 int VBoxServiceStopServices() 309 { 310 int rc = 0; 312 * 313 * This should be called even when VBoxServiceStartServices fails so it can 314 * clean up anything that we succeeded in starting. 315 */ 316 void VBoxServiceStopServices(void) 317 { 311 318 for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++) 312 319 ASMAtomicXchgBool(&g_aServices[j].fShutdown, true); … … 318 325 if (g_aServices[j].Thread != NIL_RTTHREAD) 319 326 { 320 rc = RTThreadWait(g_aServices[j].Thread, 30*1000, NULL);327 int rc = RTThreadWait(g_aServices[j].Thread, 30*1000, NULL); 321 328 if (RT_FAILURE(rc)) 322 329 VBoxServiceError("service '%s' failed to stop. (%Rrc)\n", g_aServices[j].pDesc->pszName, rc); … … 324 331 g_aServices[j].pDesc->pfnTerm(); 325 332 } 326 327 return rc; 328 } 333 } 334 329 335 330 336 int main(int argc, char **argv) 331 337 { 332 int rc = 0; 333 334 #if defined(RT_OS_WINDOWS) 338 int rc; 339 340 /* 341 * Init globals and such. 342 */ 343 RTR3Init(); 344 g_pszProgName = RTPathFilename(argv[0]); 345 for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++) 346 { 347 rc = g_aServices[j].pDesc->pfnPreInit(); 348 if (RT_FAILURE(rc)) 349 return VBoxServiceError("Service '%s' failed pre-init: %Rrc\n", g_aServices[j].pDesc->pszName); 350 } 351 352 #ifdef RT_OS_WINDOWS 353 /* 354 * Explain the purpose of this exercise and why ignoring the result is a good idea and everything. 355 */ 335 356 /* Do not use a global namespace ("Global\\") for mutex name here, will blow up NT4 compatibility! */ 336 357 HANDLE hMutexAppRunning = CreateMutex (NULL, FALSE, VBOXSERVICE_NAME); 337 if ( (hMutexAppRunning != NULL)338 && (GetLastError() == ERROR_ALREADY_EXISTS))358 if ( hMutexAppRunning != NULL 359 && GetLastError() == ERROR_ALREADY_EXISTS) 339 360 { 340 361 VBoxServiceError("%s is already running! Terminating.", g_pszProgName); … … 347 368 348 369 /* 349 * Init globals and such.350 */351 RTR3Init();352 g_pszProgName = RTPathFilename(argv[0]);353 for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++)354 {355 rc = g_aServices[j].pDesc->pfnPreInit();356 if (RT_FAILURE(rc))357 return VBoxServiceError("Service '%s' failed pre-init: %Rrc\n", g_aServices[j].pDesc->pszName);358 }359 360 /*361 370 * Parse the arguments. 362 371 */ … … 366 375 { 367 376 const char *psz = argv[i]; 368 if( (*psz != '-') 369 #if defined(RT_OS_WINDOWS) 370 && (*psz != '/') 371 #endif 372 ) 377 if (*psz != '-') 373 378 return VBoxServiceSyntax("Unknown argument '%s'\n", psz); 374 379 psz++; … … 389 394 else if (MATCHES("interval")) 390 395 psz = "i"; 391 #if defined(RT_OS_WINDOWS)396 #ifdef RT_OS_WINDOWS 392 397 else if (MATCHES("register")) 393 398 psz = "r"; … … 452 457 break; 453 458 454 #if defined(RT_OS_WINDOWS) 459 case 'h': 460 case '?': 461 return VBoxServiceUsage(); 462 463 #ifdef RT_OS_WINDOWS 455 464 case 'r': 456 465 return VBoxServiceWinInstall(); … … 459 468 return VBoxServiceWinUninstall(); 460 469 #endif 461 462 case 'h':463 #if defined(RT_OS_WINDOWS)464 case '?':465 #endif466 return VBoxServiceUsage();467 470 468 471 default: … … 513 516 if (fDaemonize && !fDaemonzied) 514 517 { 518 #ifdef RT_OS_WINDOWS 519 /** @todo Should do something like VBoxSVC here, OR automatically re-register 520 * the service and start it. Involving VbglR3Daemonize isn't an option 521 * here. 522 * 523 * Also, the idea here, IIRC, was to map the sub service to windows 524 * services. The todo below is for mimicking windows services on 525 * non-windows systems. Not sure if this is doable or not, but in anycase 526 * this code can be moved into -win. 527 * 528 * You should return when StartServiceCtrlDispatcher, btw., not 529 * continue. 530 */ 531 if (!StartServiceCtrlDispatcher(&g_aServiceTable[0])) 532 return VBoxServiceError("StartServiceCtrlDispatcher: %u\n", GetLastError()); 533 534 #else 515 535 VBoxServiceVerbose(1, "Daemonizing...\n"); 516 #if defined(RT_OS_WINDOWS)517 /** @todo Replace StartServiceCtrlDispatcher() with518 VbglR3Daemonize() once this has been ported519 to Windows later. */520 StartServiceCtrlDispatcher (gs_serviceTable);521 #else522 536 rc = VbglR3Daemonize(false /* fNoChDir */, false /* fNoClose */); 523 537 if (RT_FAILURE(rc)) … … 529 543 /** @todo Make the main thread responsive to signal so it can shutdown/restart the threads on non-SIGKILL signals. */ 530 544 531 rc = VBoxServiceStartServices(iMain); 532 533 # if defined(RT_OS_WINDOWS)534 if (fDaemonize && fDaemonzied)535 {536 while (1) {537 Sleep (100); /** @todo*/538 }539 }540 #endif 541 542 rc = VBoxServiceStopServices(); 543 544 #if defined(RT_OS_WINDOWS) 545 /* Release instance mutex. */546 if (hMutexAppRunning != NULL) {547 CloseHandle (hMutexAppRunning);548 hMutexAppRunning = NULL;549 } 550 #endif 551 return rc;552 } 553 545 #ifdef RT_OS_WINDOWS 546 if (not using StartServiceCtrlDispatcher or auto register & starting the service) 547 #endif 548 { 549 /* 550 * Start the service, enter the main threads run loop and stop them again when it returns. 551 */ 552 rc = VBoxServiceStartServices(iMain); 553 VBoxServiceStopServices(); 554 } 555 556 557 #ifdef RT_OS_WINDOWS 558 /* 559 * Release instance mutex if we got it. 560 */ 561 if (hMutexAppRunning != NULL) 562 CloseHandle(hMutexAppRunning); 563 #endif 564 565 return RT_SUCCESS(rc) ? 0 : 1; 566 } 567 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
r18670 r18712 5 5 6 6 /* 7 * Copyright (C) 200 9 Sun Microsystems, Inc.7 * Copyright (C) 2007-2009 Sun Microsystems, Inc. 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 23 23 #define ___VBoxServiceInternal_h 24 24 25 #if defined(RT_OS_WINDOWS)26 #include <windows.h>27 #include <tchar.h> 28 #include <process.h> 25 #ifdef RT_OS_WINDOWS 26 # include <Windows.h> 27 # include <tchar.h> /**@todo just drop this, this will be compiled as UTF-8/ANSI. */ 28 # include <process.h> /**@todo what's this here for? */ 29 29 #endif 30 30 31 /** Name of this program. */ 32 #if !defined(RT_OS_WINDOWS) 33 #define VBOXSERVICE_NAME "VBoxService" 34 #define VBOXSERVICE_FRIENDLY_NAME "VBoxService" 35 #else 36 #define VBOXSERVICE_NAME _T("VBoxService") 37 #define VBOXSERVICE_FRIENDLY_NAME _T("VBoxService") 38 #endif 31 /** @todo just move this into the windows specific code, it's not needed 32 * here. */ 33 /** The service name. */ 34 #define VBOXSERVICE_NAME "VBoxService" 35 /** The friendly service name. */ 36 #define VBOXSERVICE_FRIENDLY_NAME "VBoxService" 39 37 40 38 /** … … 106 104 extern int g_cVerbosity; 107 105 extern uint32_t g_DefaultInterval; 106 /** Windows SCM stuff. 107 * @todo document each of them individually, this comment only documents 108 * g_vboxServiceStatusCode on windows. On the other platforms it will be 109 * dangling. 110 * @todo all this should be moved to -win.cpp and exposed via functions. */ 111 #ifdef RT_OS_WINDOWS 112 extern DWORD g_vboxServiceStatusCode; /** @todo g_rcWinService */ 113 extern SERVICE_STATUS_HANDLE g_vboxServiceStatusHandle; /** @todo g_hWinServiceStatus */ 114 extern SERVICE_TABLE_ENTRY const g_aServiceTable[]; /** @todo generate on the fly, see comment in main() from the enabled sub services. */ 115 #endif 108 116 109 117 extern int VBoxServiceSyntax(const char *pszFormat, ...); … … 111 119 extern void VBoxServiceVerbose(int iLevel, const char *pszFormat, ...); 112 120 extern int VBoxServiceArgUInt32(int argc, char **argv, const char *psz, int *pi, uint32_t *pu32, uint32_t u32Min, uint32_t u32Max); 113 extern int VBoxServiceStartServices(int iMain); 114 extern int VBoxServiceStopServices(); 115 116 #if defined(RT_OS_WINDOWS) 117 extern int VBoxServiceWinInstall (); 118 extern int VBoxServiceWinUninstall (); 121 extern int VBoxServiceStartServices(unsigned iMain); 122 extern void VBoxServiceStopServices(void); 123 #ifdef RT_OS_WINDOWS 124 extern int VBoxServiceWinInstall(void); 125 extern int VBoxServiceWinUninstall(void); 119 126 #endif 120 127 … … 123 130 extern VBOXSERVICE g_Control; 124 131 125 /** Windows SCM stuff. */126 #if defined(RT_OS_WINDOWS)127 extern DWORD g_vboxServiceStatusCode;128 extern SERVICE_STATUS_HANDLE g_vboxServiceStatusHandle;129 extern SERVICE_TABLE_ENTRY const gs_serviceTable[];130 #endif131 132 132 __END_DECLS 133 133 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceTimeSync.cpp
r18679 r18712 116 116 static uint32_t g_TimeSyncMinAdjust = 1000; 117 117 #else 118 #if RT_OS_WINDOWS 119 /** Process token. */ 120 static HANDLE g_hTokenProcess = NULL; 121 /* Old token privileges. */ 122 static TOKEN_PRIVILEGES g_tpOld; 123 static uint32_t g_TimeSyncMinAdjust = 100; 124 #else 125 static uint32_t g_TimeSyncMinAdjust = 100; 126 #endif 118 static uint32_t g_TimeSyncMinAdjust = 100; 127 119 #endif 128 120 /** @see pg_vboxservice_timesync */ … … 133 125 /** The semaphore we're blocking on. */ 134 126 static RTSEMEVENTMULTI g_TimeSyncEvent = NIL_RTSEMEVENTMULTI; 127 128 #ifdef RT_OS_WINDOWS 129 /** Process token. */ 130 static HANDLE g_hTokenProcess = NULL; 131 /** Old token privileges. */ 132 static TOKEN_PRIVILEGES g_OldTokenPrivileges; 133 #endif 134 135 135 136 136 /** @copydoc VBOXSERVICE::pfnPreInit */ … … 166 166 static DECLCALLBACK(int) VBoxServiceTimeSyncInit(void) 167 167 { 168 int rc = VINF_SUCCESS;169 170 168 /* 171 169 * If not specified, find the right interval default. … … 177 175 g_TimeSyncInterval = 10 * 1000; 178 176 179 rc = RTSemEventMultiCreate(&g_TimeSyncEvent);177 int rc = RTSemEventMultiCreate(&g_TimeSyncEvent); 180 178 AssertRC(rc); 181 182 #if defined(RT_OS_WINDOWS) 183 /* Adjust priviledges of this process to adjust the time. */ 184 TOKEN_PRIVILEGES tp; /* Token provileges. */ 185 DWORD dwSize = sizeof (TOKEN_PRIVILEGES); 186 LUID luid = {0}; 187 188 if (!OpenProcessToken(GetCurrentProcess(), 189 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &g_hTokenProcess)) 179 #ifdef RT_OS_WINDOWS 180 if (RT_SUCCESS(rc)) 190 181 { 191 VBoxServiceError("Opening process token (SE_SYSTEMTIME_NAME) failed with code %ld!\n", GetLastError()); 192 rc = VERR_PERMISSION_DENIED; 193 } 194 else 195 { 196 if(!::LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &luid)) 182 /* 183 * Adjust priviledges of this process so we can make system time adjustments. 184 */ 185 if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &g_hTokenProcess)) 197 186 { 198 VBoxServiceError("Looking up token privileges (SE_SYSTEMTIME_NAME) failed with code %ld!\n", GetLastError()); 199 rc = VERR_PERMISSION_DENIED; 187 TOKEN_PRIVILEGES Tp; 188 RT_ZERO(Tp); 189 tp.PrivilegeCount = 1; 190 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 191 if (LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tp.Privileges[0].Luid)) 192 { 193 DWORD cbRet = sizeof(g_OldTokenPrivileges); 194 if (!AdjustTokenPrivileges(g_hTokenProcess, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &g_OldTokenPrivileges, &cbRet)) 195 { 196 DWORD dwErr = GetLastError(); 197 rc = RTErrConvertFromWin32(dwErr); 198 VBoxServiceError("Adjusting token privileges (SE_SYSTEMTIME_NAME) failed with status code %u/%Rrc!\n", dwErr, rc); 199 } 200 } 201 else 202 { 203 DWORD dwErr = GetLastError(); 204 rc = RTErrConvertFromWin32(dwErr); 205 VBoxServiceError("Looking up token privileges (SE_SYSTEMTIME_NAME) failed with status code %u/%Rrc!\n", dwErr, rc); 206 } 207 208 if (RT_FAILURE(rc)) 209 { 210 CloseHandle(g_hTokenProcess); 211 g_hTokenProcess = NULL; 212 } 200 213 } 201 202 ZeroMemory (&tp, sizeof (tp)); 203 tp.PrivilegeCount = 1; 204 tp.Privileges[0].Luid = luid; 205 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 206 207 /* Adjust Token privileges. */ 208 if (!::AdjustTokenPrivileges(g_hTokenProcess, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), 209 &g_tpOld, &dwSize)) 214 else 210 215 { 211 VBoxServiceError("Adjusting token privileges (SE_SYSTEMTIME_NAME) failed with code %ld!\n", GetLastError()); 212 rc = VERR_PERMISSION_DENIED; 216 DWORD dwErr = GetLastError(); 217 rc = RTErrConvertFromWin32(dwErr); 218 VBoxServiceError("Opening process token (SE_SYSTEMTIME_NAME) failed with status code %u/%Rrc!\n", dwErr, rc); 219 g_hTokenProcess = NULL; 213 220 } 214 221 } 215 #else 216 /* Nothing to do here yet. */ 217 #endif 218 219 #if defined(RT_OS_WINDOWS) 220 if (RT_FAILURE(rc)) 221 { 222 CloseHandle (g_hTokenProcess); 223 g_hTokenProcess = NULL; 224 } 225 #endif 222 #endif /* RT_OS_WINDOWS */ 226 223 227 224 return rc; … … 291 288 * *NIX systems have it. Fall back on settimeofday. 292 289 */ 293 #if defined(RT_OS_WINDOWS) 294 295 290 #ifdef RT_OS_WINDOWS 296 291 /* Just make sure it compiles for now, but later: 297 292 SetSystemTimeAdjustment and fall back on SetSystemTime. 298 293 */ 299 294 //AssertFatalFailed(); 300 #else 295 #else /* !RT_OS_WINDOWS */ 301 296 struct timeval tv; 302 # if !defined(RT_OS_OS2) /* PORTME */297 # if !defined(RT_OS_OS2) /* PORTME */ 303 298 RTTimeSpecGetTimeval(&Drift, &tv); 304 299 if (adjtime(&tv, NULL) == 0) … … 309 304 } 310 305 else 311 # endif306 # endif 312 307 { 313 308 errno = 0; … … 321 316 VBoxServiceVerbose(1, "settimeofday to %s\n", 322 317 RTTimeToString(RTTimeExplode(&Time, &Tmp), sz, sizeof(sz))); 323 # ifdef DEBUG318 # ifdef DEBUG 324 319 if (g_cVerbosity >= 3) 325 320 VBoxServiceVerbose(2, " new time %s\n", 326 321 RTTimeToString(RTTimeExplode(&Time, RTTimeNow(&Tmp)), sz, sizeof(sz))); 327 # endif322 # endif 328 323 cErrors = 0; 329 324 } … … 377 372 static DECLCALLBACK(void) VBoxServiceTimeSyncTerm(void) 378 373 { 379 #if defined(RT_OS_WINDOWS) 380 /* Disable SE_SYSTEMTIME_NAME again. */ 381 DWORD dwSize = sizeof (TOKEN_PRIVILEGES); 382 if (g_hTokenProcess && !::AdjustTokenPrivileges(g_hTokenProcess, FALSE, &g_tpOld, dwSize, NULL, NULL)) 383 VBoxServiceError("Adjusting back token privileges (SE_SYSTEMTIME_NAME) failed with code %ld!\n", GetLastError()); 374 #ifdef RT_OS_WINDOWS 375 /* 376 * Restore the SE_SYSTEMTIME_NAME token privileges (if init succeeded). 377 */ 378 if (g_hTokenProcess) 379 { 380 if (!AdjustTokenPrivileges(g_hTokenProcess, FALSE, &g_tpOld, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) 381 { 382 DWORD dwErr = GetLastError(); 383 VBoxServiceError("Restoring token privileges (SE_SYSTEMTIME_NAME) failed with code %u!\n", dwErr); 384 } 385 CloseHandle(g_hTokenProcess); 386 g_hTokenProcess = NULL; 387 } 384 388 #endif 385 389 386 RTSemEventMultiDestroy(g_TimeSyncEvent); 387 g_TimeSyncEvent = NIL_RTSEMEVENTMULTI; 390 if (g_TimeSyncEvent != NIL_RTSEMEVENTMULTI) 391 { 392 RTSemEventMultiDestroy(g_TimeSyncEvent); 393 g_TimeSyncEvent = NIL_RTSEMEVENTMULTI; 394 } 388 395 } 389 396
Note:
See TracChangeset
for help on using the changeset viewer.