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