6a7eb53c87068e46ec8d4f30d613dbbcc82ddd5e
[reactos.git] / reactos / subsys / system / services / services.c
1 /* $Id$
2 *
3 * service control manager
4 *
5 * ReactOS Operating System
6 *
7 * --------------------------------------------------------------------
8 *
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.
13 *
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.
18 *
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,
22 * MA 02139, USA.
23 *
24 */
25
26 /* NOTE:
27 * - Services.exe is NOT a native application, it is a GUI app.
28 */
29
30 /* INCLUDES *****************************************************************/
31
32 #include "services.h"
33
34 #define NDEBUG
35 #include <debug.h>
36
37 int WINAPI RegisterServicesProcess(DWORD ServicesProcessId);
38
39 /* GLOBALS ******************************************************************/
40
41 #define PIPE_BUFSIZE 1024
42 #define PIPE_TIMEOUT 1000
43
44
45 /* FUNCTIONS *****************************************************************/
46
47 VOID
48 PrintString(LPCSTR fmt, ...)
49 {
50 #ifdef DBG
51 CHAR buffer[512];
52 va_list ap;
53
54 va_start(ap, fmt);
55 vsprintf(buffer, fmt, ap);
56 va_end(ap);
57
58 OutputDebugStringA(buffer);
59 #endif
60 }
61
62
63 BOOL
64 ScmCreateStartEvent(PHANDLE StartEvent)
65 {
66 HANDLE hEvent;
67
68 hEvent = CreateEvent(NULL,
69 TRUE,
70 FALSE,
71 TEXT("SvcctrlStartEvent_A3725DX"));
72 if (hEvent == NULL)
73 {
74 if (GetLastError() == ERROR_ALREADY_EXISTS)
75 {
76 hEvent = OpenEvent(EVENT_ALL_ACCESS,
77 FALSE,
78 TEXT("SvcctrlStartEvent_A3725DX"));
79 if (hEvent == NULL)
80 {
81 return FALSE;
82 }
83 }
84 else
85 {
86 return FALSE;
87 }
88 }
89
90 *StartEvent = hEvent;
91
92 return TRUE;
93 }
94
95
96 BOOL
97 ScmNamedPipeHandleRequest(PVOID Request,
98 DWORD RequestSize,
99 PVOID Reply,
100 LPDWORD ReplySize)
101 {
102 DbgPrint("SCM READ: %s\n", Request);
103
104 *ReplySize = 0;
105 return FALSE;
106 }
107
108
109 DWORD WINAPI
110 ScmNamedPipeThread(LPVOID Context)
111 {
112 CHAR chRequest[PIPE_BUFSIZE];
113 CHAR chReply[PIPE_BUFSIZE];
114 DWORD cbReplyBytes;
115 DWORD cbBytesRead;
116 DWORD cbWritten;
117 BOOL fSuccess;
118 HANDLE hPipe;
119
120 hPipe = (HANDLE)Context;
121
122 DPRINT("ScmNamedPipeThread(%x) - Accepting SCM commands through named pipe\n", hPipe);
123
124 for (;;) {
125 fSuccess = ReadFile(hPipe,
126 &chRequest,
127 PIPE_BUFSIZE,
128 &cbBytesRead,
129 NULL);
130 if (!fSuccess || cbBytesRead == 0) {
131 break;
132 }
133 if (ScmNamedPipeHandleRequest(&chRequest, cbBytesRead, &chReply, &cbReplyBytes)) {
134 fSuccess = WriteFile(hPipe,
135 &chReply,
136 cbReplyBytes,
137 &cbWritten,
138 NULL);
139 if (!fSuccess || cbReplyBytes != cbWritten) {
140 break;
141 }
142 }
143 }
144 DPRINT("ScmNamedPipeThread(%x) - Disconnecting named pipe connection\n", hPipe);
145 FlushFileBuffers(hPipe);
146 DisconnectNamedPipe(hPipe);
147 CloseHandle(hPipe);
148 DPRINT("ScmNamedPipeThread(%x) - Done.\n", hPipe);
149 return ERROR_SUCCESS;
150 }
151
152
153 BOOL
154 ScmCreateNamedPipe(VOID)
155 {
156 DWORD dwThreadId;
157 BOOL fConnected;
158 HANDLE hThread;
159 HANDLE hPipe;
160
161 DPRINT("ScmCreateNamedPipe() - CreateNamedPipe(\"\\\\.\\pipe\\Ntsvcs\")\n");
162
163 hPipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\Ntsvcs"),
164 PIPE_ACCESS_DUPLEX,
165 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
166 PIPE_UNLIMITED_INSTANCES,
167 PIPE_BUFSIZE,
168 PIPE_BUFSIZE,
169 PIPE_TIMEOUT,
170 NULL);
171 if (hPipe == INVALID_HANDLE_VALUE) {
172 DPRINT("CreateNamedPipe() failed (%d)\n", GetLastError());
173 return FALSE;
174 }
175
176 DPRINT("CreateNamedPipe() - calling ConnectNamedPipe(%x)\n", hPipe);
177 fConnected = ConnectNamedPipe(hPipe,
178 NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
179 DPRINT("CreateNamedPipe() - ConnectNamedPipe() returned %d\n", fConnected);
180
181 if (fConnected) {
182 DPRINT("Pipe connected\n");
183 hThread = CreateThread(NULL,
184 0,
185 ScmNamedPipeThread,
186 (LPVOID)hPipe,
187 0,
188 &dwThreadId);
189 if (!hThread) {
190 DPRINT("Could not create thread (%d)\n", GetLastError());
191 DisconnectNamedPipe(hPipe);
192 CloseHandle(hPipe);
193 DPRINT("CreateNamedPipe() - returning FALSE\n");
194 return FALSE;
195 }
196 } else {
197 DPRINT("Pipe not connected\n");
198 CloseHandle(hPipe);
199 DPRINT("CreateNamedPipe() - returning FALSE\n");
200 return FALSE;
201 }
202 DPRINT("CreateNamedPipe() - returning TRUE\n");
203 return TRUE;
204 }
205
206
207 DWORD WINAPI
208 ScmNamedPipeListenerThread(LPVOID Context)
209 {
210 // HANDLE hPipe;
211 DPRINT("ScmNamedPipeListenerThread(%x) - aka SCM.\n", Context);
212
213 // hPipe = (HANDLE)Context;
214 for (;;) {
215 DPRINT("SCM: Waiting for new connection on named pipe...\n");
216 /* Create named pipe */
217 if (!ScmCreateNamedPipe()) {
218 DPRINT1("\nSCM: Failed to create named pipe\n");
219 break;
220 //ExitThread(0);
221 }
222 DPRINT("\nSCM: named pipe session created.\n");
223 Sleep(10);
224 }
225 DPRINT("\n\nWARNING: ScmNamedPipeListenerThread(%x) - Aborted.\n\n", Context);
226 return ERROR_SUCCESS;
227 }
228
229
230 BOOL
231 StartScmNamedPipeThreadListener(VOID)
232 {
233 DWORD dwThreadId;
234 HANDLE hThread;
235
236 hThread = CreateThread(NULL,
237 0,
238 ScmNamedPipeListenerThread,
239 NULL, /*(LPVOID)hPipe,*/
240 0,
241 &dwThreadId);
242 if (!hThread)
243 {
244 DPRINT1("SERVICES: Could not create thread (Status %lx)\n", GetLastError());
245 return FALSE;
246 }
247
248 return TRUE;
249 }
250
251
252 VOID FASTCALL
253 AcquireLoadDriverPrivilege(VOID)
254 {
255 HANDLE hToken;
256 TOKEN_PRIVILEGES tkp;
257
258 /* Get a token for this process */
259 if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
260 {
261 /* Get the LUID for the debug privilege */
262 LookupPrivilegeValue(NULL, SE_LOAD_DRIVER_NAME, &tkp.Privileges[0].Luid);
263
264 /* One privilege to set */
265 tkp.PrivilegeCount = 1;
266 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
267
268 /* Get the debug privilege for this process */
269 AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
270 }
271 }
272
273
274 int STDCALL
275 WinMain(HINSTANCE hInstance,
276 HINSTANCE hPrevInstance,
277 LPSTR lpCmdLine,
278 int nShowCmd)
279 {
280 HANDLE hScmStartEvent;
281 HANDLE hEvent;
282 NTSTATUS Status;
283
284 DPRINT("SERVICES: Service Control Manager\n");
285
286 /* Acquire privileges to load drivers */
287 AcquireLoadDriverPrivilege();
288
289 /* Create start event */
290 if (!ScmCreateStartEvent(&hScmStartEvent))
291 {
292 DPRINT1("SERVICES: Failed to create start event\n");
293 ExitThread(0);
294 }
295
296 DPRINT("SERVICES: created start event with handle %x.\n", hScmStartEvent);
297
298 // ScmInitThreadManager();
299
300 /* FIXME: more initialization */
301
302
303 /* Create the service database */
304 Status = ScmCreateServiceDataBase();
305 if (!NT_SUCCESS(Status))
306 {
307 DPRINT1("SERVICES: failed to create SCM database (Status %lx)\n", Status);
308 ExitThread(0);
309 }
310
311 /* Update service database */
312 ScmGetBootAndSystemDriverState();
313
314 /* Start the RPC server */
315 ScmStartRpcServer();
316
317 /* Register service process with CSRSS */
318 // RegisterServicesProcess(GetCurrentProcessId());
319
320 DPRINT("SERVICES: Initialized.\n");
321
322 /* Signal start event */
323 SetEvent(hScmStartEvent);
324
325 #if 0
326 /* FIXME: register event handler (used for system shutdown) */
327 SetConsoleCtrlHandler(...);
328 #endif
329
330 /* Start auto-start services */
331 ScmAutoStartServices();
332
333 /* FIXME: more to do ? */
334
335
336 DPRINT("SERVICES: Running.\n");
337
338 #if 1
339 hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
340 WaitForSingleObject(hEvent, INFINITE);
341 #else
342 for (;;)
343 {
344 NtYieldExecution();
345 }
346 #endif
347
348 DPRINT("SERVICES: Finished.\n");
349
350 ExitThread(0);
351
352 return 0;
353 }
354
355 /* EOF */