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
;
32 /* FUNCTIONS *****************************************************************/
35 PrintString(LPCSTR fmt
, ...)
42 vsprintf(buffer
, fmt
, ap
);
45 OutputDebugStringA(buffer
);
51 ScmCreateStartEvent(PHANDLE StartEvent
)
55 hEvent
= CreateEvent(NULL
,
58 TEXT("SvcctrlStartEvent_A3752DX"));
61 if (GetLastError() == ERROR_ALREADY_EXISTS
)
63 hEvent
= OpenEvent(EVENT_ALL_ACCESS
,
65 TEXT("SvcctrlStartEvent_A3752DX"));
89 hEvent
= CreateEventW(NULL
,
92 L
"LSA_RPC_SERVER_ACTIVE");
95 dwError
= GetLastError();
96 DPRINT("Failed to create the notication event (Error %lu)\n", dwError
);
98 if (dwError
== ERROR_ALREADY_EXISTS
)
100 hEvent
= OpenEventW(SYNCHRONIZE
,
102 L
"LSA_RPC_SERVER_ACTIVE");
105 DPRINT1("Could not open the notification event (Error %lu)\n", GetLastError());
111 DPRINT("Wait for the LSA server!\n");
112 WaitForSingleObject(hEvent
, INFINITE
);
113 DPRINT("LSA server running!\n");
120 ScmNamedPipeHandleRequest(PVOID Request
,
125 DbgPrint("SCM READ: %s\n", Request
);
133 ScmNamedPipeThread(LPVOID Context
)
135 CHAR chRequest
[PIPE_BUFSIZE
];
136 CHAR chReply
[PIPE_BUFSIZE
];
143 hPipe
= (HANDLE
)Context
;
145 DPRINT("ScmNamedPipeThread(%x) - Accepting SCM commands through named pipe\n", hPipe
);
149 bSuccess
= ReadFile(hPipe
,
154 if (!bSuccess
|| cbBytesRead
== 0)
159 if (ScmNamedPipeHandleRequest(&chRequest
, cbBytesRead
, &chReply
, &cbReplyBytes
))
161 bSuccess
= WriteFile(hPipe
,
166 if (!bSuccess
|| cbReplyBytes
!= cbWritten
)
173 DPRINT("ScmNamedPipeThread(%x) - Disconnecting named pipe connection\n", hPipe
);
175 FlushFileBuffers(hPipe
);
176 DisconnectNamedPipe(hPipe
);
179 DPRINT("ScmNamedPipeThread(%x) - Done.\n", hPipe
);
181 return ERROR_SUCCESS
;
186 ScmCreateNamedPipe(VOID
)
193 DPRINT("ScmCreateNamedPipe() - CreateNamedPipe(\"\\\\.\\pipe\\Ntsvcs\")\n");
195 hPipe
= CreateNamedPipe(TEXT("\\\\.\\pipe\\Ntsvcs"),
197 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
,
198 PIPE_UNLIMITED_INSTANCES
,
203 if (hPipe
== INVALID_HANDLE_VALUE
)
205 DPRINT("CreateNamedPipe() failed (%d)\n", GetLastError());
209 DPRINT("CreateNamedPipe() - calling ConnectNamedPipe(%x)\n", hPipe
);
210 bConnected
= ConnectNamedPipe(hPipe
,
211 NULL
) ? TRUE
: (GetLastError() == ERROR_PIPE_CONNECTED
);
212 DPRINT("CreateNamedPipe() - ConnectNamedPipe() returned %d\n", bConnected
);
216 DPRINT("Pipe connected\n");
217 hThread
= CreateThread(NULL
,
225 DPRINT("Could not create thread (%d)\n", GetLastError());
226 DisconnectNamedPipe(hPipe
);
228 DPRINT("CreateNamedPipe() - returning FALSE\n");
234 DPRINT("Pipe not connected\n");
236 DPRINT("CreateNamedPipe() - returning FALSE\n");
239 DPRINT("CreateNamedPipe() - returning TRUE\n");
245 ScmNamedPipeListenerThread(LPVOID Context
)
248 DPRINT("ScmNamedPipeListenerThread(%x) - aka SCM.\n", Context
);
250 // hPipe = (HANDLE)Context;
253 DPRINT("SCM: Waiting for new connection on named pipe...\n");
254 /* Create named pipe */
255 if (!ScmCreateNamedPipe())
257 DPRINT1("\nSCM: Failed to create named pipe\n");
261 DPRINT("\nSCM: named pipe session created.\n");
264 DPRINT("\n\nWARNING: ScmNamedPipeListenerThread(%x) - Aborted.\n\n", Context
);
265 return ERROR_SUCCESS
;
270 StartScmNamedPipeThreadListener(VOID
)
275 hThread
= CreateThread(NULL
,
277 ScmNamedPipeListenerThread
,
278 NULL
, /*(LPVOID)hPipe,*/
283 DPRINT1("SERVICES: Could not create thread (Status %lx)\n", GetLastError());
292 AcquireLoadDriverPrivilege(VOID
)
295 TOKEN_PRIVILEGES tkp
;
297 /* Get a token for this process */
298 if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
, &hToken
))
300 /* Get the LUID for the debug privilege */
301 LookupPrivilegeValue(NULL
, SE_LOAD_DRIVER_NAME
, &tkp
.Privileges
[0].Luid
);
303 /* One privilege to set */
304 tkp
.PrivilegeCount
= 1;
305 tkp
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
307 /* Get the debug privilege for this process */
308 AdjustTokenPrivileges(hToken
, FALSE
, &tkp
, 0, (PTOKEN_PRIVILEGES
)NULL
, 0);
314 ShutdownHandlerRoutine(DWORD dwCtrlType
)
316 DPRINT1("ShutdownHandlerRoutine() called\n");
318 if (dwCtrlType
& (CTRL_SHUTDOWN_EVENT
| CTRL_LOGOFF_EVENT
))
320 DPRINT1("Shutdown event received!\n");
323 ScmAutoShutdownServices();
324 ScmShutdownServiceDatabase();
332 wWinMain(HINSTANCE hInstance
,
333 HINSTANCE hPrevInstance
,
337 HANDLE hScmStartEvent
;
341 DPRINT("SERVICES: Service Control Manager\n");
343 /* Create start event */
344 if (!ScmCreateStartEvent(&hScmStartEvent
))
346 DPRINT1("SERVICES: Failed to create start event\n");
350 DPRINT("SERVICES: created start event with handle %x.\n", hScmStartEvent
);
352 // ScmInitThreadManager();
354 /* FIXME: more initialization */
357 /* Create the service database */
358 dwError
= ScmCreateServiceDatabase();
359 if (dwError
!= ERROR_SUCCESS
)
361 DPRINT1("SERVICES: failed to create SCM database (Error %lu)\n", dwError
);
365 /* Update service database */
366 ScmGetBootAndSystemDriverState();
368 /* Start the RPC server */
371 /* Register service process with CSRSS */
372 RegisterServicesProcess(GetCurrentProcessId());
374 DPRINT("SERVICES: Initialized.\n");
376 /* Signal start event */
377 SetEvent(hScmStartEvent
);
379 /* Register event handler (used for system shutdown) */
380 SetConsoleCtrlHandler(ShutdownHandlerRoutine
, TRUE
);
382 /* Wait for the LSA server */
385 /* Acquire privileges to load drivers */
386 AcquireLoadDriverPrivilege();
388 ScmInitNamedPipeCriticalSection();
390 /* Start auto-start services */
391 ScmAutoStartServices();
393 /* FIXME: more to do ? */
396 DPRINT("SERVICES: Running.\n");
399 hEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
401 WaitForSingleObject(hEvent
, INFINITE
);
409 ScmDeleteNamedPipeCriticalSection();
411 CloseHandle(hScmStartEvent
);
413 DPRINT("SERVICES: Finished.\n");