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 ScmCreateEvent(PHANDLE Event
,
56 hEvent
= CreateEventW(NULL
,
62 if (GetLastError() == ERROR_ALREADY_EXISTS
)
64 hEvent
= OpenEventW(EVENT_ALL_ACCESS
,
72 DPRINT("SERVICES: created event %S with handle %x\n", Name
, hEvent
);
77 DPRINT1("SERVICES: Failed to create event %S\n", Name
);
83 ScmNamedPipeHandleRequest(PVOID Request
,
88 DbgPrint("SCM READ: %s\n", Request
);
96 ScmNamedPipeThread(LPVOID Context
)
98 CHAR chRequest
[PIPE_BUFSIZE
];
99 CHAR chReply
[PIPE_BUFSIZE
];
106 hPipe
= (HANDLE
)Context
;
108 DPRINT("ScmNamedPipeThread(%x) - Accepting SCM commands through named pipe\n", hPipe
);
112 bSuccess
= ReadFile(hPipe
,
117 if (!bSuccess
|| cbBytesRead
== 0)
122 if (ScmNamedPipeHandleRequest(&chRequest
, cbBytesRead
, &chReply
, &cbReplyBytes
))
124 bSuccess
= WriteFile(hPipe
,
129 if (!bSuccess
|| cbReplyBytes
!= cbWritten
)
136 DPRINT("ScmNamedPipeThread(%x) - Disconnecting named pipe connection\n", hPipe
);
138 FlushFileBuffers(hPipe
);
139 DisconnectNamedPipe(hPipe
);
142 DPRINT("ScmNamedPipeThread(%x) - Done.\n", hPipe
);
144 return ERROR_SUCCESS
;
149 ScmCreateNamedPipe(VOID
)
156 DPRINT("ScmCreateNamedPipe() - CreateNamedPipe(\"\\\\.\\pipe\\Ntsvcs\")\n");
158 hPipe
= CreateNamedPipe(TEXT("\\\\.\\pipe\\Ntsvcs"),
160 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
,
161 PIPE_UNLIMITED_INSTANCES
,
166 if (hPipe
== INVALID_HANDLE_VALUE
)
168 DPRINT("CreateNamedPipe() failed (%d)\n", GetLastError());
172 DPRINT("CreateNamedPipe() - calling ConnectNamedPipe(%x)\n", hPipe
);
173 bConnected
= ConnectNamedPipe(hPipe
,
174 NULL
) ? TRUE
: (GetLastError() == ERROR_PIPE_CONNECTED
);
175 DPRINT("CreateNamedPipe() - ConnectNamedPipe() returned %d\n", bConnected
);
179 DPRINT("Pipe connected\n");
180 hThread
= CreateThread(NULL
,
188 DPRINT("Could not create thread (%d)\n", GetLastError());
189 DisconnectNamedPipe(hPipe
);
191 DPRINT("CreateNamedPipe() - returning FALSE\n");
197 DPRINT("Pipe not connected\n");
199 DPRINT("CreateNamedPipe() - returning FALSE\n");
202 DPRINT("CreateNamedPipe() - returning TRUE\n");
208 ScmNamedPipeListenerThread(LPVOID Context
)
211 DPRINT("ScmNamedPipeListenerThread(%x) - aka SCM.\n", Context
);
213 // hPipe = (HANDLE)Context;
216 DPRINT("SCM: Waiting for new connection on named pipe...\n");
217 /* Create named pipe */
218 if (!ScmCreateNamedPipe())
220 DPRINT1("\nSCM: Failed to create named pipe\n");
224 DPRINT("\nSCM: named pipe session created.\n");
227 DPRINT("\n\nWARNING: ScmNamedPipeListenerThread(%x) - Aborted.\n\n", Context
);
228 return ERROR_SUCCESS
;
233 StartScmNamedPipeThreadListener(VOID
)
238 hThread
= CreateThread(NULL
,
240 ScmNamedPipeListenerThread
,
241 NULL
, /*(LPVOID)hPipe,*/
246 DPRINT1("SERVICES: Could not create thread (Status %lx)\n", GetLastError());
255 AcquireLoadDriverPrivilege(VOID
)
258 TOKEN_PRIVILEGES tkp
;
260 /* Get a token for this process */
261 if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
, &hToken
))
263 /* Get the LUID for the debug privilege */
264 LookupPrivilegeValue(NULL
, SE_LOAD_DRIVER_NAME
, &tkp
.Privileges
[0].Luid
);
266 /* One privilege to set */
267 tkp
.PrivilegeCount
= 1;
268 tkp
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
270 /* Get the debug privilege for this process */
271 AdjustTokenPrivileges(hToken
, FALSE
, &tkp
, 0, (PTOKEN_PRIVILEGES
)NULL
, 0);
277 ShutdownHandlerRoutine(DWORD dwCtrlType
)
279 DPRINT1("ShutdownHandlerRoutine() called\n");
281 if (dwCtrlType
== CTRL_SHUTDOWN_EVENT
)
283 DPRINT1("Shutdown event received!\n");
286 ScmAutoShutdownServices();
287 ScmShutdownServiceDatabase();
295 wWinMain(HINSTANCE hInstance
,
296 HINSTANCE hPrevInstance
,
300 HANDLE hScmStartEvent
;
301 HANDLE hScmAutoStartCompleteEvent
;
305 DPRINT("SERVICES: Service Control Manager\n");
307 /* Acquire privileges to load drivers */
308 AcquireLoadDriverPrivilege();
311 if (!ScmCreateEvent(&hScmAutoStartCompleteEvent
, L
"SC_AutoStartComplete"))
316 if (!ScmCreateEvent(&hScmStartEvent
, L
"SvcctrlStartEvent_A3752DX"))
321 // ScmInitThreadManager();
323 /* FIXME: more initialization */
326 /* Create the service database */
327 dwError
= ScmCreateServiceDatabase();
328 if (dwError
!= ERROR_SUCCESS
)
330 DPRINT1("SERVICES: failed to create SCM database (Error %lu)\n", dwError
);
334 /* Update service database */
335 ScmGetBootAndSystemDriverState();
337 /* Start the RPC server */
340 /* Register service process with CSRSS */
341 RegisterServicesProcess(GetCurrentProcessId());
343 DPRINT("SERVICES: Initialized.\n");
345 /* Signal start event */
346 SetEvent(hScmStartEvent
);
348 /* Register event handler (used for system shutdown) */
349 SetConsoleCtrlHandler(ShutdownHandlerRoutine
, TRUE
);
351 /* Start auto-start services */
352 ScmAutoStartServices();
354 /* FIXME: more to do ? */
357 DPRINT("SERVICES: Running.\n");
359 /* Signal complete event */
360 SetEvent(hScmAutoStartCompleteEvent
);
363 hEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
365 WaitForSingleObject(hEvent
, INFINITE
);
373 CloseHandle(hScmStartEvent
);
375 DPRINT("SERVICES: Finished.\n");