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>
12 * - Services.exe is NOT a native application, it is a GUI app.
15 /* INCLUDES *****************************************************************/
22 int WINAPI
RegisterServicesProcess(DWORD ServicesProcessId
);
24 /* GLOBALS ******************************************************************/
26 #define PIPE_BUFSIZE 1024
27 #define PIPE_TIMEOUT 1000
29 BOOL ScmShutdown
= FALSE
;
30 static HANDLE hScmShutdownEvent
= NULL
;
33 /* FUNCTIONS *****************************************************************/
36 PrintString(LPCSTR fmt
, ...)
43 vsprintf(buffer
, fmt
, ap
);
46 OutputDebugStringA(buffer
);
52 ScmLogError(DWORD dwEventId
,
58 hLog
= RegisterEventSourceW(NULL
,
59 L
"Service Control Manager");
62 DPRINT1("ScmLogEvent: RegisterEventSourceW failed %d\n", GetLastError());
66 if (!ReportEventW(hLog
,
76 DPRINT1("ScmLogEvent: ReportEventW failed %d\n", GetLastError());
79 DeregisterEventSource(hLog
);
84 ScmCreateStartEvent(PHANDLE StartEvent
)
88 hEvent
= CreateEventW(NULL
,
91 L
"SvcctrlStartEvent_A3752DX");
94 if (GetLastError() == ERROR_ALREADY_EXISTS
)
96 hEvent
= OpenEventW(EVENT_ALL_ACCESS
,
98 L
"SvcctrlStartEvent_A3752DX");
110 *StartEvent
= hEvent
;
122 hEvent
= CreateEventW(NULL
,
125 L
"LSA_RPC_SERVER_ACTIVE");
128 dwError
= GetLastError();
129 DPRINT1("Failed to create the notication event (Error %lu)\n", dwError
);
131 if (dwError
== ERROR_ALREADY_EXISTS
)
133 hEvent
= OpenEventW(SYNCHRONIZE
,
135 L
"LSA_RPC_SERVER_ACTIVE");
138 DPRINT1("Could not open the notification event (Error %lu)\n", GetLastError());
144 DPRINT("Wait for the LSA server!\n");
145 WaitForSingleObject(hEvent
, INFINITE
);
146 DPRINT("LSA server running!\n");
150 DPRINT("ScmWaitForLsa() done\n");
155 ScmNamedPipeHandleRequest(PVOID Request
,
160 DbgPrint("SCM READ: %s\n", Request
);
168 ScmNamedPipeThread(LPVOID Context
)
170 CHAR chRequest
[PIPE_BUFSIZE
];
171 CHAR chReply
[PIPE_BUFSIZE
];
178 hPipe
= (HANDLE
)Context
;
180 DPRINT("ScmNamedPipeThread(%x) - Accepting SCM commands through named pipe\n", hPipe
);
184 bSuccess
= ReadFile(hPipe
,
189 if (!bSuccess
|| cbBytesRead
== 0)
194 if (ScmNamedPipeHandleRequest(&chRequest
, cbBytesRead
, &chReply
, &cbReplyBytes
))
196 bSuccess
= WriteFile(hPipe
,
201 if (!bSuccess
|| cbReplyBytes
!= cbWritten
)
208 DPRINT("ScmNamedPipeThread(%x) - Disconnecting named pipe connection\n", hPipe
);
210 FlushFileBuffers(hPipe
);
211 DisconnectNamedPipe(hPipe
);
214 DPRINT("ScmNamedPipeThread(%x) - Done.\n", hPipe
);
216 return ERROR_SUCCESS
;
221 ScmCreateNamedPipe(VOID
)
228 DPRINT("ScmCreateNamedPipe() - CreateNamedPipe(\"\\\\.\\pipe\\Ntsvcs\")\n");
230 hPipe
= CreateNamedPipeW(L
"\\\\.\\pipe\\Ntsvcs",
232 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
,
233 PIPE_UNLIMITED_INSTANCES
,
238 if (hPipe
== INVALID_HANDLE_VALUE
)
240 DPRINT("CreateNamedPipe() failed (%d)\n", GetLastError());
244 DPRINT("CreateNamedPipe() - calling ConnectNamedPipe(%x)\n", hPipe
);
245 bConnected
= ConnectNamedPipe(hPipe
,
246 NULL
) ? TRUE
: (GetLastError() == ERROR_PIPE_CONNECTED
);
247 DPRINT("CreateNamedPipe() - ConnectNamedPipe() returned %d\n", bConnected
);
251 DPRINT("Pipe connected\n");
252 hThread
= CreateThread(NULL
,
260 DPRINT("Could not create thread (%d)\n", GetLastError());
261 DisconnectNamedPipe(hPipe
);
263 DPRINT("CreateNamedPipe() - returning FALSE\n");
267 CloseHandle(hThread
);
271 DPRINT("Pipe not connected\n");
273 DPRINT("CreateNamedPipe() - returning FALSE\n");
276 DPRINT("CreateNamedPipe() - returning TRUE\n");
282 ScmNamedPipeListenerThread(LPVOID Context
)
285 DPRINT("ScmNamedPipeListenerThread(%x) - aka SCM.\n", Context
);
287 // hPipe = (HANDLE)Context;
290 DPRINT("SCM: Waiting for new connection on named pipe...\n");
291 /* Create named pipe */
292 if (!ScmCreateNamedPipe())
294 DPRINT1("\nSCM: Failed to create named pipe\n");
298 DPRINT("\nSCM: named pipe session created.\n");
301 DPRINT("\n\nWARNING: ScmNamedPipeListenerThread(%x) - Aborted.\n\n", Context
);
302 return ERROR_SUCCESS
;
307 StartScmNamedPipeThreadListener(VOID
)
312 hThread
= CreateThread(NULL
,
314 ScmNamedPipeListenerThread
,
315 NULL
, /*(LPVOID)hPipe,*/
320 DPRINT1("SERVICES: Could not create thread (Status %lx)\n", GetLastError());
324 CloseHandle(hThread
);
331 AcquireLoadDriverPrivilege(VOID
)
334 TOKEN_PRIVILEGES tkp
;
336 /* Get a token for this process */
337 if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
, &hToken
))
339 /* Get the LUID for the debug privilege */
340 LookupPrivilegeValue(NULL
, SE_LOAD_DRIVER_NAME
, &tkp
.Privileges
[0].Luid
);
342 /* One privilege to set */
343 tkp
.PrivilegeCount
= 1;
344 tkp
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
346 /* Get the debug privilege for this process */
347 AdjustTokenPrivileges(hToken
, FALSE
, &tkp
, 0, (PTOKEN_PRIVILEGES
)NULL
, 0);
353 ShutdownHandlerRoutine(DWORD dwCtrlType
)
355 DPRINT1("ShutdownHandlerRoutine() called\n");
357 if (dwCtrlType
& (CTRL_SHUTDOWN_EVENT
| CTRL_LOGOFF_EVENT
))
359 DPRINT1("Shutdown event received!\n");
362 ScmAutoShutdownServices();
363 ScmShutdownServiceDatabase();
365 /* Set the shutdwon event */
366 SetEvent(hScmShutdownEvent
);
374 wWinMain(HINSTANCE hInstance
,
375 HINSTANCE hPrevInstance
,
379 HANDLE hScmStartEvent
= NULL
;
380 SC_RPC_LOCK Lock
= NULL
;
383 DPRINT("SERVICES: Service Control Manager\n");
385 /* Create start event */
386 if (!ScmCreateStartEvent(&hScmStartEvent
))
388 DPRINT1("SERVICES: Failed to create start event\n");
392 DPRINT("SERVICES: created start event with handle %p.\n", hScmStartEvent
);
394 /* Create the shutdown event */
395 hScmShutdownEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
396 if (hScmShutdownEvent
== NULL
)
398 DPRINT1("SERVICES: Failed to create shutdown event\n");
402 // ScmInitThreadManager();
404 /* FIXME: more initialization */
406 /* Create the service database */
407 dwError
= ScmCreateServiceDatabase();
408 if (dwError
!= ERROR_SUCCESS
)
410 DPRINT1("SERVICES: failed to create SCM database (Error %lu)\n", dwError
);
414 /* Update service database */
415 ScmGetBootAndSystemDriverState();
417 /* Start the RPC server */
420 /* Register service process with CSRSS */
421 RegisterServicesProcess(GetCurrentProcessId());
423 DPRINT("SERVICES: Initialized.\n");
425 /* Signal start event */
426 SetEvent(hScmStartEvent
);
428 /* Register event handler (used for system shutdown) */
429 SetConsoleCtrlHandler(ShutdownHandlerRoutine
, TRUE
);
431 /* Wait for the LSA server */
434 /* Acquire privileges to load drivers */
435 AcquireLoadDriverPrivilege();
437 ScmInitNamedPipeCriticalSection();
439 /* Acquire the service start lock until autostart services have been started */
440 dwError
= ScmAcquireServiceStartLock(TRUE
, &Lock
);
441 if (dwError
!= ERROR_SUCCESS
)
443 DPRINT1("SERVICES: failed to acquire the service start lock (Error %lu)\n", dwError
);
447 /* Start auto-start services */
448 ScmAutoStartServices();
450 /* FIXME: more to do ? */
452 /* Release the service start lock */
453 ScmReleaseServiceStartLock(&Lock
);
455 DPRINT("SERVICES: Running.\n");
457 /* Wait until the shutdown event gets signaled */
458 WaitForSingleObject(hScmShutdownEvent
, INFINITE
);
461 ScmDeleteNamedPipeCriticalSection();
463 /* Close the shutdown event */
464 if (hScmShutdownEvent
!= NULL
)
465 CloseHandle(hScmShutdownEvent
);
467 /* Close the start event */
468 if (hScmStartEvent
!= NULL
)
469 CloseHandle(hScmStartEvent
);
471 DPRINT("SERVICES: Finished.\n");