[SERVICES][ADVAPI32] Support the security process aka lsass.exe
[reactos.git] / base / system / services / services.c
1 /*
2 * PROJECT: ReactOS Service Control Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/system/services/services.c
5 * PURPOSE: Main SCM controller
6 * COPYRIGHT: Copyright 2001-2005 Eric Kohl
7 * Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
8 *
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include "services.h"
14
15 #include <wincon.h>
16
17 #define NDEBUG
18 #include <debug.h>
19
20 int WINAPI RegisterServicesProcess(DWORD ServicesProcessId);
21
22 /* GLOBALS ******************************************************************/
23
24 /* Defined in include/reactos/services/services.h */
25 // #define SCM_START_EVENT L"SvcctrlStartEvent_A3752DX"
26 #define SCM_AUTOSTARTCOMPLETE_EVENT L"SC_AutoStartComplete"
27
28 BOOL ScmInitialize = FALSE;
29 BOOL ScmShutdown = FALSE;
30 static HANDLE hScmShutdownEvent = NULL;
31 static HANDLE hScmSecurityServicesEvent = NULL;
32
33
34 /* FUNCTIONS *****************************************************************/
35
36 VOID
37 PrintString(LPCSTR fmt, ...)
38 {
39 #if DBG
40 CHAR buffer[512];
41 va_list ap;
42
43 va_start(ap, fmt);
44 vsprintf(buffer, fmt, ap);
45 va_end(ap);
46
47 OutputDebugStringA(buffer);
48 #endif
49 }
50
51
52 DWORD
53 SetSecurityServicesEvent(VOID)
54 {
55 DWORD dwError;
56
57 if (hScmSecurityServicesEvent != NULL)
58 return ERROR_SUCCESS;
59
60 /* Create or open the SECURITY_SERVICES_STARTED event */
61 hScmSecurityServicesEvent = CreateEventW(NULL,
62 TRUE,
63 FALSE,
64 L"SECURITY_SERVICES_STARTED");
65 if (hScmSecurityServicesEvent == NULL)
66 {
67 dwError = GetLastError();
68 if (dwError != ERROR_ALREADY_EXISTS)
69 return dwError;
70
71 hScmSecurityServicesEvent = OpenEventW(EVENT_MODIFY_STATE,
72 FALSE,
73 L"SECURITY_SERVICES_STARTED");
74 if (hScmSecurityServicesEvent == NULL)
75 return GetLastError();
76 }
77
78 SetEvent(hScmSecurityServicesEvent);
79
80 return ERROR_SUCCESS;
81 }
82
83
84 VOID
85 ScmLogEvent(DWORD dwEventId,
86 WORD wType,
87 WORD wStrings,
88 LPCWSTR *lpStrings)
89 {
90 HANDLE hLog;
91
92 hLog = RegisterEventSourceW(NULL,
93 L"Service Control Manager");
94 if (hLog == NULL)
95 {
96 DPRINT1("ScmLogEvent: RegisterEventSourceW failed %lu\n", GetLastError());
97 return;
98 }
99
100 if (!ReportEventW(hLog,
101 wType,
102 0,
103 dwEventId,
104 NULL,
105 wStrings,
106 0,
107 lpStrings,
108 NULL))
109 {
110 DPRINT1("ScmLogEvent: ReportEventW failed %lu\n", GetLastError());
111 }
112
113 DeregisterEventSource(hLog);
114 }
115
116
117 VOID
118 ScmWaitForLsa(VOID)
119 {
120 HANDLE hEvent = CreateEventW(NULL, TRUE, FALSE, L"LSA_RPC_SERVER_ACTIVE");
121 if (hEvent == NULL)
122 {
123 DPRINT1("Failed to create or open the notification event (Error %lu)\n", GetLastError());
124 }
125 else
126 {
127 DPRINT("Wait for the LSA server!\n");
128 WaitForSingleObject(hEvent, INFINITE);
129 DPRINT("LSA server running!\n");
130 CloseHandle(hEvent);
131 }
132
133 DPRINT("ScmWaitForLsa() done\n");
134 }
135
136
137 BOOL WINAPI
138 ShutdownHandlerRoutine(DWORD dwCtrlType)
139 {
140 DPRINT1("ShutdownHandlerRoutine() called\n");
141
142 if (dwCtrlType & (CTRL_SHUTDOWN_EVENT | CTRL_LOGOFF_EVENT))
143 {
144 DPRINT1("Shutdown event received!\n");
145 ScmShutdown = TRUE;
146
147 ScmAutoShutdownServices();
148 ScmShutdownServiceDatabase();
149
150 /* Set the shutdown event */
151 SetEvent(hScmShutdownEvent);
152 }
153
154 return TRUE;
155 }
156
157
158 int WINAPI
159 wWinMain(HINSTANCE hInstance,
160 HINSTANCE hPrevInstance,
161 LPWSTR lpCmdLine,
162 int nShowCmd)
163 {
164 HANDLE hScmStartEvent = NULL;
165 HANDLE hScmAutoStartCompleteEvent = NULL;
166 SC_RPC_LOCK Lock = NULL;
167 BOOL bCanDeleteNamedPipeCriticalSection = FALSE;
168 DWORD dwError;
169
170 DPRINT("SERVICES: Service Control Manager\n");
171
172 /* Make us critical */
173 RtlSetProcessIsCritical(TRUE, NULL, TRUE);
174
175 /* We are initializing ourselves */
176 ScmInitialize = TRUE;
177
178 /* Create the start event */
179 hScmStartEvent = CreateEventW(NULL, TRUE, FALSE, SCM_START_EVENT);
180 if (hScmStartEvent == NULL)
181 {
182 DPRINT1("SERVICES: Failed to create the start event\n");
183 goto done;
184 }
185 DPRINT("SERVICES: Created start event with handle %p.\n", hScmStartEvent);
186
187 /* Create the auto-start complete event */
188 hScmAutoStartCompleteEvent = CreateEventW(NULL, TRUE, FALSE, SCM_AUTOSTARTCOMPLETE_EVENT);
189 if (hScmAutoStartCompleteEvent == NULL)
190 {
191 DPRINT1("SERVICES: Failed to create the auto-start complete event\n");
192 goto done;
193 }
194 DPRINT("SERVICES: created auto-start complete event with handle %p.\n", hScmAutoStartCompleteEvent);
195
196 /* Create the shutdown event */
197 hScmShutdownEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
198 if (hScmShutdownEvent == NULL)
199 {
200 DPRINT1("SERVICES: Failed to create the shutdown event\n");
201 goto done;
202 }
203
204 /* Initialize our communication named pipe's critical section */
205 ScmInitNamedPipeCriticalSection();
206 bCanDeleteNamedPipeCriticalSection = TRUE;
207
208 // ScmInitThreadManager();
209
210 ScmInitializeSecurity();
211
212 /* FIXME: more initialization */
213
214 /* Create the 'Last Known Good' control set */
215 dwError = ScmCreateLastKnownGoodControlSet();
216 if (dwError != ERROR_SUCCESS)
217 {
218 DPRINT1("SERVICES: Failed to create the 'Last Known Good' control set (Error %lu)\n", dwError);
219 goto done;
220 }
221
222 /* Create the services database */
223 dwError = ScmCreateServiceDatabase();
224 if (dwError != ERROR_SUCCESS)
225 {
226 DPRINT1("SERVICES: Failed to create SCM database (Error %lu)\n", dwError);
227 goto done;
228 }
229
230 /* Update the services database */
231 ScmGetBootAndSystemDriverState();
232
233 /* Register the Service Control Manager process with the ReactOS Subsystem */
234 if (!RegisterServicesProcess(GetCurrentProcessId()))
235 {
236 DPRINT1("SERVICES: Could not register SCM process\n");
237 goto done;
238 }
239
240 /*
241 * Acquire the user service start lock until
242 * auto-start services have been started.
243 */
244 dwError = ScmAcquireServiceStartLock(TRUE, &Lock);
245 if (dwError != ERROR_SUCCESS)
246 {
247 DPRINT1("SERVICES: Failed to acquire the service start lock (Error %lu)\n", dwError);
248 goto done;
249 }
250
251 /* Start the RPC server */
252 ScmStartRpcServer();
253
254 /* Signal start event */
255 SetEvent(hScmStartEvent);
256
257 DPRINT("SERVICES: Initialized.\n");
258
259 /* Register event handler (used for system shutdown) */
260 SetConsoleCtrlHandler(ShutdownHandlerRoutine, TRUE);
261
262 /*
263 * Set our shutdown parameters: we want to shutdown after the maintained
264 * services (that inherit the default shutdown level of 640).
265 */
266 SetProcessShutdownParameters(480, SHUTDOWN_NORETRY);
267
268 /* Start auto-start services */
269 ScmAutoStartServices();
270
271 /* Signal auto-start complete event */
272 SetEvent(hScmAutoStartCompleteEvent);
273
274 /* FIXME: more to do ? */
275
276 /* Release the service start lock */
277 ScmReleaseServiceStartLock(&Lock);
278
279 /* Initialization finished */
280 ScmInitialize = FALSE;
281
282 DPRINT("SERVICES: Running.\n");
283
284 /* Wait until the shutdown event gets signaled */
285 WaitForSingleObject(hScmShutdownEvent, INFINITE);
286
287 done:
288 ScmShutdownSecurity();
289
290 /* Delete our communication named pipe's critical section */
291 if (bCanDeleteNamedPipeCriticalSection != FALSE)
292 ScmDeleteNamedPipeCriticalSection();
293
294 if (hScmSecurityServicesEvent != NULL)
295 CloseHandle(hScmSecurityServicesEvent);
296
297 /* Close the shutdown event */
298 if (hScmShutdownEvent != NULL)
299 CloseHandle(hScmShutdownEvent);
300
301 /* Close the auto-start complete event */
302 if (hScmAutoStartCompleteEvent != NULL)
303 CloseHandle(hScmAutoStartCompleteEvent);
304
305 /* Close the start event */
306 if (hScmStartEvent != NULL)
307 CloseHandle(hScmStartEvent);
308
309 DPRINT("SERVICES: Finished.\n");
310
311 ExitThread(0);
312 return 0;
313 }
314
315 /* EOF */