xref: /reactos/base/system/services/services.c (revision 36873c49)
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