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 *****************************************************************/
20 int WINAPI
RegisterServicesProcess(DWORD ServicesProcessId
);
22 /* GLOBALS ******************************************************************/
24 #define PIPE_BUFSIZE 1024
25 #define PIPE_TIMEOUT 1000
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"
32 BOOL ScmInitialize
= FALSE
;
33 BOOL ScmShutdown
= FALSE
;
34 static HANDLE hScmShutdownEvent
= NULL
;
37 /* FUNCTIONS *****************************************************************/
40 PrintString(LPCSTR fmt
, ...)
47 vsprintf(buffer
, fmt
, ap
);
50 OutputDebugStringA(buffer
);
56 ScmLogEvent(DWORD dwEventId
,
63 hLog
= RegisterEventSourceW(NULL
,
64 L
"Service Control Manager");
67 DPRINT1("ScmLogEvent: RegisterEventSourceW failed %lu\n", GetLastError());
71 if (!ReportEventW(hLog
,
81 DPRINT1("ScmLogEvent: ReportEventW failed %lu\n", GetLastError());
84 DeregisterEventSource(hLog
);
91 HANDLE hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, LSA_RPC_SERVER_ACTIVE
);
94 DPRINT1("Failed to create the notification event (Error %lu)\n", GetLastError());
98 DPRINT("Wait for the LSA server!\n");
99 WaitForSingleObject(hEvent
, INFINITE
);
100 DPRINT("LSA server running!\n");
104 DPRINT("ScmWaitForLsa() done\n");
109 ScmNamedPipeHandleRequest(PVOID Request
,
114 DbgPrint("SCM READ: %p\n", Request
);
122 ScmNamedPipeThread(LPVOID Context
)
124 CHAR chRequest
[PIPE_BUFSIZE
];
125 CHAR chReply
[PIPE_BUFSIZE
];
132 hPipe
= (HANDLE
)Context
;
134 DPRINT("ScmNamedPipeThread(%p) - Accepting SCM commands through named pipe\n", hPipe
);
138 bSuccess
= ReadFile(hPipe
,
143 if (!bSuccess
|| cbBytesRead
== 0)
148 if (ScmNamedPipeHandleRequest(&chRequest
, cbBytesRead
, &chReply
, &cbReplyBytes
))
150 bSuccess
= WriteFile(hPipe
,
155 if (!bSuccess
|| cbReplyBytes
!= cbWritten
)
162 DPRINT("ScmNamedPipeThread(%p) - Disconnecting named pipe connection\n", hPipe
);
164 FlushFileBuffers(hPipe
);
165 DisconnectNamedPipe(hPipe
);
168 DPRINT("ScmNamedPipeThread(%p) - Done.\n", hPipe
);
170 return ERROR_SUCCESS
;
175 ScmCreateNamedPipe(VOID
)
182 DPRINT("ScmCreateNamedPipe() - CreateNamedPipe(\"\\\\.\\pipe\\Ntsvcs\")\n");
184 hPipe
= CreateNamedPipeW(L
"\\\\.\\pipe\\Ntsvcs",
186 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
,
187 PIPE_UNLIMITED_INSTANCES
,
192 if (hPipe
== INVALID_HANDLE_VALUE
)
194 DPRINT("CreateNamedPipe() failed (%lu)\n", GetLastError());
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
);
205 DPRINT("Pipe connected\n");
206 hThread
= CreateThread(NULL
,
214 DPRINT("Could not create thread (%lu)\n", GetLastError());
215 DisconnectNamedPipe(hPipe
);
217 DPRINT("CreateNamedPipe() - returning FALSE\n");
221 CloseHandle(hThread
);
225 DPRINT("Pipe not connected\n");
227 DPRINT("CreateNamedPipe() - returning FALSE\n");
230 DPRINT("CreateNamedPipe() - returning TRUE\n");
236 ScmNamedPipeListenerThread(LPVOID Context
)
239 DPRINT("ScmNamedPipeListenerThread(%p) - aka SCM.\n", Context
);
241 // hPipe = (HANDLE)Context;
244 DPRINT("SCM: Waiting for new connection on named pipe...\n");
245 /* Create named pipe */
246 if (!ScmCreateNamedPipe())
248 DPRINT1("\nSCM: Failed to create named pipe\n");
252 DPRINT("\nSCM: named pipe session created.\n");
255 DPRINT("\n\nWARNING: ScmNamedPipeListenerThread(%p) - Aborted.\n\n", Context
);
256 return ERROR_SUCCESS
;
261 StartScmNamedPipeThreadListener(VOID
)
266 hThread
= CreateThread(NULL
,
268 ScmNamedPipeListenerThread
,
269 NULL
, /*(LPVOID)hPipe,*/
274 DPRINT1("SERVICES: Could not create thread (Status %lx)\n", GetLastError());
278 CloseHandle(hThread
);
285 ShutdownHandlerRoutine(DWORD dwCtrlType
)
287 DPRINT1("ShutdownHandlerRoutine() called\n");
289 if (dwCtrlType
& (CTRL_SHUTDOWN_EVENT
| CTRL_LOGOFF_EVENT
))
291 DPRINT1("Shutdown event received!\n");
294 ScmAutoShutdownServices();
295 ScmShutdownServiceDatabase();
297 /* Set the shutdwon event */
298 SetEvent(hScmShutdownEvent
);
306 wWinMain(HINSTANCE hInstance
,
307 HINSTANCE hPrevInstance
,
311 HANDLE hScmStartEvent
= NULL
;
312 HANDLE hScmAutoStartCompleteEvent
= NULL
;
313 SC_RPC_LOCK Lock
= NULL
;
314 BOOL bCanDeleteNamedPipeCriticalSection
= FALSE
;
317 DPRINT("SERVICES: Service Control Manager\n");
319 /* Make us critical */
320 RtlSetProcessIsCritical(TRUE
, NULL
, TRUE
);
322 /* We are initializing ourselves */
323 ScmInitialize
= TRUE
;
325 /* Create the start event */
326 hScmStartEvent
= CreateEventW(NULL
, TRUE
, FALSE
, SCM_START_EVENT
);
327 if (hScmStartEvent
== NULL
)
329 DPRINT1("SERVICES: Failed to create the start event\n");
332 DPRINT("SERVICES: Created start event with handle %p.\n", hScmStartEvent
);
334 /* Create the auto-start complete event */
335 hScmAutoStartCompleteEvent
= CreateEventW(NULL
, TRUE
, FALSE
, SCM_AUTOSTARTCOMPLETE_EVENT
);
336 if (hScmAutoStartCompleteEvent
== NULL
)
338 DPRINT1("SERVICES: Failed to create the auto-start complete event\n");
341 DPRINT("SERVICES: created auto-start complete event with handle %p.\n", hScmAutoStartCompleteEvent
);
343 /* Create the shutdown event */
344 hScmShutdownEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
345 if (hScmShutdownEvent
== NULL
)
347 DPRINT1("SERVICES: Failed to create the shutdown event\n");
351 /* Initialize our communication named pipe's critical section */
352 ScmInitNamedPipeCriticalSection();
353 bCanDeleteNamedPipeCriticalSection
= TRUE
;
355 // ScmInitThreadManager();
357 /* FIXME: more initialization */
359 /* Read the control set values */
360 if (!ScmGetControlSetValues())
362 DPRINT1("SERVICES: Failed to read the control set values\n");
366 /* Create the services database */
367 dwError
= ScmCreateServiceDatabase();
368 if (dwError
!= ERROR_SUCCESS
)
370 DPRINT1("SERVICES: Failed to create SCM database (Error %lu)\n", dwError
);
374 /* Wait for the LSA server */
377 /* Update the services database */
378 ScmGetBootAndSystemDriverState();
380 /* Register the Service Control Manager process with the ReactOS Subsystem */
381 if (!RegisterServicesProcess(GetCurrentProcessId()))
383 DPRINT1("SERVICES: Could not register SCM process\n");
388 * Acquire the user service start lock until
389 * auto-start services have been started.
391 dwError
= ScmAcquireServiceStartLock(TRUE
, &Lock
);
392 if (dwError
!= ERROR_SUCCESS
)
394 DPRINT1("SERVICES: Failed to acquire the service start lock (Error %lu)\n", dwError
);
398 /* Start the RPC server */
401 /* Signal start event */
402 SetEvent(hScmStartEvent
);
404 DPRINT("SERVICES: Initialized.\n");
406 /* Register event handler (used for system shutdown) */
407 SetConsoleCtrlHandler(ShutdownHandlerRoutine
, TRUE
);
410 * Set our shutdown parameters: we want to shutdown after the maintained
411 * services (that inherit the default shutdown level of 640).
413 SetProcessShutdownParameters(480, SHUTDOWN_NORETRY
);
415 /* Start auto-start services */
416 ScmAutoStartServices();
418 /* Signal auto-start complete event */
419 SetEvent(hScmAutoStartCompleteEvent
);
421 /* FIXME: more to do ? */
423 /* Release the service start lock */
424 ScmReleaseServiceStartLock(&Lock
);
426 /* Initialization finished */
427 ScmInitialize
= FALSE
;
429 DPRINT("SERVICES: Running.\n");
431 /* Wait until the shutdown event gets signaled */
432 WaitForSingleObject(hScmShutdownEvent
, INFINITE
);
435 /* Delete our communication named pipe's critical section */
436 if (bCanDeleteNamedPipeCriticalSection
== TRUE
)
437 ScmDeleteNamedPipeCriticalSection();
439 /* Close the shutdown event */
440 if (hScmShutdownEvent
!= NULL
)
441 CloseHandle(hScmShutdownEvent
);
443 /* Close the auto-start complete event */
444 if (hScmAutoStartCompleteEvent
!= NULL
)
445 CloseHandle(hScmAutoStartCompleteEvent
);
447 /* Close the start event */
448 if (hScmStartEvent
!= NULL
)
449 CloseHandle(hScmStartEvent
);
451 DPRINT("SERVICES: Finished.\n");