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 static HANDLE hScmShutdownEvent = NULL; 31 static HANDLE hScmSecurityServicesEvent = NULL; 32 33 34 /* FUNCTIONS *****************************************************************/ 35 36 VOID 37 PrintString(LPCSTR fmt, ...) 38 { 39 #if DBG 40 CHAR buffer[512]; 41 va_list ap; 42 43 va_start(ap, fmt); 44 vsprintf(buffer, fmt, ap); 45 va_end(ap); 46 47 OutputDebugStringA(buffer); 48 #endif 49 } 50 51 52 DWORD 53 SetSecurityServicesEvent(VOID) 54 { 55 DWORD dwError; 56 57 if (hScmSecurityServicesEvent != NULL) 58 return ERROR_SUCCESS; 59 60 /* Create or open the SECURITY_SERVICES_STARTED event */ 61 hScmSecurityServicesEvent = CreateEventW(NULL, 62 TRUE, 63 FALSE, 64 L"SECURITY_SERVICES_STARTED"); 65 if (hScmSecurityServicesEvent == NULL) 66 { 67 dwError = GetLastError(); 68 if (dwError != ERROR_ALREADY_EXISTS) 69 return dwError; 70 71 hScmSecurityServicesEvent = OpenEventW(EVENT_MODIFY_STATE, 72 FALSE, 73 L"SECURITY_SERVICES_STARTED"); 74 if (hScmSecurityServicesEvent == NULL) 75 return GetLastError(); 76 } 77 78 SetEvent(hScmSecurityServicesEvent); 79 80 return ERROR_SUCCESS; 81 } 82 83 84 VOID 85 ScmLogEvent(DWORD dwEventId, 86 WORD wType, 87 WORD wStrings, 88 LPCWSTR *lpStrings) 89 { 90 HANDLE hLog; 91 92 hLog = RegisterEventSourceW(NULL, 93 L"Service Control Manager"); 94 if (hLog == NULL) 95 { 96 DPRINT1("ScmLogEvent: RegisterEventSourceW failed %lu\n", GetLastError()); 97 return; 98 } 99 100 if (!ReportEventW(hLog, 101 wType, 102 0, 103 dwEventId, 104 NULL, 105 wStrings, 106 0, 107 lpStrings, 108 NULL)) 109 { 110 DPRINT1("ScmLogEvent: ReportEventW failed %lu\n", GetLastError()); 111 } 112 113 DeregisterEventSource(hLog); 114 } 115 116 117 VOID 118 ScmWaitForLsa(VOID) 119 { 120 HANDLE hEvent = CreateEventW(NULL, TRUE, FALSE, L"LSA_RPC_SERVER_ACTIVE"); 121 if (hEvent == NULL) 122 { 123 DPRINT1("Failed to create or open the notification event (Error %lu)\n", GetLastError()); 124 } 125 else 126 { 127 DPRINT("Wait for the LSA server!\n"); 128 WaitForSingleObject(hEvent, INFINITE); 129 DPRINT("LSA server running!\n"); 130 CloseHandle(hEvent); 131 } 132 133 DPRINT("ScmWaitForLsa() done\n"); 134 } 135 136 137 BOOL WINAPI 138 ShutdownHandlerRoutine(DWORD dwCtrlType) 139 { 140 DPRINT1("ShutdownHandlerRoutine() called\n"); 141 142 if (dwCtrlType & (CTRL_SHUTDOWN_EVENT | CTRL_LOGOFF_EVENT)) 143 { 144 DPRINT1("Shutdown event received!\n"); 145 ScmShutdown = TRUE; 146 147 ScmAutoShutdownServices(); 148 ScmShutdownServiceDatabase(); 149 150 /* Set the shutdown event */ 151 SetEvent(hScmShutdownEvent); 152 } 153 154 return TRUE; 155 } 156 157 158 int WINAPI 159 wWinMain(HINSTANCE hInstance, 160 HINSTANCE hPrevInstance, 161 LPWSTR lpCmdLine, 162 int nShowCmd) 163 { 164 HANDLE hScmStartEvent = NULL; 165 HANDLE hScmAutoStartCompleteEvent = NULL; 166 SC_RPC_LOCK Lock = NULL; 167 BOOL bCanDeleteNamedPipeCriticalSection = FALSE; 168 DWORD dwError; 169 170 DPRINT("SERVICES: Service Control Manager\n"); 171 172 /* Make us critical */ 173 RtlSetProcessIsCritical(TRUE, NULL, TRUE); 174 175 /* We are initializing ourselves */ 176 ScmInitialize = TRUE; 177 178 /* Create the start event */ 179 hScmStartEvent = CreateEventW(NULL, TRUE, FALSE, SCM_START_EVENT); 180 if (hScmStartEvent == NULL) 181 { 182 DPRINT1("SERVICES: Failed to create the start event\n"); 183 goto done; 184 } 185 DPRINT("SERVICES: Created start event with handle %p.\n", hScmStartEvent); 186 187 /* Create the auto-start complete event */ 188 hScmAutoStartCompleteEvent = CreateEventW(NULL, TRUE, FALSE, SCM_AUTOSTARTCOMPLETE_EVENT); 189 if (hScmAutoStartCompleteEvent == NULL) 190 { 191 DPRINT1("SERVICES: Failed to create the auto-start complete event\n"); 192 goto done; 193 } 194 DPRINT("SERVICES: created auto-start complete event with handle %p.\n", hScmAutoStartCompleteEvent); 195 196 /* Create the shutdown event */ 197 hScmShutdownEvent = CreateEventW(NULL, TRUE, FALSE, NULL); 198 if (hScmShutdownEvent == NULL) 199 { 200 DPRINT1("SERVICES: Failed to create the shutdown event\n"); 201 goto done; 202 } 203 204 /* Initialize our communication named pipe's critical section */ 205 ScmInitNamedPipeCriticalSection(); 206 bCanDeleteNamedPipeCriticalSection = TRUE; 207 208 // ScmInitThreadManager(); 209 210 ScmInitializeSecurity(); 211 212 /* FIXME: more initialization */ 213 214 /* Create the 'Last Known Good' control set */ 215 dwError = ScmCreateLastKnownGoodControlSet(); 216 if (dwError != ERROR_SUCCESS) 217 { 218 DPRINT1("SERVICES: Failed to create the 'Last Known Good' control set (Error %lu)\n", dwError); 219 goto done; 220 } 221 222 /* Create the services database */ 223 dwError = ScmCreateServiceDatabase(); 224 if (dwError != ERROR_SUCCESS) 225 { 226 DPRINT1("SERVICES: Failed to create SCM database (Error %lu)\n", dwError); 227 goto done; 228 } 229 230 /* Update the services database */ 231 ScmGetBootAndSystemDriverState(); 232 233 /* Register the Service Control Manager process with the ReactOS Subsystem */ 234 if (!RegisterServicesProcess(GetCurrentProcessId())) 235 { 236 DPRINT1("SERVICES: Could not register SCM process\n"); 237 goto done; 238 } 239 240 /* 241 * Acquire the user service start lock until 242 * auto-start services have been started. 243 */ 244 dwError = ScmAcquireServiceStartLock(TRUE, &Lock); 245 if (dwError != ERROR_SUCCESS) 246 { 247 DPRINT1("SERVICES: Failed to acquire the service start lock (Error %lu)\n", dwError); 248 goto done; 249 } 250 251 /* Start the RPC server */ 252 ScmStartRpcServer(); 253 254 /* Signal start event */ 255 SetEvent(hScmStartEvent); 256 257 DPRINT("SERVICES: Initialized.\n"); 258 259 /* Register event handler (used for system shutdown) */ 260 SetConsoleCtrlHandler(ShutdownHandlerRoutine, TRUE); 261 262 /* 263 * Set our shutdown parameters: we want to shutdown after the maintained 264 * services (that inherit the default shutdown level of 640). 265 */ 266 SetProcessShutdownParameters(480, SHUTDOWN_NORETRY); 267 268 /* Start auto-start services */ 269 ScmAutoStartServices(); 270 271 /* Signal auto-start complete event */ 272 SetEvent(hScmAutoStartCompleteEvent); 273 274 /* FIXME: more to do ? */ 275 276 /* Release the service start lock */ 277 ScmReleaseServiceStartLock(&Lock); 278 279 /* Initialization finished */ 280 ScmInitialize = FALSE; 281 282 DPRINT("SERVICES: Running.\n"); 283 284 /* Wait until the shutdown event gets signaled */ 285 WaitForSingleObject(hScmShutdownEvent, INFINITE); 286 287 done: 288 ScmShutdownSecurity(); 289 290 /* Delete our communication named pipe's critical section */ 291 if (bCanDeleteNamedPipeCriticalSection != FALSE) 292 ScmDeleteNamedPipeCriticalSection(); 293 294 if (hScmSecurityServicesEvent != NULL) 295 CloseHandle(hScmSecurityServicesEvent); 296 297 /* Close the shutdown event */ 298 if (hScmShutdownEvent != NULL) 299 CloseHandle(hScmShutdownEvent); 300 301 /* Close the auto-start complete event */ 302 if (hScmAutoStartCompleteEvent != NULL) 303 CloseHandle(hScmAutoStartCompleteEvent); 304 305 /* Close the start event */ 306 if (hScmStartEvent != NULL) 307 CloseHandle(hScmStartEvent); 308 309 DPRINT("SERVICES: Finished.\n"); 310 311 ExitThread(0); 312 return 0; 313 } 314 315 /* EOF */ 316