3 * service control manager
5 * ReactOS Operating System
7 * --------------------------------------------------------------------
9 * This software is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) any later version.
14 * This software is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this software; see the file COPYING.LIB. If not, write
21 * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
27 * - Services.exe is NOT a native application, it is a GUI app.
30 /* INCLUDES *****************************************************************/
32 #define NTOS_MODE_USER
45 /* GLOBALS ******************************************************************/
47 #define PIPE_BUFSIZE 1024
48 #define PIPE_TIMEOUT 1000
51 /* FUNCTIONS *****************************************************************/
54 PrintString(char* fmt
,...)
61 vsprintf(buffer
, fmt
, ap
);
64 OutputDebugStringA(buffer
);
70 ScmCreateStartEvent(PHANDLE StartEvent
)
74 hEvent
= CreateEvent(NULL
,
77 _T("SvcctrlStartEvent_A3725DX"));
79 if (GetLastError() == ERROR_ALREADY_EXISTS
) {
80 hEvent
= OpenEvent(EVENT_ALL_ACCESS
,
82 _T("SvcctrlStartEvent_A3725DX"));
96 ScmNamedPipeHandleRequest(
102 DbgPrint("SCM READ: %s\n", Request
);
111 ScmNamedPipeThread(LPVOID Context
)
113 CHAR chRequest
[PIPE_BUFSIZE
];
114 CHAR chReply
[PIPE_BUFSIZE
];
121 hPipe
= (HANDLE
)Context
;
123 DPRINT("ScmNamedPipeThread(%x) - Accepting SCM commands through named pipe\n", hPipe
);
126 fSuccess
= ReadFile(hPipe
,
131 if (!fSuccess
|| cbBytesRead
== 0) {
134 if (ScmNamedPipeHandleRequest(&chRequest
, cbBytesRead
, &chReply
, &cbReplyBytes
)) {
135 fSuccess
= WriteFile(hPipe
,
140 if (!fSuccess
|| cbReplyBytes
!= cbWritten
) {
145 DPRINT("ScmNamedPipeThread(%x) - Disconnecting named pipe connection\n", hPipe
);
146 FlushFileBuffers(hPipe
);
147 DisconnectNamedPipe(hPipe
);
149 DPRINT("ScmNamedPipeThread(%x) - Done.\n", hPipe
);
150 return ERROR_SUCCESS
;
153 BOOL
ScmCreateNamedPipe(VOID
)
160 DPRINT("ScmCreateNamedPipe() - CreateNamedPipe(\"\\\\.\\pipe\\Ntsvcs\")\n");
162 hPipe
= CreateNamedPipe("\\\\.\\pipe\\Ntsvcs",
164 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
,
165 PIPE_UNLIMITED_INSTANCES
,
170 if (hPipe
== INVALID_HANDLE_VALUE
) {
171 DPRINT("CreateNamedPipe() failed (%d)\n", GetLastError());
175 DPRINT("CreateNamedPipe() - calling ConnectNamedPipe(%x)\n", hPipe
);
176 fConnected
= ConnectNamedPipe(hPipe
,
177 NULL
) ? TRUE
: (GetLastError() == ERROR_PIPE_CONNECTED
);
178 DPRINT("CreateNamedPipe() - ConnectNamedPipe() returned %d\n", fConnected
);
181 DPRINT("Pipe connected\n");
182 hThread
= CreateThread(NULL
,
189 DPRINT("Could not create thread (%d)\n", GetLastError());
190 DisconnectNamedPipe(hPipe
);
192 DPRINT("CreateNamedPipe() - returning FALSE\n");
196 DPRINT("Pipe not connected\n");
198 DPRINT("CreateNamedPipe() - returning FALSE\n");
201 DPRINT("CreateNamedPipe() - returning TRUE\n");
207 ScmNamedPipeListenerThread(LPVOID Context
)
210 DPRINT("ScmNamedPipeListenerThread(%x) - aka SCM.\n", Context
);
212 // hPipe = (HANDLE)Context;
214 DPRINT("SCM: Waiting for new connection on named pipe...\n");
215 /* Create named pipe */
216 if (!ScmCreateNamedPipe()) {
217 DPRINT1("\nSCM: Failed to create named pipe\n");
221 DPRINT("\nSCM: named pipe session created.\n");
224 DPRINT("\n\nWARNING: ScmNamedPipeListenerThread(%x) - Aborted.\n\n", Context
);
225 return ERROR_SUCCESS
;
228 BOOL
StartScmNamedPipeThreadListener(void)
233 hThread
= CreateThread(NULL
,
235 ScmNamedPipeListenerThread
,
236 NULL
, /*(LPVOID)hPipe,*/
241 DPRINT1("SERVICES: Could not create thread (Status %lx)\n", GetLastError());
248 AcquireLoadDriverPrivilege(VOID
)
251 TOKEN_PRIVILEGES tkp
;
253 /* Get a token for this process. */
254 if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
, &hToken
)) {
255 /* Get the LUID for the debug privilege. */
256 LookupPrivilegeValue(NULL
, SE_LOAD_DRIVER_NAME
, &tkp
.Privileges
[0].Luid
);
258 tkp
.PrivilegeCount
= 1; /* one privilege to set */
259 tkp
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
261 /* Get the debug privilege for this process. */
262 AdjustTokenPrivileges(hToken
, FALSE
, &tkp
, 0, (PTOKEN_PRIVILEGES
)NULL
, 0);
267 WinMain(HINSTANCE hInstance
,
268 HINSTANCE hPrevInstance
,
272 HANDLE hScmStartEvent
;
276 DPRINT("SERVICES: Service Control Manager\n");
278 /* Acquire privileges to load drivers */
279 AcquireLoadDriverPrivilege();
281 /* Create start event */
282 if (!ScmCreateStartEvent(&hScmStartEvent
))
284 DPRINT1("SERVICES: Failed to create start event\n");
288 DPRINT("SERVICES: created start event with handle %x.\n", hScmStartEvent
);
290 /* FIXME: more initialization */
293 /* Create the service database */
294 Status
= ScmCreateServiceDataBase();
295 if (!NT_SUCCESS(Status
))
297 DPRINT1("SERVICES: failed to create SCM database (Status %lx)\n", Status
);
301 /* Update service database */
302 ScmGetBootAndSystemDriverState();
305 DPRINT("SERVICES: Attempting to create named pipe...\n");
306 /* Create named pipe */
307 if (!ScmCreateNamedPipe()) {
308 DPRINT1("SERVICES: Failed to create named pipe\n");
311 DPRINT("SERVICES: named pipe created successfully.\n");
313 DPRINT("SERVICES: Attempting to create named pipe listener...\n");
314 if (!StartScmNamedPipeThreadListener()) {
315 DPRINT1("SERVICES: Failed to create named pipe listener thread.\n");
318 DPRINT("SERVICES: named pipe listener thread created.\n");
320 /* FIXME: create listener thread for pipe */
323 /* Register service process with CSRSS */
324 RegisterServicesProcess(GetCurrentProcessId());
326 DPRINT("SERVICES: Initialized.\n");
328 /* Signal start event */
329 SetEvent(hScmStartEvent
);
331 /* FIXME: register event handler (used for system shutdown) */
332 // SetConsoleCtrlHandler(...);
335 /* Start auto-start services */
336 ScmAutoStartServices();
338 /* FIXME: more to do ? */
341 DPRINT("SERVICES: Running.\n");
344 hEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
345 WaitForSingleObject(hEvent
, INFINITE
);
353 DPRINT("SERVICES: Finished.\n");