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>
11 /* INCLUDES *****************************************************************/
20 int WINAPI
RegisterServicesProcess(DWORD ServicesProcessId
);
22 /* GLOBALS ******************************************************************/
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 #define LSA_RPC_SERVER_ACTIVE L"LSA_RPC_SERVER_ACTIVE"
29 BOOL ScmInitialize
= FALSE
;
30 BOOL ScmShutdown
= FALSE
;
31 static HANDLE hScmShutdownEvent
= NULL
;
34 /* FUNCTIONS *****************************************************************/
37 PrintString(LPCSTR fmt
, ...)
44 vsprintf(buffer
, fmt
, ap
);
47 OutputDebugStringA(buffer
);
53 ScmLogEvent(DWORD dwEventId
,
60 hLog
= RegisterEventSourceW(NULL
,
61 L
"Service Control Manager");
64 DPRINT1("ScmLogEvent: RegisterEventSourceW failed %lu\n", GetLastError());
68 if (!ReportEventW(hLog
,
78 DPRINT1("ScmLogEvent: ReportEventW failed %lu\n", GetLastError());
81 DeregisterEventSource(hLog
);
88 HANDLE hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, LSA_RPC_SERVER_ACTIVE
);
91 DPRINT1("Failed to create the notification event (Error %lu)\n", GetLastError());
95 DPRINT("Wait for the LSA server!\n");
96 WaitForSingleObject(hEvent
, INFINITE
);
97 DPRINT("LSA server running!\n");
101 DPRINT("ScmWaitForLsa() done\n");
106 ShutdownHandlerRoutine(DWORD dwCtrlType
)
108 DPRINT1("ShutdownHandlerRoutine() called\n");
110 if (dwCtrlType
& (CTRL_SHUTDOWN_EVENT
| CTRL_LOGOFF_EVENT
))
112 DPRINT1("Shutdown event received!\n");
115 ScmAutoShutdownServices();
116 ScmShutdownServiceDatabase();
118 /* Set the shutdown event */
119 SetEvent(hScmShutdownEvent
);
126 /*** HACK CORE-12541: Special service accounts initialization HACK ************/
128 #include <ndk/setypes.h>
133 /* Inspired from userenv.dll's CreateUserProfileExW and LoadUserProfileW APIs */
136 ScmLogAccountHack(IN LPCWSTR pszAccountName
,
140 BOOL Success
= FALSE
;
143 BOOLEAN WasPriv1Set
= FALSE
, WasPriv2Set
= FALSE
;
146 WCHAR szUserHivePath
[MAX_PATH
];
148 DPRINT1("ScmLogAccountsHack(%S, %S)\n", pszAccountName
, pszSid
);
149 if (!pszAccountName
|| !pszSid
|| !phProfile
)
150 return ERROR_INVALID_PARAMETER
;
152 /* Convert the SID string into a SID. NOTE: No RTL equivalent. */
153 if (!ConvertStringSidToSidW(pszSid
, &pSid
))
155 DPRINT1("ConvertStringSidToSidW() failed (error %lu)\n", GetLastError());
159 /* Determine a suitable profile path */
160 dwLength
= ARRAYSIZE(szUserHivePath
);
161 if (!GetProfilesDirectoryW(szUserHivePath
, &dwLength
))
163 DPRINT1("GetProfilesDirectoryW() failed (error %lu)\n", GetLastError());
167 /* Create user hive name */
168 StringCbCatW(szUserHivePath
, sizeof(szUserHivePath
), L
"\\");
169 StringCbCatW(szUserHivePath
, sizeof(szUserHivePath
), pszAccountName
);
170 StringCbCatW(szUserHivePath
, sizeof(szUserHivePath
), L
"\\ntuser.dat");
171 DPRINT("szUserHivePath: %S\n", szUserHivePath
);
173 /* Magic #1: Create the special user profile if needed */
174 if (GetFileAttributesW(szUserHivePath
) == INVALID_FILE_ATTRIBUTES
)
176 if (!CreateUserProfileW(pSid
, pszAccountName
))
178 DPRINT1("CreateUserProfileW() failed (error %lu)\n", GetLastError());
184 * Now Da Magiks #2: Manually mount the user profile registry hive
185 * aka. manually do what LoadUserProfile does!! But we don't require
189 /* Acquire restore privilege */
190 Status
= RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE
, TRUE
, FALSE
, &WasPriv1Set
);
191 if (!NT_SUCCESS(Status
))
193 DPRINT1("RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE) failed (Error 0x%08lx)\n", Status
);
197 /* Acquire backup privilege */
198 Status
= RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE
, TRUE
, FALSE
, &WasPriv2Set
);
199 if (!NT_SUCCESS(Status
))
201 DPRINT1("RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE) failed (Error 0x%08lx)\n", Status
);
202 RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE
, WasPriv1Set
, FALSE
, &WasPriv1Set
);
206 /* Load user registry hive */
207 Error
= RegLoadKeyW(HKEY_USERS
, pszSid
, szUserHivePath
);
209 /* Remove restore and backup privileges */
210 RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE
, WasPriv2Set
, FALSE
, &WasPriv2Set
);
211 RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE
, WasPriv1Set
, FALSE
, &WasPriv1Set
);
213 /* HACK: Do not fail if the profile has already been loaded! */
214 if (Error
== ERROR_SHARING_VIOLATION
)
215 Error
= ERROR_SUCCESS
;
217 if (Error
!= ERROR_SUCCESS
)
219 DPRINT1("RegLoadKeyW() failed (Error %ld)\n", Error
);
223 /* Open future HKEY_CURRENT_USER */
224 Error
= RegOpenKeyExW(HKEY_USERS
,
229 if (Error
!= ERROR_SUCCESS
)
231 DPRINT1("RegOpenKeyExW() failed (Error %ld)\n", Error
);
240 DPRINT1("ScmLogAccountsHack(%S) returned %s\n",
241 pszAccountName
, Success
? "success" : "failure");
248 LPCWSTR pszAccountName
;
251 } AccountHandles
[] = {
252 // {L"LocalSystem" , L"S-1-5-18", NULL},
253 {L
"LocalService" , L
"S-1-5-19", NULL
}, // L"NT AUTHORITY\\LocalService"
254 {L
"NetworkService", L
"S-1-5-20", NULL
}, // L"NT AUTHORITY\\NetworkService"
258 ScmCleanupServiceAccountsHack(VOID
)
262 DPRINT1("ScmCleanupServiceAccountsHack()\n");
264 for (i
= 0; i
< ARRAYSIZE(AccountHandles
); ++i
)
266 if (AccountHandles
[i
].hProfile
)
268 RegCloseKey(AccountHandles
[i
].hProfile
);
269 AccountHandles
[i
].hProfile
= NULL
;
275 ScmApplyServiceAccountsHack(VOID
)
279 DPRINT1("ScmApplyServiceAccountsHack()\n");
281 for (i
= 0; i
< ARRAYSIZE(AccountHandles
); ++i
)
283 if (!ScmLogAccountHack( AccountHandles
[i
].pszAccountName
,
284 AccountHandles
[i
].pszSid
,
285 &AccountHandles
[i
].hProfile
))
287 ScmCleanupServiceAccountsHack();
295 /*************************** END OF HACK CORE-12541 ***************************/
299 wWinMain(HINSTANCE hInstance
,
300 HINSTANCE hPrevInstance
,
304 HANDLE hScmStartEvent
= NULL
;
305 HANDLE hScmAutoStartCompleteEvent
= NULL
;
306 SC_RPC_LOCK Lock
= NULL
;
307 BOOL bCanDeleteNamedPipeCriticalSection
= FALSE
;
310 DPRINT("SERVICES: Service Control Manager\n");
312 /* Make us critical */
313 RtlSetProcessIsCritical(TRUE
, NULL
, TRUE
);
315 /* We are initializing ourselves */
316 ScmInitialize
= TRUE
;
318 /* Create the start event */
319 hScmStartEvent
= CreateEventW(NULL
, TRUE
, FALSE
, SCM_START_EVENT
);
320 if (hScmStartEvent
== NULL
)
322 DPRINT1("SERVICES: Failed to create the start event\n");
325 DPRINT("SERVICES: Created start event with handle %p.\n", hScmStartEvent
);
327 /* Create the auto-start complete event */
328 hScmAutoStartCompleteEvent
= CreateEventW(NULL
, TRUE
, FALSE
, SCM_AUTOSTARTCOMPLETE_EVENT
);
329 if (hScmAutoStartCompleteEvent
== NULL
)
331 DPRINT1("SERVICES: Failed to create the auto-start complete event\n");
334 DPRINT("SERVICES: created auto-start complete event with handle %p.\n", hScmAutoStartCompleteEvent
);
336 /* Create the shutdown event */
337 hScmShutdownEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
338 if (hScmShutdownEvent
== NULL
)
340 DPRINT1("SERVICES: Failed to create the shutdown event\n");
344 /* Initialize our communication named pipe's critical section */
345 ScmInitNamedPipeCriticalSection();
346 bCanDeleteNamedPipeCriticalSection
= TRUE
;
348 // ScmInitThreadManager();
350 ScmInitializeSecurity();
352 /* FIXME: more initialization */
354 /* Read the control set values */
355 if (!ScmGetControlSetValues())
357 DPRINT1("SERVICES: Failed to read the control set values\n");
361 /* Create the services database */
362 dwError
= ScmCreateServiceDatabase();
363 if (dwError
!= ERROR_SUCCESS
)
365 DPRINT1("SERVICES: Failed to create SCM database (Error %lu)\n", dwError
);
369 /* Wait for the LSA server */
372 /* Update the services database */
373 ScmGetBootAndSystemDriverState();
375 /* Register the Service Control Manager process with the ReactOS Subsystem */
376 if (!RegisterServicesProcess(GetCurrentProcessId()))
378 DPRINT1("SERVICES: Could not register SCM process\n");
383 * Acquire the user service start lock until
384 * auto-start services have been started.
386 dwError
= ScmAcquireServiceStartLock(TRUE
, &Lock
);
387 if (dwError
!= ERROR_SUCCESS
)
389 DPRINT1("SERVICES: Failed to acquire the service start lock (Error %lu)\n", dwError
);
393 /* Start the RPC server */
396 /* Signal start event */
397 SetEvent(hScmStartEvent
);
399 DPRINT("SERVICES: Initialized.\n");
401 /* Register event handler (used for system shutdown) */
402 SetConsoleCtrlHandler(ShutdownHandlerRoutine
, TRUE
);
405 * Set our shutdown parameters: we want to shutdown after the maintained
406 * services (that inherit the default shutdown level of 640).
408 SetProcessShutdownParameters(480, SHUTDOWN_NORETRY
);
410 /*** HACK CORE-12541: Apply service accounts HACK ***/
411 ScmApplyServiceAccountsHack();
413 /* Start auto-start services */
414 ScmAutoStartServices();
416 /* Signal auto-start complete event */
417 SetEvent(hScmAutoStartCompleteEvent
);
419 /* FIXME: more to do ? */
421 /* Release the service start lock */
422 ScmReleaseServiceStartLock(&Lock
);
424 /* Initialization finished */
425 ScmInitialize
= FALSE
;
427 DPRINT("SERVICES: Running.\n");
429 /* Wait until the shutdown event gets signaled */
430 WaitForSingleObject(hScmShutdownEvent
, INFINITE
);
432 /*** HACK CORE-12541: Cleanup service accounts HACK ***/
433 ScmCleanupServiceAccountsHack();
436 ScmShutdownSecurity();
438 /* Delete our communication named pipe's critical section */
439 if (bCanDeleteNamedPipeCriticalSection
!= FALSE
)
440 ScmDeleteNamedPipeCriticalSection();
442 /* Close the shutdown event */
443 if (hScmShutdownEvent
!= NULL
)
444 CloseHandle(hScmShutdownEvent
);
446 /* Close the auto-start complete event */
447 if (hScmAutoStartCompleteEvent
!= NULL
)
448 CloseHandle(hScmAutoStartCompleteEvent
);
450 /* Close the start event */
451 if (hScmStartEvent
!= NULL
)
452 CloseHandle(hScmStartEvent
);
454 DPRINT("SERVICES: Finished.\n");