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 /* Defined in include/reactos/services/services.h */
26 // #define SCM_START_EVENT L"SvcctrlStartEvent_A3752DX"
27 #define SCM_AUTOSTARTCOMPLETE_EVENT L"SC_AutoStartComplete"
28 #define LSA_RPC_SERVER_ACTIVE L"LSA_RPC_SERVER_ACTIVE"
30 BOOL ScmInitialize
= FALSE
;
31 BOOL ScmShutdown
= FALSE
;
32 static HANDLE hScmShutdownEvent
= NULL
;
35 /* FUNCTIONS *****************************************************************/
38 PrintString(LPCSTR fmt
, ...)
45 vsprintf(buffer
, fmt
, ap
);
48 OutputDebugStringA(buffer
);
54 ScmLogError(DWORD dwEventId
,
60 hLog
= RegisterEventSourceW(NULL
,
61 L
"Service Control Manager");
64 DPRINT1("ScmLogEvent: RegisterEventSourceW failed %lu\n", GetLastError());
68 if (!ReportEventW(hLog
,
78 DPRINT1("ScmLogEvent: ReportEventW failed %lu\n", GetLastError());
81 DeregisterEventSource(hLog
);
86 ScmCreateControlEvent(PHANDLE Event
,
88 DWORD dwDesiredAccess
)
91 * This function creates a generic non-inheritable event
92 * and return a handle to the caller. The caller must
93 * close this handle afterwards.
98 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, Name
);
101 if (GetLastError() == ERROR_ALREADY_EXISTS
)
103 hEvent
= OpenEventW(dwDesiredAccess
, FALSE
, Name
);
109 DPRINT("SERVICES: Created event %S with handle %x\n", Name
, hEvent
);
115 DPRINT1("SERVICES: Failed to create event %S (Error %lu)\n", Name
, GetLastError());
126 if (!ScmCreateControlEvent(&hEvent
,
127 LSA_RPC_SERVER_ACTIVE
,
130 DPRINT1("Failed to create the notification event (Error %lu)\n", GetLastError());
134 DPRINT("Wait for the LSA server!\n");
135 WaitForSingleObject(hEvent
, INFINITE
);
136 DPRINT("LSA server running!\n");
141 DPRINT("ScmWaitForLsa() done\n");
146 ScmNamedPipeHandleRequest(PVOID Request
,
151 DbgPrint("SCM READ: %p\n", Request
);
159 ScmNamedPipeThread(LPVOID Context
)
161 CHAR chRequest
[PIPE_BUFSIZE
];
162 CHAR chReply
[PIPE_BUFSIZE
];
169 hPipe
= (HANDLE
)Context
;
171 DPRINT("ScmNamedPipeThread(%p) - Accepting SCM commands through named pipe\n", hPipe
);
175 bSuccess
= ReadFile(hPipe
,
180 if (!bSuccess
|| cbBytesRead
== 0)
185 if (ScmNamedPipeHandleRequest(&chRequest
, cbBytesRead
, &chReply
, &cbReplyBytes
))
187 bSuccess
= WriteFile(hPipe
,
192 if (!bSuccess
|| cbReplyBytes
!= cbWritten
)
199 DPRINT("ScmNamedPipeThread(%p) - Disconnecting named pipe connection\n", hPipe
);
201 FlushFileBuffers(hPipe
);
202 DisconnectNamedPipe(hPipe
);
205 DPRINT("ScmNamedPipeThread(%p) - Done.\n", hPipe
);
207 return ERROR_SUCCESS
;
212 ScmCreateNamedPipe(VOID
)
219 DPRINT("ScmCreateNamedPipe() - CreateNamedPipe(\"\\\\.\\pipe\\Ntsvcs\")\n");
221 hPipe
= CreateNamedPipeW(L
"\\\\.\\pipe\\Ntsvcs",
223 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
,
224 PIPE_UNLIMITED_INSTANCES
,
229 if (hPipe
== INVALID_HANDLE_VALUE
)
231 DPRINT("CreateNamedPipe() failed (%lu)\n", GetLastError());
235 DPRINT("CreateNamedPipe() - calling ConnectNamedPipe(%p)\n", hPipe
);
236 bConnected
= ConnectNamedPipe(hPipe
,
237 NULL
) ? TRUE
: (GetLastError() == ERROR_PIPE_CONNECTED
);
238 DPRINT("CreateNamedPipe() - ConnectNamedPipe() returned %d\n", bConnected
);
242 DPRINT("Pipe connected\n");
243 hThread
= CreateThread(NULL
,
251 DPRINT("Could not create thread (%lu)\n", GetLastError());
252 DisconnectNamedPipe(hPipe
);
254 DPRINT("CreateNamedPipe() - returning FALSE\n");
258 CloseHandle(hThread
);
262 DPRINT("Pipe not connected\n");
264 DPRINT("CreateNamedPipe() - returning FALSE\n");
267 DPRINT("CreateNamedPipe() - returning TRUE\n");
273 ScmNamedPipeListenerThread(LPVOID Context
)
276 DPRINT("ScmNamedPipeListenerThread(%p) - aka SCM.\n", Context
);
278 // hPipe = (HANDLE)Context;
281 DPRINT("SCM: Waiting for new connection on named pipe...\n");
282 /* Create named pipe */
283 if (!ScmCreateNamedPipe())
285 DPRINT1("\nSCM: Failed to create named pipe\n");
289 DPRINT("\nSCM: named pipe session created.\n");
292 DPRINT("\n\nWARNING: ScmNamedPipeListenerThread(%p) - Aborted.\n\n", Context
);
293 return ERROR_SUCCESS
;
298 StartScmNamedPipeThreadListener(VOID
)
303 hThread
= CreateThread(NULL
,
305 ScmNamedPipeListenerThread
,
306 NULL
, /*(LPVOID)hPipe,*/
311 DPRINT1("SERVICES: Could not create thread (Status %lx)\n", GetLastError());
315 CloseHandle(hThread
);
322 ShutdownHandlerRoutine(DWORD dwCtrlType
)
324 DPRINT1("ShutdownHandlerRoutine() called\n");
326 if (dwCtrlType
& (CTRL_SHUTDOWN_EVENT
| CTRL_LOGOFF_EVENT
))
328 DPRINT1("Shutdown event received!\n");
331 ScmAutoShutdownServices();
332 ScmShutdownServiceDatabase();
334 /* Set the shutdwon event */
335 SetEvent(hScmShutdownEvent
);
343 wWinMain(HINSTANCE hInstance
,
344 HINSTANCE hPrevInstance
,
348 HANDLE hScmStartEvent
= NULL
;
349 HANDLE hScmAutoStartCompleteEvent
= NULL
;
350 SC_RPC_LOCK Lock
= NULL
;
351 BOOL bCanDeleteNamedPipeCriticalSection
= FALSE
;
354 DPRINT("SERVICES: Service Control Manager\n");
356 /* We are initializing ourselves */
357 ScmInitialize
= TRUE
;
359 /* Create the start event */
360 if (!ScmCreateControlEvent(&hScmStartEvent
,
364 DPRINT1("SERVICES: Failed to create the start event\n");
367 DPRINT("SERVICES: Created start event with handle %p.\n", hScmStartEvent
);
369 /* Create the auto-start complete event */
370 if (!ScmCreateControlEvent(&hScmAutoStartCompleteEvent
,
371 SCM_AUTOSTARTCOMPLETE_EVENT
,
374 DPRINT1("SERVICES: Failed to create the auto-start complete event\n");
377 DPRINT("SERVICES: created auto-start complete event with handle %p.\n", hScmAutoStartCompleteEvent
);
379 /* Create the shutdown event */
380 hScmShutdownEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
381 if (hScmShutdownEvent
== NULL
)
383 DPRINT1("SERVICES: Failed to create shutdown event\n");
387 /* Initialize our communication named pipe's critical section */
388 ScmInitNamedPipeCriticalSection();
389 bCanDeleteNamedPipeCriticalSection
= TRUE
;
391 // ScmInitThreadManager();
393 /* FIXME: more initialization */
395 /* Read the control set values */
396 if (!ScmGetControlSetValues())
398 DPRINT1("SERVICES: Failed to read the control set values\n");
402 /* Create the services database */
403 dwError
= ScmCreateServiceDatabase();
404 if (dwError
!= ERROR_SUCCESS
)
406 DPRINT1("SERVICES: Failed to create SCM database (Error %lu)\n", dwError
);
410 /* Wait for the LSA server */
413 /* Update the services database */
414 ScmGetBootAndSystemDriverState();
416 /* Register the Service Control Manager process with the ReactOS Subsystem */
417 if (!RegisterServicesProcess(GetCurrentProcessId()))
419 DPRINT1("SERVICES: Could not register SCM process\n");
424 * Acquire the user service start lock until
425 * auto-start services have been started.
427 dwError
= ScmAcquireServiceStartLock(TRUE
, &Lock
);
428 if (dwError
!= ERROR_SUCCESS
)
430 DPRINT1("SERVICES: Failed to acquire the service start lock (Error %lu)\n", dwError
);
434 /* Start the RPC server */
437 /* Signal start event */
438 SetEvent(hScmStartEvent
);
440 DPRINT("SERVICES: Initialized.\n");
442 /* Register event handler (used for system shutdown) */
443 SetConsoleCtrlHandler(ShutdownHandlerRoutine
, TRUE
);
445 /* Start auto-start services */
446 ScmAutoStartServices();
448 /* Signal auto-start complete event */
449 SetEvent(hScmAutoStartCompleteEvent
);
451 /* FIXME: more to do ? */
453 /* Release the service start lock */
454 ScmReleaseServiceStartLock(&Lock
);
456 /* Initialization finished */
457 ScmInitialize
= FALSE
;
459 DPRINT("SERVICES: Running.\n");
461 /* Wait until the shutdown event gets signaled */
462 WaitForSingleObject(hScmShutdownEvent
, INFINITE
);
465 /* Delete our communication named pipe's critical section */
466 if (bCanDeleteNamedPipeCriticalSection
== TRUE
)
467 ScmDeleteNamedPipeCriticalSection();
469 /* Close the shutdown event */
470 if (hScmShutdownEvent
!= NULL
)
471 CloseHandle(hScmShutdownEvent
);
473 /* Close the auto-start complete event */
474 if (hScmAutoStartCompleteEvent
!= NULL
)
475 CloseHandle(hScmAutoStartCompleteEvent
);
477 /* Close the start event */
478 if (hScmStartEvent
!= NULL
)
479 CloseHandle(hScmStartEvent
);
481 DPRINT("SERVICES: Finished.\n");