c2d17cc4337ba65f3a8eda08068272a332936382
[reactos.git] / 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 <windows.h>
35
36 #include "services.h"
37
38 #define DBG
39 //#define NDEBUG
40 #include <debug.h>
41
42
43
44 /* GLOBALS ******************************************************************/
45
46 #define PIPE_BUFSIZE 1024
47 #define PIPE_TIMEOUT 1000
48
49
50 /* FUNCTIONS *****************************************************************/
51
52 void
53 PrintString(char* fmt,...)
54 {
55 #ifdef DBG
56     char buffer[512];
57     va_list ap;
58
59     va_start(ap, fmt);
60     vsprintf(buffer, fmt, ap);
61     va_end(ap);
62
63     OutputDebugStringA(buffer);
64 #endif
65 }
66
67
68 BOOL
69 ScmCreateStartEvent(PHANDLE StartEvent)
70 {
71     HANDLE hEvent;
72
73     hEvent = CreateEvent(NULL,
74                          TRUE,
75                          FALSE,
76                          _T("SvcctrlStartEvent_A3725DX"));
77     if (hEvent == NULL) {
78         if (GetLastError() == ERROR_ALREADY_EXISTS) {
79             hEvent = OpenEvent(EVENT_ALL_ACCESS,
80                                FALSE,
81                                _T("SvcctrlStartEvent_A3725DX"));
82             if (hEvent == NULL) {
83                 return FALSE;
84             }
85         } else {
86             return FALSE;
87         }
88     }
89     *StartEvent = hEvent;
90     return TRUE;
91 }
92
93
94 BOOL
95 ScmNamedPipeHandleRequest(
96     PVOID Request,
97     DWORD RequestSize,
98     PVOID Reply,
99     LPDWORD ReplySize)
100 {
101     DbgPrint("SCM READ: %s\n", Request);
102
103     *ReplySize = 0;
104     return FALSE;
105 }
106
107
108 DWORD
109 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 BOOL ScmCreateNamedPipe(VOID)
153 {
154     DWORD dwThreadId;
155     BOOL fConnected;
156     HANDLE hThread;
157     HANDLE hPipe;
158
159     DPRINT("ScmCreateNamedPipe() - CreateNamedPipe(\"\\\\.\\pipe\\Ntsvcs\")\n");
160
161     hPipe = CreateNamedPipe("\\\\.\\pipe\\Ntsvcs",
162               PIPE_ACCESS_DUPLEX,
163               PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
164               PIPE_UNLIMITED_INSTANCES,
165               PIPE_BUFSIZE,
166               PIPE_BUFSIZE,
167               PIPE_TIMEOUT,
168               NULL);
169     if (hPipe == INVALID_HANDLE_VALUE) {
170         DPRINT("CreateNamedPipe() failed (%d)\n", GetLastError());
171         return FALSE;
172     }
173
174     DPRINT("CreateNamedPipe() - calling ConnectNamedPipe(%x)\n", hPipe);
175     fConnected = ConnectNamedPipe(hPipe,
176                    NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
177     DPRINT("CreateNamedPipe() - ConnectNamedPipe() returned %d\n", fConnected);
178
179     if (fConnected) {
180         DPRINT("Pipe connected\n");
181         hThread = CreateThread(NULL,
182                                0,
183                                ScmNamedPipeThread,
184                                (LPVOID)hPipe,
185                                0,
186                                &dwThreadId);
187         if (!hThread) {
188             DPRINT("Could not create thread (%d)\n", GetLastError());
189             DisconnectNamedPipe(hPipe);
190             CloseHandle(hPipe);
191             DPRINT("CreateNamedPipe() - returning FALSE\n");
192            return FALSE;
193         }
194     } else {
195         DPRINT("Pipe not connected\n");
196         CloseHandle(hPipe);
197         DPRINT("CreateNamedPipe() - returning FALSE\n");
198         return FALSE;
199     }
200     DPRINT("CreateNamedPipe() - returning TRUE\n");
201     return TRUE;
202 }
203
204 DWORD
205 WINAPI
206 ScmNamedPipeListenerThread(LPVOID Context)
207 {
208 //    HANDLE hPipe;
209     DPRINT("ScmNamedPipeListenerThread(%x) - aka SCM.\n", Context);
210
211 //    hPipe = (HANDLE)Context;
212     for (;;) {
213         PrintString("SCM: Waiting for new connection on named pipe...\n");
214         /* Create named pipe */
215         if (!ScmCreateNamedPipe()) {
216             PrintString("\nSCM: Failed to create named pipe\n");
217             break;
218             //ExitThread(0);
219         }
220         PrintString("\nSCM: named pipe session created.\n");
221         Sleep(10);
222     }
223     DPRINT("\n\nWARNING: ScmNamedPipeListenerThread(%x) - Aborted.\n\n", Context);
224     return ERROR_SUCCESS;
225 }
226
227 BOOL StartScmNamedPipeThreadListener(void)
228 {
229     DWORD dwThreadId;
230     HANDLE hThread;
231
232     hThread = CreateThread(NULL,
233                  0,
234                  ScmNamedPipeListenerThread,
235                  NULL, /*(LPVOID)hPipe,*/
236                  0,
237                  &dwThreadId);
238
239     if (!hThread) {
240         PrintString("SERVICES: Could not create thread (Status %lx)\n", GetLastError());
241         return FALSE;
242     }
243     return TRUE;
244 }
245
246 int STDCALL
247 WinMain(HINSTANCE hInstance,
248     HINSTANCE hPrevInstance,
249     LPSTR lpCmdLine,
250     int nShowCmd)
251 {
252   HANDLE hScmStartEvent;
253   HANDLE hEvent;
254   NTSTATUS Status;
255
256   PrintString("SERVICES: Service Control Manager\n");
257
258   /* Create start event */
259   if (!ScmCreateStartEvent(&hScmStartEvent))
260     {
261       PrintString("SERVICES: Failed to create start event\n");
262       ExitThread(0);
263     }
264
265   PrintString("SERVICES: created start event with handle %x.\n", hScmStartEvent);
266
267   /* FIXME: more initialization */
268
269
270   /* Create the service database */
271   Status = ScmCreateServiceDataBase();
272   if (!NT_SUCCESS(Status))
273     {
274       PrintString("SERVICES: failed to create SCM database (Status %lx)\n", Status);
275       ExitThread(0);
276     }
277
278   /* Update service database */
279   ScmGetBootAndSystemDriverState();
280
281 #if 0
282     PrintString("SERVICES: Attempting to create named pipe...\n");
283     /* Create named pipe */
284     if (!ScmCreateNamedPipe()) {
285         PrintString("SERVICES: Failed to create named pipe\n");
286         ExitThread(0);
287     }
288     PrintString("SERVICES: named pipe created successfully.\n");
289 #else
290     PrintString("SERVICES: Attempting to create named pipe listener...\n");
291     if (!StartScmNamedPipeThreadListener()) {
292         PrintString("SERVICES: Failed to create named pipe listener thread.\n");
293         ExitThread(0);
294     }
295     PrintString("SERVICES: named pipe listener thread created.\n");
296 #endif
297    /* FIXME: create listener thread for pipe */
298
299
300   /* Register service process with CSRSS */
301   RegisterServicesProcess(GetCurrentProcessId());
302
303   PrintString("SERVICES: Initialized.\n");
304
305   /* Signal start event */
306   SetEvent(hScmStartEvent);
307
308   /* FIXME: register event handler (used for system shutdown) */
309 //  SetConsoleCtrlHandler(...);
310
311
312   /* Start auto-start services */
313   ScmAutoStartServices();
314
315   /* FIXME: more to do ? */
316
317
318   PrintString("SERVICES: Running.\n");
319
320 #if 1
321   hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
322   WaitForSingleObject(hEvent, INFINITE);
323 #else
324     for (;;)
325       {
326     NtYieldExecution();
327       }
328 #endif
329
330   PrintString("SERVICES: Finished.\n");
331
332   ExitThread(0);
333   return(0);
334 }
335
336 /* EOF */