:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[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     {
79       if (GetLastError() == ERROR_ALREADY_EXISTS)
80         {
81           hEvent = OpenEvent(EVENT_ALL_ACCESS,
82                              FALSE,
83                              _T("SvcctrlStartEvent_A3725DX"));
84           if (hEvent == NULL)
85             {
86               return(FALSE);
87             }
88         }
89       else
90         {
91           return(FALSE);
92         }
93     }
94
95   *StartEvent = hEvent;
96
97   return(TRUE);
98 }
99
100
101 BOOL
102 ScmNamedPipeHandleRequest(
103   PVOID Request,
104   DWORD RequestSize,
105         PVOID Reply,
106         LPDWORD ReplySize)
107 {
108   DbgPrint("SCM READ: %s\n", Request);
109
110   *ReplySize = 0;
111
112   return FALSE;
113 }
114
115
116 DWORD
117 WINAPI
118 ScmNamedPipeThread(
119   LPVOID Context)
120 {
121   CHAR chRequest[PIPE_BUFSIZE];
122   CHAR chReply[PIPE_BUFSIZE];
123   DWORD cbReplyBytes;
124   DWORD cbBytesRead;
125   DWORD cbWritten;
126   BOOL fSuccess;
127   HANDLE hPipe;
128
129   DPRINT("Accepting SCM commands through named pipe\n");
130    
131   hPipe = (HANDLE)Context;
132
133   for (;;)
134   {
135           fSuccess = ReadFile(
136       hPipe,
137                   &chRequest,
138                         PIPE_BUFSIZE,
139       &cbBytesRead,
140                         NULL);
141           if (!fSuccess || cbBytesRead == 0)
142     {
143             break;
144     }
145
146           if (ScmNamedPipeHandleRequest(&chRequest, cbBytesRead, &chReply, &cbReplyBytes))
147     {
148             fSuccess = WriteFile(
149         hPipe,
150                 &chReply,
151                 cbReplyBytes,
152                 &cbWritten,
153                 NULL);
154             if (!fSuccess || cbReplyBytes != cbWritten)
155       {
156               break;
157       }
158     }
159   }
160
161   FlushFileBuffers(hPipe);
162   DisconnectNamedPipe(hPipe);
163   CloseHandle(hPipe);
164
165   return ERROR_SUCCESS;
166 }
167
168
169 BOOL ScmCreateNamedPipe(VOID)
170 {
171   DWORD dwThreadId;
172   BOOL fConnected;
173   HANDLE hThread;
174   HANDLE hPipe;
175
176   hPipe = CreateNamedPipe("\\\\.\\pipe\\Ntsvcs",
177                           PIPE_ACCESS_DUPLEX,
178                           PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
179                           PIPE_UNLIMITED_INSTANCES,
180                           PIPE_BUFSIZE,
181                           PIPE_BUFSIZE,
182                           PIPE_TIMEOUT,
183                           NULL);
184   if (hPipe == INVALID_HANDLE_VALUE)
185     {
186       DPRINT("CreateNamedPipe() failed (%d)\n", GetLastError());
187       return(FALSE);
188     }
189
190   fConnected = ConnectNamedPipe(hPipe,
191                                 NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
192   if (fConnected)
193     {
194       DPRINT("Pipe connected\n");
195
196       hThread = CreateThread(NULL,
197                              0,
198                              ScmNamedPipeThread,
199                              (LPVOID)hPipe,
200                              0,
201                              &dwThreadId);
202       if (!hThread)
203         {
204           DPRINT("Could not create thread (%d)\n", GetLastError());
205
206           DisconnectNamedPipe(hPipe);
207           CloseHandle(hPipe);
208           return(FALSE);
209         }
210     }
211   else
212     {
213       DPRINT("Pipe not connected\n");
214
215       CloseHandle(hPipe);
216       return FALSE;
217     }
218
219   return TRUE;
220 }
221
222
223 int STDCALL
224 WinMain(HINSTANCE hInstance,
225         HINSTANCE hPrevInstance,
226         LPSTR lpCmdLine,
227         int nShowCmd)
228 {
229   HANDLE hScmStartEvent;
230   HANDLE hEvent;
231   NTSTATUS Status;
232
233   PrintString("Service Control Manager\n");
234
235   /* Create start event */
236   if (!ScmCreateStartEvent(&hScmStartEvent))
237     {
238       PrintString("SERVICES: Failed to create start event\n");
239       ExitThread(0);
240     }
241
242
243   /* FIXME: more initialization */
244
245
246   /* Create the service database */
247   Status = ScmCreateServiceDataBase();
248   if (!NT_SUCCESS(Status))
249     {
250       PrintString("ScmCreateServiceDataBase() failed (Status %lx)\n", Status);
251       ExitThread(0);
252     }
253
254   /* Update service database */
255   ScmGetBootAndSystemDriverState();
256
257 #if 0
258    /* Create named pipe */
259    if (!ScmCreateNamedPipe())
260      {
261         PrintString("SERVICES: Failed to create named pipe\n");
262         ExitThread(0);
263      }
264 #endif
265    /* FIXME: create listener thread for pipe */
266
267
268   /* Register service process with CSRSS */
269   RegisterServicesProcess(GetCurrentProcessId());
270
271   PrintString("SERVICES: Initialized.\n");
272
273   /* Signal start event */
274   SetEvent(hScmStartEvent);
275
276   /* FIXME: register event handler (used for system shutdown) */
277 //  SetConsoleCtrlHandler(...);
278
279
280   /* Start auto-start services */
281   ScmAutoStartServices();
282
283   /* FIXME: more to do ? */
284
285
286   PrintString("SERVICES: Running.\n");
287
288   hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
289   WaitForSingleObject(hEvent, INFINITE);
290 #if 0
291     for (;;)
292       {
293         NtYieldExecution();
294       }
295 #endif
296
297   PrintString("SERVICES: Finished.\n");
298
299   ExitThread(0);
300   return(0);
301 }
302
303 /* EOF */