Relative include path fixed to absolute path.
[reactos.git] / reactos / subsys / system / services / services.c
1 /* $Id: services.c,v 1.9 2002/10/20 14:54:34 ekohl Exp $
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 */