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