1 /* 2 * PROJECT: ReactOS Service Control Manager 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: base/system/services/services.c 5 * PURPOSE: Main SCM controller 6 * COPYRIGHT: Copyright 2001-2005 Eric Kohl 7 * Copyright 2007 Ged Murphy <gedmurphy@reactos.org> 8 * 9 */ 10 11 /* INCLUDES *****************************************************************/ 12 13 #include "services.h" 14 15 #include <wincon.h> 16 17 #define NDEBUG 18 #include <debug.h> 19 20 int WINAPI RegisterServicesProcess(DWORD ServicesProcessId); 21 22 /* GLOBALS ******************************************************************/ 23 24 /* Defined in include/reactos/services/services.h */ 25 // #define SCM_START_EVENT L"SvcctrlStartEvent_A3752DX" 26 #define SCM_AUTOSTARTCOMPLETE_EVENT L"SC_AutoStartComplete" 27 28 BOOL ScmInitialize = FALSE; 29 BOOL ScmShutdown = FALSE; 30 BOOL ScmLiveSetup = FALSE; 31 BOOL ScmSetupInProgress = FALSE; 32 static HANDLE hScmShutdownEvent = NULL; 33 static HANDLE hScmSecurityServicesEvent = NULL; 34 35 36 /* FUNCTIONS *****************************************************************/ 37 38 VOID 39 PrintString(LPCSTR fmt, ...) 40 { 41 #if DBG 42 CHAR buffer[512]; 43 va_list ap; 44 45 va_start(ap, fmt); 46 vsprintf(buffer, fmt, ap); 47 va_end(ap); 48 49 OutputDebugStringA(buffer); 50 #endif 51 } 52 53 DWORD 54 CheckForLiveCD(VOID) 55 { 56 WCHAR CommandLine[MAX_PATH]; 57 HKEY hSetupKey; 58 DWORD dwSetupType; 59 DWORD dwSetupInProgress; 60 DWORD dwType; 61 DWORD dwSize; 62 DWORD dwError; 63 64 DPRINT1("CheckSetup()\n"); 65 66 /* Open the Setup key */ 67 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 68 L"SYSTEM\\Setup", 69 0, 70 KEY_QUERY_VALUE, 71 &hSetupKey); 72 if (dwError != ERROR_SUCCESS) 73 return dwError; 74 75 /* Read the SetupType value */ 76 dwSize = sizeof(DWORD); 77 dwError = RegQueryValueExW(hSetupKey, 78 L"SetupType", 79 NULL, 80 &dwType, 81 (LPBYTE)&dwSetupType, 82 &dwSize); 83 84 if (dwError != ERROR_SUCCESS || 85 dwType != REG_DWORD || 86 dwSize != sizeof(DWORD) || 87 dwSetupType == 0) 88 goto done; 89 90 /* Read the CmdLine value */ 91 dwSize = sizeof(CommandLine); 92 dwError = RegQueryValueExW(hSetupKey, 93 L"CmdLine", 94 NULL, 95 &dwType, 96 (LPBYTE)CommandLine, 97 &dwSize); 98 99 if (dwError != ERROR_SUCCESS || 100 (dwType != REG_SZ && 101 dwType != REG_EXPAND_SZ && 102 dwType != REG_MULTI_SZ)) 103 goto done; 104 105 /* Check for the '-mini' option */ 106 if (wcsstr(CommandLine, L" -mini") != NULL) 107 { 108 DPRINT1("Running on LiveCD\n"); 109 ScmLiveSetup = TRUE; 110 } 111 112 /* Read the SystemSetupInProgress value */ 113 dwSize = sizeof(DWORD); 114 dwError = RegQueryValueExW(hSetupKey, 115 L"SystemSetupInProgress", 116 NULL, 117 &dwType, 118 (LPBYTE)&dwSetupInProgress, 119 &dwSize); 120 if (dwError != ERROR_SUCCESS || 121 dwType != REG_DWORD || 122 dwSize != sizeof(DWORD) || 123 dwSetupType == 0) 124 { 125 goto done; 126 } 127 128 if (dwSetupInProgress == 1) 129 { 130 DPRINT1("ReactOS Setup currently in progress!\n"); 131 ScmSetupInProgress = TRUE; 132 } 133 134 done: 135 RegCloseKey(hSetupKey); 136 137 return dwError; 138 } 139 140 141 DWORD 142 SetSecurityServicesEvent(VOID) 143 { 144 DWORD dwError; 145 146 if (hScmSecurityServicesEvent != NULL) 147 return ERROR_SUCCESS; 148 149 /* Create or open the SECURITY_SERVICES_STARTED event */ 150 hScmSecurityServicesEvent = CreateEventW(NULL, 151 TRUE, 152 FALSE, 153 L"SECURITY_SERVICES_STARTED"); 154 if (hScmSecurityServicesEvent == NULL) 155 { 156 dwError = GetLastError(); 157 if (dwError != ERROR_ALREADY_EXISTS) 158 return dwError; 159 160 hScmSecurityServicesEvent = OpenEventW(EVENT_MODIFY_STATE, 161 FALSE, 162 L"SECURITY_SERVICES_STARTED"); 163 if (hScmSecurityServicesEvent == NULL) 164 return GetLastError(); 165 } 166 167 SetEvent(hScmSecurityServicesEvent); 168 169 return ERROR_SUCCESS; 170 } 171 172 173 VOID 174 ScmLogEvent(DWORD dwEventId, 175 WORD wType, 176 WORD wStrings, 177 LPCWSTR *lpStrings) 178 { 179 HANDLE hLog; 180 181 hLog = RegisterEventSourceW(NULL, 182 L"Service Control Manager"); 183 if (hLog == NULL) 184 { 185 DPRINT1("ScmLogEvent: RegisterEventSourceW failed %lu\n", GetLastError()); 186 return; 187 } 188 189 if (!ReportEventW(hLog, 190 wType, 191 0, 192 dwEventId, 193 NULL, 194 wStrings, 195 0, 196 lpStrings, 197 NULL)) 198 { 199 DPRINT1("ScmLogEvent: ReportEventW failed %lu\n", GetLastError()); 200 } 201 202 DeregisterEventSource(hLog); 203 } 204 205 206 VOID 207 ScmWaitForLsa(VOID) 208 { 209 HANDLE hEvent = CreateEventW(NULL, TRUE, FALSE, L"LSA_RPC_SERVER_ACTIVE"); 210 if (hEvent == NULL) 211 { 212 DPRINT1("Failed to create or open the notification event (Error %lu)\n", GetLastError()); 213 } 214 else 215 { 216 DPRINT("Wait for the LSA server\n"); 217 WaitForSingleObject(hEvent, INFINITE); 218 DPRINT("LSA server running\n"); 219 CloseHandle(hEvent); 220 } 221 222 DPRINT("ScmWaitForLsa() done\n"); 223 } 224 225 226 BOOL WINAPI 227 ShutdownHandlerRoutine(DWORD dwCtrlType) 228 { 229 DPRINT1("ShutdownHandlerRoutine() called\n"); 230 231 if (dwCtrlType & (CTRL_SHUTDOWN_EVENT | CTRL_LOGOFF_EVENT)) 232 { 233 DPRINT1("Shutdown event received\n"); 234 ScmShutdown = TRUE; 235 236 ScmAutoShutdownServices(); 237 ScmShutdownServiceDatabase(); 238 239 /* Set the shutdown event */ 240 SetEvent(hScmShutdownEvent); 241 } 242 243 return TRUE; 244 } 245 246 247 int WINAPI 248 wWinMain(HINSTANCE hInstance, 249 HINSTANCE hPrevInstance, 250 LPWSTR lpCmdLine, 251 int nShowCmd) 252 { 253 HANDLE hScmStartEvent = NULL; 254 HANDLE hScmAutoStartCompleteEvent = NULL; 255 SC_RPC_LOCK Lock = NULL; 256 BOOL bCanDeleteNamedPipeCriticalSection = FALSE; 257 DWORD dwError; 258 259 DPRINT("SERVICES: Service Control Manager\n"); 260 261 dwError = CheckForLiveCD(); 262 if (dwError != ERROR_SUCCESS) 263 { 264 DPRINT1("SERVICES: Failed to check for LiveCD (Error %lu)\n", dwError); 265 goto done; 266 } 267 268 /* Make us critical */ 269 RtlSetProcessIsCritical(TRUE, NULL, TRUE); 270 271 /* We are initializing ourselves */ 272 ScmInitialize = TRUE; 273 274 /* Create the start event */ 275 hScmStartEvent = CreateEventW(NULL, TRUE, FALSE, SCM_START_EVENT); 276 if (hScmStartEvent == NULL) 277 { 278 DPRINT1("SERVICES: Failed to create the start event\n"); 279 goto done; 280 } 281 DPRINT("SERVICES: Created start event with handle %p\n", hScmStartEvent); 282 283 /* Create the auto-start complete event */ 284 hScmAutoStartCompleteEvent = CreateEventW(NULL, TRUE, FALSE, SCM_AUTOSTARTCOMPLETE_EVENT); 285 if (hScmAutoStartCompleteEvent == NULL) 286 { 287 DPRINT1("SERVICES: Failed to create the auto-start complete event\n"); 288 goto done; 289 } 290 DPRINT("SERVICES: created auto-start complete event with handle %p\n", hScmAutoStartCompleteEvent); 291 292 /* Create the shutdown event */ 293 hScmShutdownEvent = CreateEventW(NULL, TRUE, FALSE, NULL); 294 if (hScmShutdownEvent == NULL) 295 { 296 DPRINT1("SERVICES: Failed to create the shutdown event\n"); 297 goto done; 298 } 299 300 /* Initialize our communication named pipe's critical section */ 301 ScmInitNamedPipeCriticalSection(); 302 bCanDeleteNamedPipeCriticalSection = TRUE; 303 304 // ScmInitThreadManager(); 305 306 ScmInitializeSecurity(); 307 308 /* FIXME: more initialization */ 309 310 /* Create the 'Last Known Good' control set */ 311 dwError = ScmCreateLastKnownGoodControlSet(); 312 if (dwError != ERROR_SUCCESS) 313 { 314 DPRINT1("SERVICES: Failed to create the 'Last Known Good' control set (Error %lu)\n", dwError); 315 goto done; 316 } 317 318 /* Create the services database */ 319 dwError = ScmCreateServiceDatabase(); 320 if (dwError != ERROR_SUCCESS) 321 { 322 DPRINT1("SERVICES: Failed to create SCM database (Error %lu)\n", dwError); 323 goto done; 324 } 325 326 /* Update the services database */ 327 ScmGetBootAndSystemDriverState(); 328 329 /* Register the Service Control Manager process with the ReactOS Subsystem */ 330 if (!RegisterServicesProcess(GetCurrentProcessId())) 331 { 332 DPRINT1("SERVICES: Could not register SCM process\n"); 333 goto done; 334 } 335 336 /* 337 * Acquire the user service start lock until 338 * auto-start services have been started. 339 */ 340 dwError = ScmAcquireServiceStartLock(TRUE, &Lock); 341 if (dwError != ERROR_SUCCESS) 342 { 343 DPRINT1("SERVICES: Failed to acquire service start lock (Error %lu)\n", dwError); 344 goto done; 345 } 346 347 /* Start the RPC server */ 348 ScmStartRpcServer(); 349 350 /* Signal start event */ 351 SetEvent(hScmStartEvent); 352 353 DPRINT("SERVICES: Initialized\n"); 354 355 /* Register event handler (used for system shutdown) */ 356 SetConsoleCtrlHandler(ShutdownHandlerRoutine, TRUE); 357 358 /* 359 * Set our shutdown parameters: we want to shutdown after the maintained 360 * services (that inherit the default shutdown level of 640). 361 */ 362 SetProcessShutdownParameters(480, SHUTDOWN_NORETRY); 363 364 /* Start auto-start services */ 365 ScmAutoStartServices(); 366 367 /* Signal auto-start complete event */ 368 SetEvent(hScmAutoStartCompleteEvent); 369 370 /* FIXME: more to do ? */ 371 372 /* Release the service start lock */ 373 ScmReleaseServiceStartLock(&Lock); 374 375 /* Initialization finished */ 376 ScmInitialize = FALSE; 377 378 DPRINT("SERVICES: Running\n"); 379 380 /* Wait until the shutdown event gets signaled */ 381 WaitForSingleObject(hScmShutdownEvent, INFINITE); 382 383 done: 384 ScmShutdownSecurity(); 385 386 /* Delete our communication named pipe's critical section */ 387 if (bCanDeleteNamedPipeCriticalSection != FALSE) 388 ScmDeleteNamedPipeCriticalSection(); 389 390 if (hScmSecurityServicesEvent != NULL) 391 CloseHandle(hScmSecurityServicesEvent); 392 393 /* Close the shutdown event */ 394 if (hScmShutdownEvent != NULL) 395 CloseHandle(hScmShutdownEvent); 396 397 /* Close the auto-start complete event */ 398 if (hScmAutoStartCompleteEvent != NULL) 399 CloseHandle(hScmAutoStartCompleteEvent); 400 401 /* Close the start event */ 402 if (hScmStartEvent != NULL) 403 CloseHandle(hScmStartEvent); 404 405 DPRINT("SERVICES: Finished\n"); 406 407 ExitThread(0); 408 return 0; 409 } 410 411 /* EOF */ 412