First draft of a ScmNamedPipeListenerThread implementation.
[reactos.git] / reactos / subsys / system / services / services.c
1 /* $Id: services.c,v 1.10 2002/12/27 13:54:28 robd 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 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 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 */