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>
11 /* INCLUDES *****************************************************************/
18 int WINAPI
RegisterServicesProcess(DWORD ServicesProcessId
);
20 /* GLOBALS ******************************************************************/
22 #define PIPE_BUFSIZE 1024
23 #define PIPE_TIMEOUT 1000
25 BOOL ScmShutdown
= FALSE
;
26 static HANDLE hScmShutdownEvent
= NULL
;
29 /* FUNCTIONS *****************************************************************/
32 PrintString(LPCSTR fmt
, ...)
39 vsprintf(buffer
, fmt
, ap
);
42 OutputDebugStringA(buffer
);
48 ScmLogError(DWORD dwEventId
,
54 hLog
= RegisterEventSourceW(NULL
,
55 L
"Service Control Manager");
58 DPRINT1("ScmLogEvent: RegisterEventSourceW failed %d\n", GetLastError());
62 if (!ReportEventW(hLog
,
72 DPRINT1("ScmLogEvent: ReportEventW failed %d\n", GetLastError());
75 DeregisterEventSource(hLog
);
80 ScmCreateStartEvent(PHANDLE StartEvent
)
84 hEvent
= CreateEventW(NULL
,
87 L
"SvcctrlStartEvent_A3752DX");
90 if (GetLastError() == ERROR_ALREADY_EXISTS
)
92 hEvent
= OpenEventW(EVENT_ALL_ACCESS
,
94 L
"SvcctrlStartEvent_A3752DX");
106 *StartEvent
= hEvent
;
118 hEvent
= CreateEventW(NULL
,
121 L
"LSA_RPC_SERVER_ACTIVE");
124 dwError
= GetLastError();
125 DPRINT1("Failed to create the notication event (Error %lu)\n", dwError
);
127 if (dwError
== ERROR_ALREADY_EXISTS
)
129 hEvent
= OpenEventW(SYNCHRONIZE
,
131 L
"LSA_RPC_SERVER_ACTIVE");
134 DPRINT1("Could not open the notification event (Error %lu)\n", GetLastError());
140 DPRINT("Wait for the LSA server!\n");
141 WaitForSingleObject(hEvent
, INFINITE
);
142 DPRINT("LSA server running!\n");
146 DPRINT("ScmWaitForLsa() done\n");
151 ScmNamedPipeHandleRequest(PVOID Request
,
156 DbgPrint("SCM READ: %s\n", Request
);
164 ScmNamedPipeThread(LPVOID Context
)
166 CHAR chRequest
[PIPE_BUFSIZE
];
167 CHAR chReply
[PIPE_BUFSIZE
];
174 hPipe
= (HANDLE
)Context
;
176 DPRINT("ScmNamedPipeThread(%x) - Accepting SCM commands through named pipe\n", hPipe
);
180 bSuccess
= ReadFile(hPipe
,
185 if (!bSuccess
|| cbBytesRead
== 0)
190 if (ScmNamedPipeHandleRequest(&chRequest
, cbBytesRead
, &chReply
, &cbReplyBytes
))
192 bSuccess
= WriteFile(hPipe
,
197 if (!bSuccess
|| cbReplyBytes
!= cbWritten
)
204 DPRINT("ScmNamedPipeThread(%x) - Disconnecting named pipe connection\n", hPipe
);
206 FlushFileBuffers(hPipe
);
207 DisconnectNamedPipe(hPipe
);
210 DPRINT("ScmNamedPipeThread(%x) - Done.\n", hPipe
);
212 return ERROR_SUCCESS
;
217 ScmCreateNamedPipe(VOID
)
224 DPRINT("ScmCreateNamedPipe() - CreateNamedPipe(\"\\\\.\\pipe\\Ntsvcs\")\n");
226 hPipe
= CreateNamedPipeW(L
"\\\\.\\pipe\\Ntsvcs",
228 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
,
229 PIPE_UNLIMITED_INSTANCES
,
234 if (hPipe
== INVALID_HANDLE_VALUE
)
236 DPRINT("CreateNamedPipe() failed (%d)\n", GetLastError());
240 DPRINT("CreateNamedPipe() - calling ConnectNamedPipe(%x)\n", hPipe
);
241 bConnected
= ConnectNamedPipe(hPipe
,
242 NULL
) ? TRUE
: (GetLastError() == ERROR_PIPE_CONNECTED
);
243 DPRINT("CreateNamedPipe() - ConnectNamedPipe() returned %d\n", bConnected
);
247 DPRINT("Pipe connected\n");
248 hThread
= CreateThread(NULL
,
256 DPRINT("Could not create thread (%d)\n", GetLastError());
257 DisconnectNamedPipe(hPipe
);
259 DPRINT("CreateNamedPipe() - returning FALSE\n");
263 CloseHandle(hThread
);
267 DPRINT("Pipe not connected\n");
269 DPRINT("CreateNamedPipe() - returning FALSE\n");
272 DPRINT("CreateNamedPipe() - returning TRUE\n");
278 ScmNamedPipeListenerThread(LPVOID Context
)
281 DPRINT("ScmNamedPipeListenerThread(%x) - aka SCM.\n", Context
);
283 // hPipe = (HANDLE)Context;
286 DPRINT("SCM: Waiting for new connection on named pipe...\n");
287 /* Create named pipe */
288 if (!ScmCreateNamedPipe())
290 DPRINT1("\nSCM: Failed to create named pipe\n");
294 DPRINT("\nSCM: named pipe session created.\n");
297 DPRINT("\n\nWARNING: ScmNamedPipeListenerThread(%x) - Aborted.\n\n", Context
);
298 return ERROR_SUCCESS
;
303 StartScmNamedPipeThreadListener(VOID
)
308 hThread
= CreateThread(NULL
,
310 ScmNamedPipeListenerThread
,
311 NULL
, /*(LPVOID)hPipe,*/
316 DPRINT1("SERVICES: Could not create thread (Status %lx)\n", GetLastError());
320 CloseHandle(hThread
);
327 ShutdownHandlerRoutine(DWORD dwCtrlType
)
329 DPRINT1("ShutdownHandlerRoutine() called\n");
331 if (dwCtrlType
& (CTRL_SHUTDOWN_EVENT
| CTRL_LOGOFF_EVENT
))
333 DPRINT1("Shutdown event received!\n");
336 ScmAutoShutdownServices();
337 ScmShutdownServiceDatabase();
339 /* Set the shutdwon event */
340 SetEvent(hScmShutdownEvent
);
348 wWinMain(HINSTANCE hInstance
,
349 HINSTANCE hPrevInstance
,
353 HANDLE hScmStartEvent
= NULL
;
354 SC_RPC_LOCK Lock
= NULL
;
355 BOOL bCanDeleteNamedPipeCriticalSection
= FALSE
;
358 DPRINT("SERVICES: Service Control Manager\n");
360 /* Create start event */
361 if (!ScmCreateStartEvent(&hScmStartEvent
))
363 DPRINT1("SERVICES: Failed to create start event\n");
367 DPRINT("SERVICES: created start event with handle %p.\n", hScmStartEvent
);
369 /* Create the shutdown event */
370 hScmShutdownEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
371 if (hScmShutdownEvent
== NULL
)
373 DPRINT1("SERVICES: Failed to create shutdown event\n");
377 /* Initialize our communication named pipe's critical section */
378 ScmInitNamedPipeCriticalSection();
379 bCanDeleteNamedPipeCriticalSection
= TRUE
;
381 // ScmInitThreadManager();
383 /* FIXME: more initialization */
385 /* Read the control set values */
386 if (!ScmGetControlSetValues())
388 DPRINT1("SERVICES: failed to read the control set values\n");
392 /* Create the services database */
393 dwError
= ScmCreateServiceDatabase();
394 if (dwError
!= ERROR_SUCCESS
)
396 DPRINT1("SERVICES: failed to create SCM database (Error %lu)\n", dwError
);
400 /* Update the services database */
401 ScmGetBootAndSystemDriverState();
403 /* Register the Service Control Manager process with CSRSS */
404 if (!RegisterServicesProcess(GetCurrentProcessId()))
406 DPRINT1("SERVICES: Could not register SCM process\n");
410 /* Acquire the service start lock until autostart services have been started */
411 dwError
= ScmAcquireServiceStartLock(TRUE
, &Lock
);
412 if (dwError
!= ERROR_SUCCESS
)
414 DPRINT1("SERVICES: failed to acquire the service start lock (Error %lu)\n", dwError
);
418 /* Start the RPC server */
421 DPRINT("SERVICES: Initialized.\n");
423 /* Signal start event */
424 SetEvent(hScmStartEvent
);
426 /* Register event handler (used for system shutdown) */
427 SetConsoleCtrlHandler(ShutdownHandlerRoutine
, TRUE
);
429 /* Wait for the LSA server */
432 /* Start auto-start services */
433 ScmAutoStartServices();
435 /* FIXME: more to do ? */
437 /* Release the service start lock */
438 ScmReleaseServiceStartLock(&Lock
);
440 DPRINT("SERVICES: Running.\n");
442 /* Wait until the shutdown event gets signaled */
443 WaitForSingleObject(hScmShutdownEvent
, INFINITE
);
446 /* Delete our communication named pipe's critical section */
447 if (bCanDeleteNamedPipeCriticalSection
== TRUE
)
448 ScmDeleteNamedPipeCriticalSection();
450 /* Close the shutdown event */
451 if (hScmShutdownEvent
!= NULL
)
452 CloseHandle(hScmShutdownEvent
);
454 /* Close the start event */
455 if (hScmStartEvent
!= NULL
)
456 CloseHandle(hScmStartEvent
);
458 DPRINT("SERVICES: Finished.\n");