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