*
*/
-/* NOTE:
- * - Services.exe is NOT a native application, it is a GUI app.
- */
-
/* INCLUDES *****************************************************************/
#include "services.h"
+#include <wincon.h>
+
#define NDEBUG
#include <debug.h>
#define PIPE_BUFSIZE 1024
#define PIPE_TIMEOUT 1000
+/* Defined in include/reactos/services/services.h */
+// #define SCM_START_EVENT L"SvcctrlStartEvent_A3752DX"
+#define SCM_AUTOSTARTCOMPLETE_EVENT L"SC_AutoStartComplete"
+#define LSA_RPC_SERVER_ACTIVE L"LSA_RPC_SERVER_ACTIVE"
+
+BOOL ScmInitialize = FALSE;
BOOL ScmShutdown = FALSE;
+static HANDLE hScmShutdownEvent = NULL;
/* FUNCTIONS *****************************************************************/
VOID
-ScmLogError(DWORD dwEventId,
+ScmLogEvent(DWORD dwEventId,
+ WORD wType,
WORD wStrings,
LPCWSTR *lpStrings)
{
L"Service Control Manager");
if (hLog == NULL)
{
- DPRINT1("ScmLogEvent: RegisterEventSourceW failed %d\n", GetLastError());
+ DPRINT1("ScmLogEvent: RegisterEventSourceW failed %lu\n", GetLastError());
return;
}
if (!ReportEventW(hLog,
- EVENTLOG_ERROR_TYPE,
+ wType,
0,
dwEventId,
- NULL, // Sid,
+ NULL,
wStrings,
0,
lpStrings,
NULL))
{
- DPRINT1("ScmLogEvent: ReportEventW failed %d\n", GetLastError());
+ DPRINT1("ScmLogEvent: ReportEventW failed %lu\n", GetLastError());
}
DeregisterEventSource(hLog);
}
-BOOL
-ScmCreateStartEvent(PHANDLE StartEvent)
+VOID
+ScmWaitForLsa(VOID)
{
- HANDLE hEvent;
-
- hEvent = CreateEvent(NULL,
- TRUE,
- FALSE,
- TEXT("SvcctrlStartEvent_A3752DX"));
+ HANDLE hEvent = CreateEventW(NULL, TRUE, FALSE, LSA_RPC_SERVER_ACTIVE);
if (hEvent == NULL)
{
- if (GetLastError() == ERROR_ALREADY_EXISTS)
- {
- hEvent = OpenEvent(EVENT_ALL_ACCESS,
- FALSE,
- TEXT("SvcctrlStartEvent_A3752DX"));
- if (hEvent == NULL)
- {
- return FALSE;
- }
- }
- else
- {
- return FALSE;
- }
+ DPRINT1("Failed to create the notification event (Error %lu)\n", GetLastError());
}
-
- *StartEvent = hEvent;
-
- return TRUE;
-}
-
-
-static VOID
-ScmWaitForLsass(VOID)
-{
- HANDLE hEvent;
- DWORD dwError;
-
- hEvent = CreateEventW(NULL,
- TRUE,
- FALSE,
- L"LSA_RPC_SERVER_ACTIVE");
- if (hEvent == NULL)
+ else
{
- dwError = GetLastError();
- DPRINT("Failed to create the notication event (Error %lu)\n", dwError);
-
- if (dwError == ERROR_ALREADY_EXISTS)
- {
- hEvent = OpenEventW(SYNCHRONIZE,
- FALSE,
- L"LSA_RPC_SERVER_ACTIVE");
- if (hEvent == NULL)
- {
- DPRINT1("Could not open the notification event (Error %lu)\n", GetLastError());
- return;
- }
- }
+ DPRINT("Wait for the LSA server!\n");
+ WaitForSingleObject(hEvent, INFINITE);
+ DPRINT("LSA server running!\n");
+ CloseHandle(hEvent);
}
- DPRINT("Wait for the LSA server!\n");
- WaitForSingleObject(hEvent, INFINITE);
- DPRINT("LSA server running!\n");
-
- CloseHandle(hEvent);
+ DPRINT("ScmWaitForLsa() done\n");
}
PVOID Reply,
LPDWORD ReplySize)
{
- DbgPrint("SCM READ: %s\n", Request);
+ DbgPrint("SCM READ: %p\n", Request);
*ReplySize = 0;
return FALSE;
hPipe = (HANDLE)Context;
- DPRINT("ScmNamedPipeThread(%x) - Accepting SCM commands through named pipe\n", hPipe);
+ DPRINT("ScmNamedPipeThread(%p) - Accepting SCM commands through named pipe\n", hPipe);
for (;;)
{
}
}
- DPRINT("ScmNamedPipeThread(%x) - Disconnecting named pipe connection\n", hPipe);
+ DPRINT("ScmNamedPipeThread(%p) - Disconnecting named pipe connection\n", hPipe);
FlushFileBuffers(hPipe);
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
- DPRINT("ScmNamedPipeThread(%x) - Done.\n", hPipe);
+ DPRINT("ScmNamedPipeThread(%p) - Done.\n", hPipe);
return ERROR_SUCCESS;
}
DPRINT("ScmCreateNamedPipe() - CreateNamedPipe(\"\\\\.\\pipe\\Ntsvcs\")\n");
- hPipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\Ntsvcs"),
+ hPipe = CreateNamedPipeW(L"\\\\.\\pipe\\Ntsvcs",
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
NULL);
if (hPipe == INVALID_HANDLE_VALUE)
{
- DPRINT("CreateNamedPipe() failed (%d)\n", GetLastError());
+ DPRINT("CreateNamedPipe() failed (%lu)\n", GetLastError());
return FALSE;
}
- DPRINT("CreateNamedPipe() - calling ConnectNamedPipe(%x)\n", hPipe);
+ DPRINT("CreateNamedPipe() - calling ConnectNamedPipe(%p)\n", hPipe);
bConnected = ConnectNamedPipe(hPipe,
NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
DPRINT("CreateNamedPipe() - ConnectNamedPipe() returned %d\n", bConnected);
&dwThreadId);
if (!hThread)
{
- DPRINT("Could not create thread (%d)\n", GetLastError());
+ DPRINT("Could not create thread (%lu)\n", GetLastError());
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
DPRINT("CreateNamedPipe() - returning FALSE\n");
return FALSE;
}
+
+ CloseHandle(hThread);
}
else
{
ScmNamedPipeListenerThread(LPVOID Context)
{
// HANDLE hPipe;
- DPRINT("ScmNamedPipeListenerThread(%x) - aka SCM.\n", Context);
+ DPRINT("ScmNamedPipeListenerThread(%p) - aka SCM.\n", Context);
// hPipe = (HANDLE)Context;
for (;;)
DPRINT("\nSCM: named pipe session created.\n");
Sleep(10);
}
- DPRINT("\n\nWARNING: ScmNamedPipeListenerThread(%x) - Aborted.\n\n", Context);
+ DPRINT("\n\nWARNING: ScmNamedPipeListenerThread(%p) - Aborted.\n\n", Context);
return ERROR_SUCCESS;
}
return FALSE;
}
- return TRUE;
-}
-
-
-VOID FASTCALL
-AcquireLoadDriverPrivilege(VOID)
-{
- HANDLE hToken;
- TOKEN_PRIVILEGES tkp;
-
- /* Get a token for this process */
- if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
- {
- /* Get the LUID for the debug privilege */
- LookupPrivilegeValue(NULL, SE_LOAD_DRIVER_NAME, &tkp.Privileges[0].Luid);
-
- /* One privilege to set */
- tkp.PrivilegeCount = 1;
- tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+ CloseHandle(hThread);
- /* Get the debug privilege for this process */
- AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
- }
+ return TRUE;
}
ScmAutoShutdownServices();
ScmShutdownServiceDatabase();
+
+ /* Set the shutdwon event */
+ SetEvent(hScmShutdownEvent);
}
return TRUE;
LPWSTR lpCmdLine,
int nShowCmd)
{
- HANDLE hScmStartEvent;
- HANDLE hEvent;
+ HANDLE hScmStartEvent = NULL;
+ HANDLE hScmAutoStartCompleteEvent = NULL;
+ SC_RPC_LOCK Lock = NULL;
+ BOOL bCanDeleteNamedPipeCriticalSection = FALSE;
DWORD dwError;
DPRINT("SERVICES: Service Control Manager\n");
- /* Create start event */
- if (!ScmCreateStartEvent(&hScmStartEvent))
+ /* We are initializing ourselves */
+ ScmInitialize = TRUE;
+
+ /* Create the start event */
+ hScmStartEvent = CreateEventW(NULL, TRUE, FALSE, SCM_START_EVENT);
+ if (hScmStartEvent == NULL)
{
- DPRINT1("SERVICES: Failed to create start event\n");
- ExitThread(0);
+ DPRINT1("SERVICES: Failed to create the start event\n");
+ goto done;
}
+ DPRINT("SERVICES: Created start event with handle %p.\n", hScmStartEvent);
- DPRINT("SERVICES: created start event with handle %p.\n", hScmStartEvent);
+ /* Create the auto-start complete event */
+ hScmAutoStartCompleteEvent = CreateEventW(NULL, TRUE, FALSE, SCM_AUTOSTARTCOMPLETE_EVENT);
+ if (hScmAutoStartCompleteEvent == NULL)
+ {
+ DPRINT1("SERVICES: Failed to create the auto-start complete event\n");
+ goto done;
+ }
+ DPRINT("SERVICES: created auto-start complete event with handle %p.\n", hScmAutoStartCompleteEvent);
+
+ /* Create the shutdown event */
+ hScmShutdownEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
+ if (hScmShutdownEvent == NULL)
+ {
+ DPRINT1("SERVICES: Failed to create the shutdown event\n");
+ goto done;
+ }
+
+ /* Initialize our communication named pipe's critical section */
+ ScmInitNamedPipeCriticalSection();
+ bCanDeleteNamedPipeCriticalSection = TRUE;
// ScmInitThreadManager();
/* FIXME: more initialization */
+ /* Read the control set values */
+ if (!ScmGetControlSetValues())
+ {
+ DPRINT1("SERVICES: Failed to read the control set values\n");
+ goto done;
+ }
- /* Create the service database */
+ /* Create the services database */
dwError = ScmCreateServiceDatabase();
if (dwError != ERROR_SUCCESS)
{
- DPRINT1("SERVICES: failed to create SCM database (Error %lu)\n", dwError);
- ExitThread(0);
+ DPRINT1("SERVICES: Failed to create SCM database (Error %lu)\n", dwError);
+ goto done;
}
- /* Update service database */
+ /* Wait for the LSA server */
+ ScmWaitForLsa();
+
+ /* Update the services database */
ScmGetBootAndSystemDriverState();
- /* Start the RPC server */
- ScmStartRpcServer();
+ /* Register the Service Control Manager process with the ReactOS Subsystem */
+ if (!RegisterServicesProcess(GetCurrentProcessId()))
+ {
+ DPRINT1("SERVICES: Could not register SCM process\n");
+ goto done;
+ }
- /* Register service process with CSRSS */
- RegisterServicesProcess(GetCurrentProcessId());
+ /*
+ * Acquire the user service start lock until
+ * auto-start services have been started.
+ */
+ dwError = ScmAcquireServiceStartLock(TRUE, &Lock);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("SERVICES: Failed to acquire the service start lock (Error %lu)\n", dwError);
+ goto done;
+ }
- DPRINT("SERVICES: Initialized.\n");
+ /* Start the RPC server */
+ ScmStartRpcServer();
/* Signal start event */
SetEvent(hScmStartEvent);
+ DPRINT("SERVICES: Initialized.\n");
+
/* Register event handler (used for system shutdown) */
SetConsoleCtrlHandler(ShutdownHandlerRoutine, TRUE);
- /* Wait for the LSA server */
- ScmWaitForLsass();
-
- /* Acquire privileges to load drivers */
- AcquireLoadDriverPrivilege();
-
- ScmInitNamedPipeCriticalSection();
+ /*
+ * Set our shutdown parameters: we want to shutdown after the maintained
+ * services (that inherit the default shutdown level of 640).
+ */
+ SetProcessShutdownParameters(480, SHUTDOWN_NORETRY);
/* Start auto-start services */
ScmAutoStartServices();
+ /* Signal auto-start complete event */
+ SetEvent(hScmAutoStartCompleteEvent);
+
/* FIXME: more to do ? */
+ /* Release the service start lock */
+ ScmReleaseServiceStartLock(&Lock);
+
+ /* Initialization finished */
+ ScmInitialize = FALSE;
DPRINT("SERVICES: Running.\n");
-#if 1
- hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (hEvent)
- WaitForSingleObject(hEvent, INFINITE);
-#else
- for (;;)
- {
- NtYieldExecution();
- }
-#endif
+ /* Wait until the shutdown event gets signaled */
+ WaitForSingleObject(hScmShutdownEvent, INFINITE);
+
+done:
+ /* Delete our communication named pipe's critical section */
+ if (bCanDeleteNamedPipeCriticalSection == TRUE)
+ ScmDeleteNamedPipeCriticalSection();
- ScmDeleteNamedPipeCriticalSection();
+ /* Close the shutdown event */
+ if (hScmShutdownEvent != NULL)
+ CloseHandle(hScmShutdownEvent);
- CloseHandle(hScmStartEvent);
+ /* Close the auto-start complete event */
+ if (hScmAutoStartCompleteEvent != NULL)
+ CloseHandle(hScmAutoStartCompleteEvent);
+
+ /* Close the start event */
+ if (hScmStartEvent != NULL)
+ CloseHandle(hScmStartEvent);
DPRINT("SERVICES: Finished.\n");
ExitThread(0);
-
return 0;
}