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 ScmLogError(DWORD dwEventId
,
62 hLog
= RegisterEventSourceW(NULL
,
63 L
"Service Control Manager");
66 DPRINT1("ScmLogEvent: RegisterEventSourceW failed %lu\n", GetLastError());
70 if (!ReportEventW(hLog
,
80 DPRINT1("ScmLogEvent: ReportEventW failed %lu\n", GetLastError());
83 DeregisterEventSource(hLog
);
90 HANDLE hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, LSA_RPC_SERVER_ACTIVE
);
93 DPRINT1("Failed to create the notification event (Error %lu)\n", GetLastError());
97 DPRINT("Wait for the LSA server!\n");
98 WaitForSingleObject(hEvent
, INFINITE
);
99 DPRINT("LSA server running!\n");
103 DPRINT("ScmWaitForLsa() done\n");
108 ScmNamedPipeHandleRequest(PVOID Request
,
113 DbgPrint("SCM READ: %p\n", Request
);
121 ScmNamedPipeThread(LPVOID Context
)
123 CHAR chRequest
[PIPE_BUFSIZE
];
124 CHAR chReply
[PIPE_BUFSIZE
];
131 hPipe
= (HANDLE
)Context
;
133 DPRINT("ScmNamedPipeThread(%p) - Accepting SCM commands through named pipe\n", hPipe
);
137 bSuccess
= ReadFile(hPipe
,
142 if (!bSuccess
|| cbBytesRead
== 0)
147 if (ScmNamedPipeHandleRequest(&chRequest
, cbBytesRead
, &chReply
, &cbReplyBytes
))
149 bSuccess
= WriteFile(hPipe
,
154 if (!bSuccess
|| cbReplyBytes
!= cbWritten
)
161 DPRINT("ScmNamedPipeThread(%p) - Disconnecting named pipe connection\n", hPipe
);
163 FlushFileBuffers(hPipe
);
164 DisconnectNamedPipe(hPipe
);
167 DPRINT("ScmNamedPipeThread(%p) - Done.\n", hPipe
);
169 return ERROR_SUCCESS
;
174 ScmCreateNamedPipe(VOID
)
181 DPRINT("ScmCreateNamedPipe() - CreateNamedPipe(\"\\\\.\\pipe\\Ntsvcs\")\n");
183 hPipe
= CreateNamedPipeW(L
"\\\\.\\pipe\\Ntsvcs",
185 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
,
186 PIPE_UNLIMITED_INSTANCES
,
191 if (hPipe
== INVALID_HANDLE_VALUE
)
193 DPRINT("CreateNamedPipe() failed (%lu)\n", GetLastError());
197 DPRINT("CreateNamedPipe() - calling ConnectNamedPipe(%p)\n", hPipe
);
198 bConnected
= ConnectNamedPipe(hPipe
,
199 NULL
) ? TRUE
: (GetLastError() == ERROR_PIPE_CONNECTED
);
200 DPRINT("CreateNamedPipe() - ConnectNamedPipe() returned %d\n", bConnected
);
204 DPRINT("Pipe connected\n");
205 hThread
= CreateThread(NULL
,
213 DPRINT("Could not create thread (%lu)\n", GetLastError());
214 DisconnectNamedPipe(hPipe
);
216 DPRINT("CreateNamedPipe() - returning FALSE\n");
220 CloseHandle(hThread
);
224 DPRINT("Pipe not connected\n");
226 DPRINT("CreateNamedPipe() - returning FALSE\n");
229 DPRINT("CreateNamedPipe() - returning TRUE\n");
235 ScmNamedPipeListenerThread(LPVOID Context
)
238 DPRINT("ScmNamedPipeListenerThread(%p) - aka SCM.\n", Context
);
240 // hPipe = (HANDLE)Context;
243 DPRINT("SCM: Waiting for new connection on named pipe...\n");
244 /* Create named pipe */
245 if (!ScmCreateNamedPipe())
247 DPRINT1("\nSCM: Failed to create named pipe\n");
251 DPRINT("\nSCM: named pipe session created.\n");
254 DPRINT("\n\nWARNING: ScmNamedPipeListenerThread(%p) - Aborted.\n\n", Context
);
255 return ERROR_SUCCESS
;
260 StartScmNamedPipeThreadListener(VOID
)
265 hThread
= CreateThread(NULL
,
267 ScmNamedPipeListenerThread
,
268 NULL
, /*(LPVOID)hPipe,*/
273 DPRINT1("SERVICES: Could not create thread (Status %lx)\n", GetLastError());
277 CloseHandle(hThread
);
284 ShutdownHandlerRoutine(DWORD dwCtrlType
)
286 DPRINT1("ShutdownHandlerRoutine() called\n");
288 if (dwCtrlType
& (CTRL_SHUTDOWN_EVENT
| CTRL_LOGOFF_EVENT
))
290 DPRINT1("Shutdown event received!\n");
293 ScmAutoShutdownServices();
294 ScmShutdownServiceDatabase();
296 /* Set the shutdwon event */
297 SetEvent(hScmShutdownEvent
);
305 wWinMain(HINSTANCE hInstance
,
306 HINSTANCE hPrevInstance
,
310 HANDLE hScmStartEvent
= NULL
;
311 HANDLE hScmAutoStartCompleteEvent
= NULL
;
312 SC_RPC_LOCK Lock
= NULL
;
313 BOOL bCanDeleteNamedPipeCriticalSection
= FALSE
;
316 DPRINT("SERVICES: Service Control Manager\n");
318 /* We are initializing ourselves */
319 ScmInitialize
= TRUE
;
321 /* Create the start event */
322 hScmStartEvent
= CreateEventW(NULL
, TRUE
, FALSE
, SCM_START_EVENT
);
323 if (hScmStartEvent
== NULL
)
325 DPRINT1("SERVICES: Failed to create the start event\n");
328 DPRINT("SERVICES: Created start event with handle %p.\n", hScmStartEvent
);
330 /* Create the auto-start complete event */
331 hScmAutoStartCompleteEvent
= CreateEventW(NULL
, TRUE
, FALSE
, SCM_AUTOSTARTCOMPLETE_EVENT
);
332 if (hScmAutoStartCompleteEvent
== NULL
)
334 DPRINT1("SERVICES: Failed to create the auto-start complete event\n");
337 DPRINT("SERVICES: created auto-start complete event with handle %p.\n", hScmAutoStartCompleteEvent
);
339 /* Create the shutdown event */
340 hScmShutdownEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
341 if (hScmShutdownEvent
== NULL
)
343 DPRINT1("SERVICES: Failed to create the shutdown event\n");
347 /* Initialize our communication named pipe's critical section */
348 ScmInitNamedPipeCriticalSection();
349 bCanDeleteNamedPipeCriticalSection
= TRUE
;
351 // ScmInitThreadManager();
353 /* FIXME: more initialization */
355 /* Read the control set values */
356 if (!ScmGetControlSetValues())
358 DPRINT1("SERVICES: Failed to read the control set values\n");
362 /* Create the services database */
363 dwError
= ScmCreateServiceDatabase();
364 if (dwError
!= ERROR_SUCCESS
)
366 DPRINT1("SERVICES: Failed to create SCM database (Error %lu)\n", dwError
);
370 /* Wait for the LSA server */
373 /* Update the services database */
374 ScmGetBootAndSystemDriverState();
376 /* Register the Service Control Manager process with the ReactOS Subsystem */
377 if (!RegisterServicesProcess(GetCurrentProcessId()))
379 DPRINT1("SERVICES: Could not register SCM process\n");
384 * Acquire the user service start lock until
385 * auto-start services have been started.
387 dwError
= ScmAcquireServiceStartLock(TRUE
, &Lock
);
388 if (dwError
!= ERROR_SUCCESS
)
390 DPRINT1("SERVICES: Failed to acquire the service start lock (Error %lu)\n", dwError
);
394 /* Start the RPC server */
397 /* Signal start event */
398 SetEvent(hScmStartEvent
);
400 DPRINT("SERVICES: Initialized.\n");
402 /* Register event handler (used for system shutdown) */
403 SetConsoleCtrlHandler(ShutdownHandlerRoutine
, TRUE
);
405 /* Start auto-start services */
406 ScmAutoStartServices();
408 /* Signal auto-start complete event */
409 SetEvent(hScmAutoStartCompleteEvent
);
411 /* FIXME: more to do ? */
413 /* Release the service start lock */
414 ScmReleaseServiceStartLock(&Lock
);
416 /* Initialization finished */
417 ScmInitialize
= FALSE
;
419 DPRINT("SERVICES: Running.\n");
421 /* Wait until the shutdown event gets signaled */
422 WaitForSingleObject(hScmShutdownEvent
, INFINITE
);
425 /* Delete our communication named pipe's critical section */
426 if (bCanDeleteNamedPipeCriticalSection
== TRUE
)
427 ScmDeleteNamedPipeCriticalSection();
429 /* Close the shutdown event */
430 if (hScmShutdownEvent
!= NULL
)
431 CloseHandle(hScmShutdownEvent
);
433 /* Close the auto-start complete event */
434 if (hScmAutoStartCompleteEvent
!= NULL
)
435 CloseHandle(hScmAutoStartCompleteEvent
);
437 /* Close the start event */
438 if (hScmStartEvent
!= NULL
)
439 CloseHandle(hScmStartEvent
);
441 DPRINT("SERVICES: Finished.\n");