[BASE] Spelling fixes by Josh Soref. CORE-12286
[reactos.git] / reactos / 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 #define PIPE_BUFSIZE 1024
25 #define PIPE_TIMEOUT 1000
26
27 /* Defined in include/reactos/services/services.h */
28 // #define SCM_START_EVENT L"SvcctrlStartEvent_A3752DX"
29 #define SCM_AUTOSTARTCOMPLETE_EVENT L"SC_AutoStartComplete"
30 #define LSA_RPC_SERVER_ACTIVE L"LSA_RPC_SERVER_ACTIVE"
31
32 BOOL ScmInitialize = FALSE;
33 BOOL ScmShutdown = FALSE;
34 static HANDLE hScmShutdownEvent = NULL;
35
36
37 /* FUNCTIONS *****************************************************************/
38
39 VOID
40 PrintString(LPCSTR fmt, ...)
41 {
42 #if DBG
43 CHAR buffer[512];
44 va_list ap;
45
46 va_start(ap, fmt);
47 vsprintf(buffer, fmt, ap);
48 va_end(ap);
49
50 OutputDebugStringA(buffer);
51 #endif
52 }
53
54
55 VOID
56 ScmLogEvent(DWORD dwEventId,
57 WORD wType,
58 WORD wStrings,
59 LPCWSTR *lpStrings)
60 {
61 HANDLE hLog;
62
63 hLog = RegisterEventSourceW(NULL,
64 L"Service Control Manager");
65 if (hLog == NULL)
66 {
67 DPRINT1("ScmLogEvent: RegisterEventSourceW failed %lu\n", GetLastError());
68 return;
69 }
70
71 if (!ReportEventW(hLog,
72 wType,
73 0,
74 dwEventId,
75 NULL,
76 wStrings,
77 0,
78 lpStrings,
79 NULL))
80 {
81 DPRINT1("ScmLogEvent: ReportEventW failed %lu\n", GetLastError());
82 }
83
84 DeregisterEventSource(hLog);
85 }
86
87
88 VOID
89 ScmWaitForLsa(VOID)
90 {
91 HANDLE hEvent = CreateEventW(NULL, TRUE, FALSE, LSA_RPC_SERVER_ACTIVE);
92 if (hEvent == NULL)
93 {
94 DPRINT1("Failed to create the notification event (Error %lu)\n", GetLastError());
95 }
96 else
97 {
98 DPRINT("Wait for the LSA server!\n");
99 WaitForSingleObject(hEvent, INFINITE);
100 DPRINT("LSA server running!\n");
101 CloseHandle(hEvent);
102 }
103
104 DPRINT("ScmWaitForLsa() done\n");
105 }
106
107
108 BOOL
109 ScmNamedPipeHandleRequest(PVOID Request,
110 DWORD RequestSize,
111 PVOID Reply,
112 LPDWORD ReplySize)
113 {
114 DbgPrint("SCM READ: %p\n", Request);
115
116 *ReplySize = 0;
117 return FALSE;
118 }
119
120
121 DWORD WINAPI
122 ScmNamedPipeThread(LPVOID Context)
123 {
124 CHAR chRequest[PIPE_BUFSIZE];
125 CHAR chReply[PIPE_BUFSIZE];
126 DWORD cbReplyBytes;
127 DWORD cbBytesRead;
128 DWORD cbWritten;
129 BOOL bSuccess;
130 HANDLE hPipe;
131
132 hPipe = (HANDLE)Context;
133
134 DPRINT("ScmNamedPipeThread(%p) - Accepting SCM commands through named pipe\n", hPipe);
135
136 for (;;)
137 {
138 bSuccess = ReadFile(hPipe,
139 &chRequest,
140 PIPE_BUFSIZE,
141 &cbBytesRead,
142 NULL);
143 if (!bSuccess || cbBytesRead == 0)
144 {
145 break;
146 }
147
148 if (ScmNamedPipeHandleRequest(&chRequest, cbBytesRead, &chReply, &cbReplyBytes))
149 {
150 bSuccess = WriteFile(hPipe,
151 &chReply,
152 cbReplyBytes,
153 &cbWritten,
154 NULL);
155 if (!bSuccess || cbReplyBytes != cbWritten)
156 {
157 break;
158 }
159 }
160 }
161
162 DPRINT("ScmNamedPipeThread(%p) - Disconnecting named pipe connection\n", hPipe);
163
164 FlushFileBuffers(hPipe);
165 DisconnectNamedPipe(hPipe);
166 CloseHandle(hPipe);
167
168 DPRINT("ScmNamedPipeThread(%p) - Done.\n", hPipe);
169
170 return ERROR_SUCCESS;
171 }
172
173
174 BOOL
175 ScmCreateNamedPipe(VOID)
176 {
177 DWORD dwThreadId;
178 BOOL bConnected;
179 HANDLE hThread;
180 HANDLE hPipe;
181
182 DPRINT("ScmCreateNamedPipe() - CreateNamedPipe(\"\\\\.\\pipe\\Ntsvcs\")\n");
183
184 hPipe = CreateNamedPipeW(L"\\\\.\\pipe\\Ntsvcs",
185 PIPE_ACCESS_DUPLEX,
186 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
187 PIPE_UNLIMITED_INSTANCES,
188 PIPE_BUFSIZE,
189 PIPE_BUFSIZE,
190 PIPE_TIMEOUT,
191 NULL);
192 if (hPipe == INVALID_HANDLE_VALUE)
193 {
194 DPRINT("CreateNamedPipe() failed (%lu)\n", GetLastError());
195 return FALSE;
196 }
197
198 DPRINT("CreateNamedPipe() - calling ConnectNamedPipe(%p)\n", hPipe);
199 bConnected = ConnectNamedPipe(hPipe,
200 NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
201 DPRINT("CreateNamedPipe() - ConnectNamedPipe() returned %d\n", bConnected);
202
203 if (bConnected)
204 {
205 DPRINT("Pipe connected\n");
206 hThread = CreateThread(NULL,
207 0,
208 ScmNamedPipeThread,
209 (LPVOID)hPipe,
210 0,
211 &dwThreadId);
212 if (!hThread)
213 {
214 DPRINT("Could not create thread (%lu)\n", GetLastError());
215 DisconnectNamedPipe(hPipe);
216 CloseHandle(hPipe);
217 DPRINT("CreateNamedPipe() - returning FALSE\n");
218 return FALSE;
219 }
220
221 CloseHandle(hThread);
222 }
223 else
224 {
225 DPRINT("Pipe not connected\n");
226 CloseHandle(hPipe);
227 DPRINT("CreateNamedPipe() - returning FALSE\n");
228 return FALSE;
229 }
230 DPRINT("CreateNamedPipe() - returning TRUE\n");
231 return TRUE;
232 }
233
234
235 DWORD WINAPI
236 ScmNamedPipeListenerThread(LPVOID Context)
237 {
238 // HANDLE hPipe;
239 DPRINT("ScmNamedPipeListenerThread(%p) - aka SCM.\n", Context);
240
241 // hPipe = (HANDLE)Context;
242 for (;;)
243 {
244 DPRINT("SCM: Waiting for new connection on named pipe...\n");
245 /* Create named pipe */
246 if (!ScmCreateNamedPipe())
247 {
248 DPRINT1("\nSCM: Failed to create named pipe\n");
249 break;
250 //ExitThread(0);
251 }
252 DPRINT("\nSCM: named pipe session created.\n");
253 Sleep(10);
254 }
255 DPRINT("\n\nWARNING: ScmNamedPipeListenerThread(%p) - Aborted.\n\n", Context);
256 return ERROR_SUCCESS;
257 }
258
259
260 BOOL
261 StartScmNamedPipeThreadListener(VOID)
262 {
263 DWORD dwThreadId;
264 HANDLE hThread;
265
266 hThread = CreateThread(NULL,
267 0,
268 ScmNamedPipeListenerThread,
269 NULL, /*(LPVOID)hPipe,*/
270 0,
271 &dwThreadId);
272 if (!hThread)
273 {
274 DPRINT1("SERVICES: Could not create thread (Status %lx)\n", GetLastError());
275 return FALSE;
276 }
277
278 CloseHandle(hThread);
279
280 return TRUE;
281 }
282
283
284 BOOL WINAPI
285 ShutdownHandlerRoutine(DWORD dwCtrlType)
286 {
287 DPRINT1("ShutdownHandlerRoutine() called\n");
288
289 if (dwCtrlType & (CTRL_SHUTDOWN_EVENT | CTRL_LOGOFF_EVENT))
290 {
291 DPRINT1("Shutdown event received!\n");
292 ScmShutdown = TRUE;
293
294 ScmAutoShutdownServices();
295 ScmShutdownServiceDatabase();
296
297 /* Set the shutdown event */
298 SetEvent(hScmShutdownEvent);
299 }
300
301 return TRUE;
302 }
303
304
305 int WINAPI
306 wWinMain(HINSTANCE hInstance,
307 HINSTANCE hPrevInstance,
308 LPWSTR lpCmdLine,
309 int nShowCmd)
310 {
311 HANDLE hScmStartEvent = NULL;
312 HANDLE hScmAutoStartCompleteEvent = NULL;
313 SC_RPC_LOCK Lock = NULL;
314 BOOL bCanDeleteNamedPipeCriticalSection = FALSE;
315 DWORD dwError;
316
317 DPRINT("SERVICES: Service Control Manager\n");
318
319 /* Make us critical */
320 RtlSetProcessIsCritical(TRUE, NULL, TRUE);
321
322 /* We are initializing ourselves */
323 ScmInitialize = TRUE;
324
325 /* Create the start event */
326 hScmStartEvent = CreateEventW(NULL, TRUE, FALSE, SCM_START_EVENT);
327 if (hScmStartEvent == NULL)
328 {
329 DPRINT1("SERVICES: Failed to create the start event\n");
330 goto done;
331 }
332 DPRINT("SERVICES: Created start event with handle %p.\n", hScmStartEvent);
333
334 /* Create the auto-start complete event */
335 hScmAutoStartCompleteEvent = CreateEventW(NULL, TRUE, FALSE, SCM_AUTOSTARTCOMPLETE_EVENT);
336 if (hScmAutoStartCompleteEvent == NULL)
337 {
338 DPRINT1("SERVICES: Failed to create the auto-start complete event\n");
339 goto done;
340 }
341 DPRINT("SERVICES: created auto-start complete event with handle %p.\n", hScmAutoStartCompleteEvent);
342
343 /* Create the shutdown event */
344 hScmShutdownEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
345 if (hScmShutdownEvent == NULL)
346 {
347 DPRINT1("SERVICES: Failed to create the shutdown event\n");
348 goto done;
349 }
350
351 /* Initialize our communication named pipe's critical section */
352 ScmInitNamedPipeCriticalSection();
353 bCanDeleteNamedPipeCriticalSection = TRUE;
354
355 // ScmInitThreadManager();
356
357 ScmInitializeSecurity();
358
359 /* FIXME: more initialization */
360
361 /* Read the control set values */
362 if (!ScmGetControlSetValues())
363 {
364 DPRINT1("SERVICES: Failed to read the control set values\n");
365 goto done;
366 }
367
368 /* Create the services database */
369 dwError = ScmCreateServiceDatabase();
370 if (dwError != ERROR_SUCCESS)
371 {
372 DPRINT1("SERVICES: Failed to create SCM database (Error %lu)\n", dwError);
373 goto done;
374 }
375
376 /* Wait for the LSA server */
377 ScmWaitForLsa();
378
379 /* Update the services database */
380 ScmGetBootAndSystemDriverState();
381
382 /* Register the Service Control Manager process with the ReactOS Subsystem */
383 if (!RegisterServicesProcess(GetCurrentProcessId()))
384 {
385 DPRINT1("SERVICES: Could not register SCM process\n");
386 goto done;
387 }
388
389 /*
390 * Acquire the user service start lock until
391 * auto-start services have been started.
392 */
393 dwError = ScmAcquireServiceStartLock(TRUE, &Lock);
394 if (dwError != ERROR_SUCCESS)
395 {
396 DPRINT1("SERVICES: Failed to acquire the service start lock (Error %lu)\n", dwError);
397 goto done;
398 }
399
400 /* Start the RPC server */
401 ScmStartRpcServer();
402
403 /* Signal start event */
404 SetEvent(hScmStartEvent);
405
406 DPRINT("SERVICES: Initialized.\n");
407
408 /* Register event handler (used for system shutdown) */
409 SetConsoleCtrlHandler(ShutdownHandlerRoutine, TRUE);
410
411 /*
412 * Set our shutdown parameters: we want to shutdown after the maintained
413 * services (that inherit the default shutdown level of 640).
414 */
415 SetProcessShutdownParameters(480, SHUTDOWN_NORETRY);
416
417 /* Start auto-start services */
418 ScmAutoStartServices();
419
420 /* Signal auto-start complete event */
421 SetEvent(hScmAutoStartCompleteEvent);
422
423 /* FIXME: more to do ? */
424
425 /* Release the service start lock */
426 ScmReleaseServiceStartLock(&Lock);
427
428 /* Initialization finished */
429 ScmInitialize = FALSE;
430
431 DPRINT("SERVICES: Running.\n");
432
433 /* Wait until the shutdown event gets signaled */
434 WaitForSingleObject(hScmShutdownEvent, INFINITE);
435
436 done:
437 ScmShutdownSecurity();
438
439 /* Delete our communication named pipe's critical section */
440 if (bCanDeleteNamedPipeCriticalSection == TRUE)
441 ScmDeleteNamedPipeCriticalSection();
442
443 /* Close the shutdown event */
444 if (hScmShutdownEvent != NULL)
445 CloseHandle(hScmShutdownEvent);
446
447 /* Close the auto-start complete event */
448 if (hScmAutoStartCompleteEvent != NULL)
449 CloseHandle(hScmAutoStartCompleteEvent);
450
451 /* Close the start event */
452 if (hScmStartEvent != NULL)
453 CloseHandle(hScmStartEvent);
454
455 DPRINT("SERVICES: Finished.\n");
456
457 ExitThread(0);
458 return 0;
459 }
460
461 /* EOF */