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