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