merge ROS Shell without integrated explorer part into trunk
[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 int WINAPI RegisterServicesProcess(DWORD ServicesProcessId);
44
45 /* GLOBALS ******************************************************************/
46
47 #define PIPE_BUFSIZE 1024
48 #define PIPE_TIMEOUT 1000
49
50
51 /* FUNCTIONS *****************************************************************/
52
53 VOID
54 PrintString(LPCSTR 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 {
80 if (GetLastError() == ERROR_ALREADY_EXISTS)
81 {
82 hEvent = OpenEvent(EVENT_ALL_ACCESS,
83 FALSE,
84 _T("SvcctrlStartEvent_A3725DX"));
85 if (hEvent == NULL)
86 {
87 return FALSE;
88 }
89 }
90 else
91 {
92 return FALSE;
93 }
94 }
95
96 *StartEvent = hEvent;
97
98 return TRUE;
99 }
100
101
102 BOOL
103 ScmNamedPipeHandleRequest(PVOID Request,
104 DWORD RequestSize,
105 PVOID Reply,
106 LPDWORD ReplySize)
107 {
108 DbgPrint("SCM READ: %s\n", Request);
109
110 *ReplySize = 0;
111 return FALSE;
112 }
113
114
115 DWORD WINAPI
116 ScmNamedPipeThread(LPVOID Context)
117 {
118 CHAR chRequest[PIPE_BUFSIZE];
119 CHAR chReply[PIPE_BUFSIZE];
120 DWORD cbReplyBytes;
121 DWORD cbBytesRead;
122 DWORD cbWritten;
123 BOOL fSuccess;
124 HANDLE hPipe;
125
126 hPipe = (HANDLE)Context;
127
128 DPRINT("ScmNamedPipeThread(%x) - Accepting SCM commands through named pipe\n", hPipe);
129
130 for (;;) {
131 fSuccess = ReadFile(hPipe,
132 &chRequest,
133 PIPE_BUFSIZE,
134 &cbBytesRead,
135 NULL);
136 if (!fSuccess || cbBytesRead == 0) {
137 break;
138 }
139 if (ScmNamedPipeHandleRequest(&chRequest, cbBytesRead, &chReply, &cbReplyBytes)) {
140 fSuccess = WriteFile(hPipe,
141 &chReply,
142 cbReplyBytes,
143 &cbWritten,
144 NULL);
145 if (!fSuccess || cbReplyBytes != cbWritten) {
146 break;
147 }
148 }
149 }
150 DPRINT("ScmNamedPipeThread(%x) - Disconnecting named pipe connection\n", hPipe);
151 FlushFileBuffers(hPipe);
152 DisconnectNamedPipe(hPipe);
153 CloseHandle(hPipe);
154 DPRINT("ScmNamedPipeThread(%x) - Done.\n", hPipe);
155 return ERROR_SUCCESS;
156 }
157
158
159 BOOL
160 ScmCreateNamedPipe(VOID)
161 {
162 DWORD dwThreadId;
163 BOOL fConnected;
164 HANDLE hThread;
165 HANDLE hPipe;
166
167 DPRINT("ScmCreateNamedPipe() - CreateNamedPipe(\"\\\\.\\pipe\\Ntsvcs\")\n");
168
169 hPipe = CreateNamedPipe(_T("\\\\.\\pipe\\Ntsvcs"),
170 PIPE_ACCESS_DUPLEX,
171 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
172 PIPE_UNLIMITED_INSTANCES,
173 PIPE_BUFSIZE,
174 PIPE_BUFSIZE,
175 PIPE_TIMEOUT,
176 NULL);
177 if (hPipe == INVALID_HANDLE_VALUE) {
178 DPRINT("CreateNamedPipe() failed (%d)\n", GetLastError());
179 return FALSE;
180 }
181
182 DPRINT("CreateNamedPipe() - calling ConnectNamedPipe(%x)\n", hPipe);
183 fConnected = ConnectNamedPipe(hPipe,
184 NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
185 DPRINT("CreateNamedPipe() - ConnectNamedPipe() returned %d\n", fConnected);
186
187 if (fConnected) {
188 DPRINT("Pipe connected\n");
189 hThread = CreateThread(NULL,
190 0,
191 ScmNamedPipeThread,
192 (LPVOID)hPipe,
193 0,
194 &dwThreadId);
195 if (!hThread) {
196 DPRINT("Could not create thread (%d)\n", GetLastError());
197 DisconnectNamedPipe(hPipe);
198 CloseHandle(hPipe);
199 DPRINT("CreateNamedPipe() - returning FALSE\n");
200 return FALSE;
201 }
202 } else {
203 DPRINT("Pipe not connected\n");
204 CloseHandle(hPipe);
205 DPRINT("CreateNamedPipe() - returning FALSE\n");
206 return FALSE;
207 }
208 DPRINT("CreateNamedPipe() - returning TRUE\n");
209 return TRUE;
210 }
211
212
213 DWORD WINAPI
214 ScmNamedPipeListenerThread(LPVOID Context)
215 {
216 // HANDLE hPipe;
217 DPRINT("ScmNamedPipeListenerThread(%x) - aka SCM.\n", Context);
218
219 // hPipe = (HANDLE)Context;
220 for (;;) {
221 DPRINT("SCM: Waiting for new connection on named pipe...\n");
222 /* Create named pipe */
223 if (!ScmCreateNamedPipe()) {
224 DPRINT1("\nSCM: Failed to create named pipe\n");
225 break;
226 //ExitThread(0);
227 }
228 DPRINT("\nSCM: named pipe session created.\n");
229 Sleep(10);
230 }
231 DPRINT("\n\nWARNING: ScmNamedPipeListenerThread(%x) - Aborted.\n\n", Context);
232 return ERROR_SUCCESS;
233 }
234
235
236 BOOL
237 StartScmNamedPipeThreadListener(VOID)
238 {
239 DWORD dwThreadId;
240 HANDLE hThread;
241
242 hThread = CreateThread(NULL,
243 0,
244 ScmNamedPipeListenerThread,
245 NULL, /*(LPVOID)hPipe,*/
246 0,
247 &dwThreadId);
248 if (!hThread)
249 {
250 DPRINT1("SERVICES: Could not create thread (Status %lx)\n", GetLastError());
251 return FALSE;
252 }
253
254 return TRUE;
255 }
256
257
258 VOID FASTCALL
259 AcquireLoadDriverPrivilege(VOID)
260 {
261 HANDLE hToken;
262 TOKEN_PRIVILEGES tkp;
263
264 /* Get a token for this process */
265 if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
266 {
267 /* Get the LUID for the debug privilege */
268 LookupPrivilegeValue(NULL, SE_LOAD_DRIVER_NAME, &tkp.Privileges[0].Luid);
269
270 /* One privilege to set */
271 tkp.PrivilegeCount = 1;
272 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
273
274 /* Get the debug privilege for this process */
275 AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
276 }
277 }
278
279
280 int STDCALL
281 WinMain(HINSTANCE hInstance,
282 HINSTANCE hPrevInstance,
283 LPSTR lpCmdLine,
284 int nShowCmd)
285 {
286 HANDLE hScmStartEvent;
287 HANDLE hEvent;
288 NTSTATUS Status;
289
290 DPRINT("SERVICES: Service Control Manager\n");
291
292 /* Acquire privileges to load drivers */
293 AcquireLoadDriverPrivilege();
294
295 /* Create start event */
296 if (!ScmCreateStartEvent(&hScmStartEvent))
297 {
298 DPRINT1("SERVICES: Failed to create start event\n");
299 ExitThread(0);
300 }
301
302 DPRINT("SERVICES: created start event with handle %x.\n", hScmStartEvent);
303
304 // ScmInitThreadManager();
305
306 /* FIXME: more initialization */
307
308
309 /* Create the service database */
310 Status = ScmCreateServiceDataBase();
311 if (!NT_SUCCESS(Status))
312 {
313 DPRINT1("SERVICES: failed to create SCM database (Status %lx)\n", Status);
314 ExitThread(0);
315 }
316
317 /* Update service database */
318 ScmGetBootAndSystemDriverState();
319
320 /* Start the RPC server */
321 ScmStartRpcServer();
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 #if 0
332 /* FIXME: register event handler (used for system shutdown) */
333 SetConsoleCtrlHandler(...);
334 #endif
335
336 /* Start auto-start services */
337 ScmAutoStartServices();
338
339 /* FIXME: more to do ? */
340
341
342 DPRINT("SERVICES: Running.\n");
343
344 #if 1
345 hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
346 WaitForSingleObject(hEvent, INFINITE);
347 #else
348 for (;;)
349 {
350 NtYieldExecution();
351 }
352 #endif
353
354 DPRINT("SERVICES: Finished.\n");
355
356 ExitThread(0);
357
358 return 0;
359 }
360
361 /* EOF */