Changeset 29817 in vbox
- Timestamp:
- May 26, 2010 1:54:41 PM (15 years ago)
- Location:
- trunk/src/VBox/Additions/common/VBoxService
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxService-win.cpp
r29762 r29817 5 5 6 6 /* 7 * Copyright (C) 2009 Oracle Corporation7 * Copyright (C) 2009-2010 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 29 29 #include <aclapi.h> 30 30 31 DWORD g_rcWinService = 0; 31 32 /******************************************************************************* 33 * Internal Functions * 34 *******************************************************************************/ 35 static void WINAPI vboxServiceWinMain(DWORD argc, LPTSTR *argv); 36 37 38 /******************************************************************************* 39 * Global Variables * 40 *******************************************************************************/ 41 static DWORD g_dwWinServiceLastStatus = 0; 32 42 SERVICE_STATUS_HANDLE g_hWinServiceStatus = NULL; 33 43 /** The semaphore for the dummy Windows service. */ 34 44 static RTSEMEVENT g_WindowsEvent = NIL_RTSEMEVENT; 35 45 36 void WINAPI VBoxServiceWinMain (DWORD argc, LPTSTR *argv); 37 38 static SERVICE_TABLE_ENTRY const g_aServiceTable[]= 39 { 40 {VBOXSERVICE_NAME, VBoxServiceWinMain}, 41 {NULL,NULL} 46 static SERVICE_TABLE_ENTRY const g_aServiceTable[] = 47 { 48 { VBOXSERVICE_NAME, vboxServiceWinMain }, 49 { NULL, NULL} 42 50 }; 43 51 … … 48 56 * @todo Add event log capabilities / check return values. 49 57 */ 50 DWORD VBoxServiceWinAddAceToObjectsSecurityDescriptor(LPTSTR pszObjName,51 SE_OBJECT_TYPE ObjectType,52 LPTSTR pszTrustee,53 TRUSTEE_FORM TrusteeForm,54 DWORD dwAccessRights,55 ACCESS_MODE AccessMode,56 DWORD dwInheritance)58 static DWORD vboxServiceWinAddAceToObjectsSecurityDescriptor(LPTSTR pszObjName, 59 SE_OBJECT_TYPE ObjectType, 60 LPTSTR pszTrustee, 61 TRUSTEE_FORM TrusteeForm, 62 DWORD dwAccessRights, 63 ACCESS_MODE AccessMode, 64 DWORD dwInheritance) 57 65 { 58 66 DWORD dwRes = 0; … … 74 82 else 75 83 VBoxServiceError("AddAceToObjectsSecurityDescriptor: GetNamedSecurityInfo: Error %u\n", dwRes); 76 goto Cleanup;84 goto l_Cleanup; 77 85 } 78 86 … … 90 98 { 91 99 VBoxServiceError("AddAceToObjectsSecurityDescriptor: SetEntriesInAcl: Error %u\n", dwRes); 92 goto Cleanup;100 goto l_Cleanup; 93 101 } 94 102 … … 100 108 { 101 109 VBoxServiceError("AddAceToObjectsSecurityDescriptor: SetNamedSecurityInfo: Error %u\n", dwRes); 102 goto Cleanup;110 goto l_Cleanup; 103 111 } 104 112 105 113 /** @todo get rid of that spaghetti jump ... */ 106 Cleanup:114 l_Cleanup: 107 115 108 116 if(pSD != NULL) … … 116 124 117 125 /** Reports our current status to the SCM. */ 118 BOOL VBoxServiceWinSetStatus(DWORD dwStatus, DWORD dwCheckPoint)119 { 120 if ( NULL == g_hWinServiceStatus) /* Program could be in testing mode, so no service environment available. */126 static BOOL vboxServiceWinSetStatus(DWORD dwStatus, DWORD dwCheckPoint) 127 { 128 if (g_hWinServiceStatus == NULL) /* Program could be in testing mode, so no service environment available. */ 121 129 return FALSE; 122 130 123 131 VBoxServiceVerbose(2, "Setting service status to: %ld\n", dwStatus); 124 g_ rcWinService= dwStatus;132 g_dwWinServiceLastStatus = dwStatus; 125 133 126 134 SERVICE_STATUS ss; 127 135 ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS; 128 ss.dwCurrentState = g_rcWinService;136 ss.dwCurrentState = dwStatus; 129 137 ss.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; 130 138 ss.dwWin32ExitCode = NO_ERROR; … … 137 145 138 146 139 int VBoxServiceWinSetDesc(SC_HANDLE hService) 140 { 147 /** 148 * Reports SERVICE_STOP_PENDING to SCM. 149 * 150 * @param uCheckPoint Some number. 151 */ 152 void VBoxServiceWinSetStopPendingStatus(uint32_t uCheckPoint) 153 { 154 vboxServiceWinSetStatus(SERVICE_STOP_PENDING, uCheckPoint); 155 } 156 157 158 static RTEXITCODE vboxServiceWinSetDesc(SC_HANDLE hService) 159 { 160 #ifndef TARGET_NT4 141 161 /* On W2K+ there's ChangeServiceConfig2() which lets us set some fields 142 162 like a longer service description. */ 143 #ifndef TARGET_NT4 163 /** @todo On Vista+ SERVICE_DESCRIPTION also supports localized strings! */ 144 164 SERVICE_DESCRIPTION desc; 145 /** @todo On Vista+ SERVICE_DESCRIPTION also supports localized strings! */ 146 desc. lpDescription = VBOXSERVICE_DESCRIPTION; 147 if (FALSE == ChangeServiceConfig2(hService, 148 SERVICE_CONFIG_DESCRIPTION, /* Service info level */ 149 &desc)) 165 desc.lpDescription = VBOXSERVICE_DESCRIPTION; 166 if (!ChangeServiceConfig2(hService, 167 SERVICE_CONFIG_DESCRIPTION, /* Service info level */ 168 &desc)) 150 169 { 151 170 VBoxServiceError("Cannot set the service description! Error: %ld\n", GetLastError()); 152 return 1; 153 } 154 #endif 155 return VINF_SUCCESS; 156 } 157 158 159 /** Installs the service into the registry. */ 160 int VBoxServiceWinInstall(void) 161 { 162 SC_HANDLE hService, hSCManager; 171 return RTEXITCODE_FAILURE; 172 } 173 #endif 174 return RTEXITCODE_SUCCESS; 175 } 176 177 178 /** 179 * Installs the service. 180 */ 181 RTEXITCODE VBoxServiceWinInstall(void) 182 { 183 VBoxServiceVerbose(1, "Installing service ...\n"); 184 163 185 TCHAR imagePath[MAX_PATH] = { 0 }; 164 165 GetModuleFileName(NULL,imagePath,MAX_PATH); 166 VBoxServiceVerbose(1, "Installing service ...\n"); 167 168 hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); 169 170 if (NULL == hSCManager) 186 GetModuleFileName(NULL, imagePath, sizeof(imagePath)); 187 188 SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); 189 if (hSCManager == NULL) 171 190 { 172 191 VBoxServiceError("Could not open SCM! Error: %ld\n", GetLastError()); 173 return 1; 174 } 175 176 hService = ::CreateService (hSCManager, 177 VBOXSERVICE_NAME, VBOXSERVICE_FRIENDLY_NAME, 178 SERVICE_ALL_ACCESS, 179 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, 180 SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, 181 imagePath, NULL, NULL, NULL, NULL, NULL); 182 int rc = VINF_SUCCESS; 183 if (NULL == hService) 192 return RTEXITCODE_FAILURE; 193 } 194 195 RTEXITCODE rc = RTEXITCODE_SUCCESS; 196 SC_HANDLE hService = CreateService(hSCManager, 197 VBOXSERVICE_NAME, VBOXSERVICE_FRIENDLY_NAME, 198 SERVICE_ALL_ACCESS, 199 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, 200 SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, 201 imagePath, NULL, NULL, NULL, NULL, NULL); 202 if (hService != NULL) 203 VBoxServiceVerbose(0, "Service successfully installed!\n"); 204 else 184 205 { 185 206 DWORD dwErr = GetLastError(); 186 207 switch (dwErr) 187 208 { 188 189 case ERROR_SERVICE_EXISTS: 190 191 VBoxServiceVerbose(1, "Service already exists, just updating the service config.\n"); 192 hService = OpenService (hSCManager, 193 VBOXSERVICE_NAME, 194 SERVICE_ALL_ACCESS); 195 if (NULL == hService) 196 { 197 VBoxServiceError("Could not open service! Error: %ld\n", GetLastError()); 198 rc = 1; 199 } 200 else 201 { 202 if (ChangeServiceConfig (hService, 203 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, 204 SERVICE_DEMAND_START, 205 SERVICE_ERROR_NORMAL, 206 imagePath, 207 NULL, 208 NULL, 209 NULL, 210 NULL, 211 NULL, 212 VBOXSERVICE_FRIENDLY_NAME)) 209 case ERROR_SERVICE_EXISTS: 210 VBoxServiceVerbose(1, "Service already exists, just updating the service config.\n"); 211 hService = OpenService(hSCManager, VBOXSERVICE_NAME, SERVICE_ALL_ACCESS); 212 if (hService) 213 213 { 214 VBoxServiceVerbose(1, "The service config has been successfully updated.\n"); 214 if (ChangeServiceConfig (hService, 215 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, 216 SERVICE_DEMAND_START, 217 SERVICE_ERROR_NORMAL, 218 imagePath, 219 NULL, 220 NULL, 221 NULL, 222 NULL, 223 NULL, 224 VBOXSERVICE_FRIENDLY_NAME)) 225 VBoxServiceVerbose(1, "The service config has been successfully updated.\n"); 226 else 227 rc = VBoxServiceError("Could not change service config! Error: %ld\n", GetLastError()); 215 228 } 216 229 else 217 { 218 VBoxServiceError("Could not change service config! Error: %ld\n", GetLastError()); 219 rc = 1; 220 } 221 } 222 break; 223 224 default: 225 226 VBoxServiceError("Could not create service! Error: %ld\n", dwErr); 227 rc = 1; 228 break; 229 } 230 } 231 else 232 { 233 VBoxServiceVerbose(0, "Service successfully installed!\n"); 234 } 235 236 if (RT_SUCCESS(rc)) 237 rc = VBoxServiceWinSetDesc(hService); 230 rc = VBoxServiceError("Could not open service! Error: %ld\n", GetLastError()); 231 break; 232 233 default: 234 rc = VBoxServiceError("Could not create service! Error: %ld\n", dwErr); 235 break; 236 } 237 } 238 239 if (rc == RTEXITCODE_SUCCESS) 240 rc = vboxServiceWinSetDesc(hService); 238 241 239 242 CloseServiceHandle(hService); … … 242 245 } 243 246 244 /** Uninstalls the service from the registry. */ 245 int VBoxServiceWinUninstall(void) 246 { 247 SC_HANDLE hService, hSCManager; 248 hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); 249 247 /** 248 * Uninstalls the service. 249 */ 250 RTEXITCODE VBoxServiceWinUninstall(void) 251 { 250 252 VBoxServiceVerbose(1, "Uninstalling service ...\n"); 251 253 252 if (NULL == hSCManager) { 254 SC_HANDLE hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); 255 if (hSCManager == NULL) 256 { 253 257 VBoxServiceError("Could not open SCM! Error: %d\n", GetLastError()); 254 return 1; 255 } 256 257 hService = OpenService (hSCManager, VBOXSERVICE_NAME, SERVICE_ALL_ACCESS ); 258 if (NULL == hService) { 259 VBoxServiceError("Could not open service! Error: %d\n", GetLastError()); 260 CloseServiceHandle (hSCManager); 261 return 1; 262 } 263 264 if (FALSE == DeleteService (hService)) 265 { 266 VBoxServiceError("Could not remove service! Error: %d\n", GetLastError()); 267 CloseServiceHandle (hService); 268 CloseServiceHandle (hSCManager); 269 return 1; 258 return RTEXITCODE_FAILURE; 259 } 260 261 RTEXITCODE rcExit; 262 SC_HANDLE hService = OpenService(hSCManager, VBOXSERVICE_NAME, SERVICE_ALL_ACCESS ); 263 if (hService != NULL) 264 { 265 if (DeleteService(hService)) 266 { 267 /* 268 * ??? 269 */ 270 HKEY hKey = NULL; 271 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, 272 "SYSTEM\\CurrentControlSet\\Services\\EventLog\\System", 273 0, 274 KEY_ALL_ACCESS, 275 &hKey) 276 == ERROR_SUCCESS) 277 { 278 RegDeleteKey(hKey, VBOXSERVICE_NAME); 279 RegCloseKey(hKey); 280 } 281 282 VBoxServiceVerbose(0, "Service successfully uninstalled!\n"); 283 rcExit = RTEXITCODE_SUCCESS; 284 } 285 else 286 rcExit = VBoxServiceError("Could not remove service! Error: %d\n", GetLastError()); 287 CloseServiceHandle(hService); 270 288 } 271 289 else 272 { 273 HKEY hKey = NULL; 274 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\System", 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) { 275 RegDeleteKey(hKey, VBOXSERVICE_NAME); 276 RegCloseKey(hKey); 277 } 278 279 VBoxServiceVerbose(0, "Service successfully uninstalled!\n"); 280 } 281 282 CloseServiceHandle(hService); 290 rcExit = VBoxServiceError("Could not open service! Error: %d\n", GetLastError()); 283 291 CloseServiceHandle(hSCManager); 284 292 285 return 0;286 } 287 288 289 int VBoxServiceWinStart(void)293 return rcExit; 294 } 295 296 297 static int vboxServiceWinStart(void) 290 298 { 291 299 int rc = VINF_SUCCESS; … … 296 304 SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_LOCAL_SID_AUTHORITY; 297 305 298 if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, 299 SECURITY_LOCAL_RID, 300 0, 0, 0, 0, 0, 0, 0, 301 &pBuiltinUsersSID)) 302 { 306 if (!AllocateAndInitializeSid(&SIDAuthWorld, 1, 307 SECURITY_LOCAL_RID, 308 0, 0, 0, 0, 0, 0, 0, 309 &pBuiltinUsersSID)) 310 { 311 /**@todo r=bird: rc = RTErrConvertFromWin32(GetLastError()); ?*/ 303 312 VBoxServiceError("AllocateAndInitializeSid: Error %u\n", GetLastError()); 304 313 } 305 314 else 306 315 { 307 DWORD dwRes = VBoxServiceWinAddAceToObjectsSecurityDescriptor(TEXT("\\\\.\\VBoxMiniRdrDN"),308 309 310 311 312 313 316 DWORD dwRes = vboxServiceWinAddAceToObjectsSecurityDescriptor(TEXT("\\\\.\\VBoxMiniRdrDN"), 317 SE_FILE_OBJECT, 318 (LPTSTR)pBuiltinUsersSID, 319 TRUSTEE_IS_SID, 320 FILE_GENERIC_READ | FILE_GENERIC_WRITE, 321 SET_ACCESS, 322 NO_INHERITANCE); 314 323 if (dwRes != ERROR_SUCCESS) 315 324 { … … 318 327 /* If we don't find our "VBoxMiniRdrDN" (for Shared Folders) object above, 319 328 don't report an error; it just might be not installed. Otherwise this 320 329 would cause the SCM to hang on starting up the service. */ 321 330 rc = VINF_SUCCESS; 322 331 } 323 else rc = RTErrConvertFromWin32(dwRes); 332 else 333 rc = RTErrConvertFromWin32(dwRes); 324 334 } 325 335 } … … 328 338 if (RT_SUCCESS(rc)) 329 339 { 330 /* Notify SCM *before* we're starting the services, because the last services331 always starts in main thread (which causes the SCM to wait because of the non-responding332 service). */333 VBoxServiceWinSetStatus (SERVICE_RUNNING, 0);334 335 340 rc = VBoxServiceStartServices(); 336 if (RT_FAILURE(rc)) 337 VBoxServiceWinSetStatus (SERVICE_STOPPED, 0); 338 } 341 if (RT_SUCCESS(rc)) 342 { 343 vboxServiceWinSetStatus(SERVICE_RUNNING, 0); 344 VBoxServiceMainWait(); 345 } 346 else 347 vboxServiceWinSetStatus(SERVICE_STOPPED, 0); 348 } 349 /**@todo r=bird: else vboxServiceWinSetStatus(SERVICE_STOPPED, 0); ? */ 339 350 340 351 if (RT_FAILURE(rc)) … … 345 356 346 357 358 /** 359 * Call StartServiceCtrlDispatcher. 360 * 361 * The main() thread invokes this when not started in foreground mode. It 362 * won't return till the service is being shutdown (unless start up fails). 363 * 364 * @returns RTEXITCODE_SUCCESS on normal return after service shutdown. 365 * Something else on failure, error will have been reported. 366 */ 367 RTEXITCODE VBoxServiceWinEnterCtrlDispatcher(void) 368 { 369 if (!StartServiceCtrlDispatcher(&g_aServiceTable[0])) 370 return VBoxServiceError("StartServiceCtrlDispatcher: %u. Please start %s with option -f (foreground)!", 371 GetLastError(), g_pszProgName); 372 return RTEXITCODE_SUCCESS; 373 } 374 375 347 376 #ifdef TARGET_NT4 348 VOID WINAPI VBoxServiceWinCtrlHandler(DWORD dwControl)377 static VOID WINAPI vboxServiceWinCtrlHandler(DWORD dwControl) 349 378 #else 350 DWORD WINAPI VBoxServiceWinCtrlHandler(DWORD dwControl, 351 DWORD dwEventType, 352 LPVOID lpEventData, 353 LPVOID lpContext) 354 #endif 355 { 356 DWORD rc = NO_ERROR; 357 358 VBoxServiceVerbose(2, "Control handler: Control=%ld\n", dwControl); 379 static DWORD WINAPI vboxServiceWinCtrlHandler(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext) 380 #endif 381 { 382 DWORD rcRet = NO_ERROR; 383 384 #ifdef TARGET_NT4 385 VBoxServiceVerbose(2, "Control handler: Control=%#x\n", dwControl); 386 #else 387 VBoxServiceVerbose(2, "Control handler: Control=%#x EventType=%#x\n", dwControl, dwEventType); 388 #endif 389 390 switch (dwControl) 391 { 392 case SERVICE_CONTROL_INTERROGATE: 393 vboxServiceWinSetStatus(g_dwWinServiceLastStatus, 0); 394 break; 395 396 case SERVICE_CONTROL_STOP: 397 case SERVICE_CONTROL_SHUTDOWN: 398 { 399 vboxServiceWinSetStatus(SERVICE_STOP_PENDING, 0); 400 401 int rc2 = VBoxServiceStopServices(); 402 if (RT_FAILURE(rc2)) 403 rcRet = ERROR_GEN_FAILURE; 404 405 vboxServiceWinSetStatus(SERVICE_STOPPED, 0); 406 break; 407 } 408 409 case SERVICE_CONTROL_SESSIONCHANGE: /* Only Win XP and up. */ 359 410 #ifndef TARGET_NT4 360 VBoxServiceVerbose(2, "Control handler: EventType=%ld\n", dwEventType); 361 #endif 362 363 switch (dwControl)364 {365 366 case SERVICE_CONTROL_INTERROGATE: 367 VBoxServiceWinSetStatus(g_rcWinService, 0);368 break;369 370 case SERVICE_CONTROL_STOP:371 case SERVICE_CONTROL_SHUTDOWN:372 {373 VBoxServiceWinSetStatus(SERVICE_STOP_PENDING, 0); 374 375 rc = VBoxServiceStopServices();376 377 VBoxServiceWinSetStatus(SERVICE_STOPPED, 0);378 }379 break;380 381 case SERVICE_CONTROL_SESSIONCHANGE: /* Only Win XP and up. */411 # if 0 412 switch (dwEventType) 413 { 414 case WTS_SESSION_LOGON: 415 VBoxServiceVerbose(2, "A user has logged on to the session.\n"); 416 break; 417 418 case WTS_SESSION_LOGOFF: 419 VBoxServiceVerbose(2, "A user has logged off from the session.\n"); 420 break; 421 default: 422 break; 423 } 424 # endif 425 #endif /* !TARGET_NT4 */ 426 break; 427 428 default: 429 VBoxServiceVerbose(1, "Service control function not implemented: %#x\n", dwControl); 430 rcRet = ERROR_CALL_NOT_IMPLEMENTED; 431 break; 432 } 382 433 383 434 #ifndef TARGET_NT4 384 switch (dwEventType) 385 { 386 /*case WTS_SESSION_LOGON: 387 VBoxServiceVerbose(2, "A user has logged on to the session.\n"); 388 break; 389 390 case WTS_SESSION_LOGOFF: 391 VBoxServiceVerbose(2, "A user has logged off from the session.\n"); 392 break;*/ 393 default: 394 break; 395 } 396 #endif /* TARGET_NT4 */ 397 break; 398 399 default: 400 401 VBoxServiceVerbose(1, "Service control function not implemented: %ld\n", dwControl); 402 rc = ERROR_CALL_NOT_IMPLEMENTED; 403 break; 404 } 405 406 #ifndef TARGET_NT4 407 return rc; 408 #endif 409 } 410 411 412 void WINAPI VBoxServiceWinMain(DWORD argc, LPTSTR *argv) 413 { 414 int rc = VINF_SUCCESS; 415 435 return rcRet; 436 #endif 437 } 438 439 440 static void WINAPI vboxServiceWinMain(DWORD argc, LPTSTR *argv) 441 { 416 442 VBoxServiceVerbose(2, "Registering service control handler ...\n"); 417 443 #ifdef TARGET_NT4 418 g_hWinServiceStatus = RegisterServiceCtrlHandler (VBOXSERVICE_NAME, VBoxServiceWinCtrlHandler);444 g_hWinServiceStatus = RegisterServiceCtrlHandler(VBOXSERVICE_NAME, vboxServiceWinCtrlHandler); 419 445 #else 420 g_hWinServiceStatus = RegisterServiceCtrlHandlerEx (VBOXSERVICE_NAME, VBoxServiceWinCtrlHandler, NULL); 421 #endif 422 423 if (NULL == g_hWinServiceStatus) 446 g_hWinServiceStatus = RegisterServiceCtrlHandlerEx(VBOXSERVICE_NAME, vboxServiceWinCtrlHandler, NULL); 447 #endif 448 if (g_hWinServiceStatus != NULL) 449 { 450 VBoxServiceVerbose(2, "Service control handler registered.\n"); 451 vboxServiceWinStart(); 452 } 453 else 424 454 { 425 455 DWORD dwErr = GetLastError(); 426 427 456 switch (dwErr) 428 457 { 429 case ERROR_INVALID_NAME: 430 VBoxServiceError("Invalid service name!\n"); 431 break; 432 case ERROR_SERVICE_DOES_NOT_EXIST: 433 VBoxServiceError("Service does not exist!\n"); 434 break; 435 default: 436 VBoxServiceError("Could not register service control handle! Error: %ld\n", dwErr); 437 break; 438 } 439 } 440 else 441 { 442 VBoxServiceVerbose(2, "Service control handler registered.\n"); 443 444 rc = VBoxServiceWinStart(); 445 } 446 } 458 case ERROR_INVALID_NAME: 459 VBoxServiceError("Invalid service name!\n"); 460 break; 461 case ERROR_SERVICE_DOES_NOT_EXIST: 462 VBoxServiceError("Service does not exist!\n"); 463 break; 464 default: 465 VBoxServiceError("Could not register service control handle! Error: %ld\n", dwErr); 466 break; 467 } 468 } 469 } 470 -
trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp
r29776 r29817 57 57 #ifdef RT_OS_WINDOWS 58 58 /** Signal shutdown to the Windows service thread. */ 59 bool volatile g_WindowsServiceShutdown;59 static bool volatile g_fWindowsServiceShutdown; 60 60 /** Event the Windows service thread waits for shutdown. */ 61 RTSEMEVENT g_WindowsServiceEvent;61 static RTSEMEVENT g_hEvtWindowsService; 62 62 #endif 63 63 … … 155 155 * Displays a syntax error message. 156 156 * 157 * @returns 1157 * @returns RTEXITCODE_SYNTAX. 158 158 * @param pszFormat The message text. 159 159 * @param ... Format arguments. 160 160 */ 161 intVBoxServiceSyntax(const char *pszFormat, ...)161 RTEXITCODE VBoxServiceSyntax(const char *pszFormat, ...) 162 162 { 163 163 RTStrmPrintf(g_pStdErr, "%s: syntax error: ", g_pszProgName); … … 168 168 va_end(va); 169 169 170 return 1;170 return RTEXITCODE_SYNTAX; 171 171 } 172 172 … … 175 175 * Displays an error message. 176 176 * 177 * @returns 1177 * @returns RTEXITCODE_FAILURE. 178 178 * @param pszFormat The message text. 179 179 * @param ... Format arguments. 180 180 */ 181 intVBoxServiceError(const char *pszFormat, ...)181 RTEXITCODE VBoxServiceError(const char *pszFormat, ...) 182 182 { 183 183 RTStrmPrintf(g_pStdErr, "%s: error: ", g_pszProgName); … … 192 192 va_end(va); 193 193 194 return 1;194 return RTEXITCODE_FAILURE; 195 195 } 196 196 … … 308 308 VBoxServiceVerbose(2, "Initializing services ...\n"); 309 309 for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++) 310 {311 310 if (g_aServices[j].fEnabled) 312 311 { … … 326 325 } 327 326 } 328 }329 327 330 328 /* … … 357 355 } 358 356 359 #ifdef RT_OS_WINDOWS360 if (RT_SUCCESS(rc))361 {362 /* Block the main thread. */363 VBoxServiceVerbose(1, "Waiting in main thread\n");364 int rc = RTSemEventCreate(&g_WindowsServiceEvent);365 AssertRC(rc);366 for (;;)367 {368 if (g_WindowsServiceShutdown)369 break;370 rc = RTSemEventWait(g_WindowsServiceEvent, RT_INDEFINITE_WAIT);371 AssertRC(rc);372 }373 RTSemEventDestroy(g_WindowsServiceEvent);374 g_WindowsServiceEvent = NIL_RTSEMEVENT;375 }376 #endif377 357 return rc; 378 358 } … … 389 369 int rc = VINF_SUCCESS; 390 370 391 for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++) 392 ASMAtomicXchgBool(&g_aServices[j].fShutdown, true); 371 /* 372 * Signal all the services. 373 */ 374 for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++) 375 ASMAtomicWriteBool(&g_aServices[j].fShutdown, true); 376 377 /* 378 * Do the pfnStop callback on all running services. 379 */ 393 380 for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++) 394 381 if (g_aServices[j].fStarted) … … 397 384 g_aServices[j].pDesc->pfnStop(); 398 385 } 386 387 /* 388 * Wait for all the service threads to complete. 389 */ 399 390 for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++) 400 391 { … … 411 402 #ifdef RT_OS_WINDOWS 412 403 /* Notify SCM that it takes a bit longer ... */ 413 VBoxServiceWinSetSt atus(SERVICE_STOP_PENDING, i);404 VBoxServiceWinSetStopPendingStatus(i + j*32); 414 405 #endif 415 406 } … … 423 414 #ifdef RT_OS_WINDOWS 424 415 /* 425 * As we're now done terminating all service threads, 426 * we have to stop the main thread as well (if defined). Note that the termination 427 * function will be called in a later context (when the main thread returns from the worker 428 * function). 429 */ 430 if (g_WindowsServiceEvent != NIL_RTSEMEVENT) 416 * Wake up and tell the main() thread that we're shutting down (it's 417 * sleeping in VBoxServiceMainWait). 418 */ 419 if (g_hEvtWindowsService != NIL_RTSEMEVENT) 431 420 { 432 421 VBoxServiceVerbose(3, "Stopping the main thread...\n"); 433 ASMAtomic XchgBool(&g_WindowsServiceShutdown, true);434 rc = RTSemEventSignal(g_ WindowsServiceEvent);422 ASMAtomicWriteBool(&g_fWindowsServiceShutdown, true); 423 rc = RTSemEventSignal(g_hEvtWindowsService); 435 424 AssertRC(rc); 436 425 } … … 442 431 443 432 444 #ifndef RT_OS_WINDOWS 445 /** 446 * Block all important signals, then explicitly wait until one of these 447 * signal arrives. 448 */ 449 static void VBoxServiceWaitSignal(void) 450 { 433 /** 434 * Block the main thread until the service shuts down. 435 */ 436 void VBoxServiceMainWait(void) 437 { 438 int rc; 439 440 #ifdef RT_OS_WINDOWS 441 /* 442 * Wait for the semaphore to be signalled. 443 */ 444 VBoxServiceVerbose(1, "Waiting in main thread\n"); 445 rc = RTSemEventCreate(&g_hEvtWindowsService); 446 AssertRC(rc); 447 while (!ASMAtomicReadBool(&g_fWindowsServiceShutdown)) 448 { 449 rc = RTSemEventWait(g_hEvtWindowsService, RT_INDEFINITE_WAIT); 450 AssertRC(rc); 451 } 452 RTSemEventDestroy(g_hEvtWindowsService); 453 g_hEvtWindowsService = NIL_RTSEMEVENT; 454 455 #else 456 /* 457 * Wait explicitly for a HUP, INT, QUIT, ABRT or TERM signal, blocking 458 * all important signals. 459 * 460 * The annoying EINTR/ERESTART loop is for the benefit of Solaris where 461 * sigwait returns when we receive a SIGCHLD. Kind of makes sense since 462 */ 451 463 sigset_t signalMask; 452 int iSignal;453 464 sigemptyset(&signalMask); 454 465 sigaddset(&signalMask, SIGHUP); … … 459 470 pthread_sigmask(SIG_BLOCK, &signalMask, NULL); 460 471 461 /* This loop is required on Solaris at least. FreeBSD doesn't know ERESTART. */ 462 int rc; 472 int iSignal; 463 473 do 464 474 { … … 472 482 ); 473 483 474 VBoxServiceVerbose(3, "VBoxServiceWaitSignal: Received signal %d (rc=%d)\n", iSignal, rc); 475 } 484 VBoxServiceVerbose(3, "VBoxServiceMainWait: Received signal %d (rc=%d)\n", iSignal, rc); 476 485 #endif /* !RT_OS_WINDOWS */ 486 } 477 487 478 488 … … 653 663 * Daemonize if requested. 654 664 */ 665 RTEXITCODE rcExit; 655 666 if (fDaemonize && !fDaemonized) 656 667 { 657 668 #ifdef RT_OS_WINDOWS 658 /** @todo Should do something like VBoxSVC here, OR automatically re-register659 * the service and start it. Involving VbglR3Daemonize isn't an option660 * here.661 *662 * Also, the idea here, IIRC, was to map the sub service to windows663 * services. The todo below is for mimicking windows services on664 * non-windows systems. Not sure if this is doable or not, but in anycase665 * this code can be moved into -win.666 *667 * You should return when StartServiceCtrlDispatcher, btw., not668 * continue.669 */670 669 VBoxServiceVerbose(2, "Starting service dispatcher ...\n"); 671 if (!StartServiceCtrlDispatcher(&g_aServiceTable[0])) 672 return VBoxServiceError("StartServiceCtrlDispatcher: %u. Please start %s with option -f (foreground)!", 673 GetLastError(), g_pszProgName); 674 /* Service now lives in the control dispatcher registered above. */ 670 rcExit = VBoxServiceWinEnterCtrlDispatcher(); 675 671 #else 676 672 VBoxServiceVerbose(1, "Daemonizing...\n"); … … 694 690 */ 695 691 rc = VBoxServiceStartServices(); 696 #ifndef RT_OS_WINDOWS 692 rcExit = RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; 697 693 if (RT_SUCCESS(rc)) 698 VBoxServiceWaitSignal(); 699 #endif 694 VBoxServiceMainWait(); 700 695 VBoxServiceStopServices(); 701 696 } … … 713 708 714 709 VBoxServiceVerbose(0, "Ended.\n"); 715 return RT_SUCCESS(rc) ? 0 : 1; 716 } 710 return rcExit; 711 } 712 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
r29762 r29817 102 102 /** The following constant may be defined by including NtStatus.h. */ 103 103 # define STATUS_SUCCESS ((NTSTATUS)0x00000000L) 104 105 /** @todo Move these Windows stuff into VBoxServiceVMInfo-win.cpp and hide all 106 * the windows details using behind function calls! 107 * @{ */ 104 108 /** Structure for storing the looked up user information. */ 105 109 typedef struct … … 123 127 /** Function prototypes for dynamic loading. */ 124 128 typedef DWORD (WINAPI *PFNWTSGETACTIVECONSOLESESSIONID)(void); 129 /** @} */ 125 130 126 131 #endif /* RT_OS_WINDOWS */ … … 253 258 RT_C_DECLS_BEGIN 254 259 255 extern char *g_pszProgName; 256 extern int g_cVerbosity; 257 extern uint32_t g_DefaultInterval; 258 259 extern int VBoxServiceSyntax(const char *pszFormat, ...); 260 extern int VBoxServiceError(const char *pszFormat, ...); 261 extern void VBoxServiceVerbose(int iLevel, const char *pszFormat, ...); 262 extern int VBoxServiceArgUInt32(int argc, char **argv, const char *psz, int *pi, uint32_t *pu32, uint32_t u32Min, uint32_t u32Max); 263 extern int VBoxServiceStartServices(void); 264 extern int VBoxServiceStopServices(void); 265 266 extern VBOXSERVICE g_TimeSync; 267 extern VBOXSERVICE g_Clipboard; 268 extern VBOXSERVICE g_Control; 269 extern VBOXSERVICE g_VMInfo; 270 extern VBOXSERVICE g_CpuHotPlug; 260 extern char *g_pszProgName; 261 extern int g_cVerbosity; 262 extern uint32_t g_DefaultInterval; 263 extern VBOXSERVICE g_TimeSync; 264 extern VBOXSERVICE g_Clipboard; 265 extern VBOXSERVICE g_Control; 266 extern VBOXSERVICE g_VMInfo; 267 extern VBOXSERVICE g_CpuHotPlug; 271 268 #ifdef VBOXSERVICE_MANAGEMENT 272 extern VBOXSERVICE g_MemBalloon;273 extern VBOXSERVICE g_VMStatistics;269 extern VBOXSERVICE g_MemBalloon; 270 extern VBOXSERVICE g_VMStatistics; 274 271 #endif 275 272 #ifdef VBOX_WITH_PAGE_SHARING 276 extern VBOXSERVICE g_PageSharing; 277 #endif 278 273 extern VBOXSERVICE g_PageSharing; 274 #endif 275 276 extern RTEXITCODE VBoxServiceSyntax(const char *pszFormat, ...); 277 extern RTEXITCODE VBoxServiceError(const char *pszFormat, ...); 278 extern void VBoxServiceVerbose(int iLevel, const char *pszFormat, ...); 279 extern int VBoxServiceArgUInt32(int argc, char **argv, const char *psz, int *pi, uint32_t *pu32, 280 uint32_t u32Min, uint32_t u32Max); 281 extern int VBoxServiceStartServices(void); 282 extern int VBoxServiceStopServices(void); 283 extern void VBoxServiceMainWait(void); 279 284 #ifdef RT_OS_WINDOWS 280 extern DWORD g_rcWinService; 281 extern SERVICE_TABLE_ENTRY const g_aServiceTable[]; /** @todo generate on the fly, see comment in main() from the enabled sub services. */ 285 extern RTEXITCODE VBoxServiceWinInstall(void); 286 extern RTEXITCODE VBoxServiceWinUninstall(void); 287 extern RTEXITCODE VBoxServiceWinEnterCtrlDispatcher(void); 288 extern void VBoxServiceWinSetStopPendingStatus(uint32_t uCheckPoint); 289 #endif 290 291 #ifdef RT_OS_WINDOWS 282 292 extern PFNWTSGETACTIVECONSOLESESSIONID g_pfnWTSGetActiveConsoleSessionId; /* VBoxServiceVMInfo-win.cpp */ 283 284 extern int VBoxServiceWinInstall(void);285 extern int VBoxServiceWinUninstall(void);286 extern BOOL VBoxServiceWinSetStatus(DWORD dwStatus, DWORD dwCheckPoint);287 293 # ifdef VBOX_WITH_GUEST_PROPS 288 294 extern bool VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession, VBOXSERVICEVMINFOPROC const *paProcs, DWORD cProcs); … … 295 301 296 302 #ifdef VBOX_WITH_GUEST_CONTROL 297 extern int VBoxServiceControlExecProcess(uint32_t uContext, const char *pszCmd, uint32_t uFlags,298 const char *pszArgs, uint32_t uNumArgs,299 const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars,300 const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS);303 extern int VBoxServiceControlExecProcess(uint32_t uContext, const char *pszCmd, uint32_t uFlags, 304 const char *pszArgs, uint32_t uNumArgs, 305 const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars, 306 const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS); 301 307 extern void VBoxServiceControlExecDestroyThreadData(PVBOXSERVICECTRLTHREADDATAEXEC pThread); 302 extern int VBoxServiceControlExecReadPipeBufferContent(PVBOXSERVICECTRLEXECPIPEBUF pBuf,303 uint8_t *pbBuffer, uint32_t cbBuffer, uint32_t *pcbToRead);304 extern int VBoxServiceControlExecWritePipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf,305 uint8_t *pbData, uint32_t cbData);308 extern int VBoxServiceControlExecReadPipeBufferContent(PVBOXSERVICECTRLEXECPIPEBUF pBuf, 309 uint8_t *pbBuffer, uint32_t cbBuffer, uint32_t *pcbToRead); 310 extern int VBoxServiceControlExecWritePipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf, 311 uint8_t *pbData, uint32_t cbData); 306 312 #endif 307 313
Note:
See TracChangeset
for help on using the changeset viewer.