-/* $Id: database.c,v 1.11 2003/11/14 17:13:33 weiden Exp $
+/*
*
* service control manager
- *
+ *
* ReactOS Operating System
- *
+ *
* --------------------------------------------------------------------
*
* This software is free software; you can redistribute it and/or
/* INCLUDES *****************************************************************/
+#include <windows.h>
#define NTOS_MODE_USER
-#include <ntos.h>
+#include <ndk/ntndk.h>
-#include <windows.h>
-#include <tchar.h>
+#include <services/services.h>
#include "services.h"
UNICODE_STRING GroupName;
BOOLEAN ServicesRunning;
+ ULONG TagCount;
+ PULONG TagArray;
} SERVICE_GROUP, *PSERVICE_GROUP;
-typedef struct _SERVICE
+/* GLOBALS *******************************************************************/
+
+LIST_ENTRY GroupListHead;
+LIST_ENTRY ServiceListHead;
+
+static RTL_RESOURCE DatabaseLock;
+
+
+/* FUNCTIONS *****************************************************************/
+
+PSERVICE
+ScmGetServiceEntryByName(PUNICODE_STRING ServiceName)
{
- LIST_ENTRY ServiceListEntry;
- UNICODE_STRING ServiceName;
- UNICODE_STRING RegistryPath;
- UNICODE_STRING ServiceGroup;
+ PLIST_ENTRY ServiceEntry;
+ PSERVICE CurrentService;
- ULONG Start;
- ULONG Type;
- ULONG ErrorControl;
- ULONG Tag;
+ DPRINT("ScmGetServiceEntryByName() called\n");
+
+ ServiceEntry = ServiceListHead.Flink;
+ while (ServiceEntry != &ServiceListHead)
+ {
+ CurrentService = CONTAINING_RECORD(ServiceEntry,
+ SERVICE,
+ ServiceListEntry);
+ if (RtlEqualUnicodeString(&CurrentService->ServiceName, ServiceName, TRUE))
+ {
+ DPRINT("Found service: '%wZ'\n", &CurrentService->ServiceName);
+ return CurrentService;
+ }
- BOOLEAN ServiceRunning;
- BOOLEAN ServiceVisited;
+ ServiceEntry = ServiceEntry->Flink;
+ }
- HANDLE ControlPipeHandle;
- ULONG ProcessId;
- ULONG ThreadId;
-} SERVICE, *PSERVICE;
+ DPRINT("Couldn't find a matching service\n");
+ return NULL;
+}
-/* GLOBALS *******************************************************************/
-LIST_ENTRY GroupListHead;
-LIST_ENTRY ServiceListHead;
+static NTSTATUS STDCALL
+CreateGroupOrderListRoutine(PWSTR ValueName,
+ ULONG ValueType,
+ PVOID ValueData,
+ ULONG ValueLength,
+ PVOID Context,
+ PVOID EntryContext)
+{
+ PSERVICE_GROUP Group;
+ DPRINT("IopGetGroupOrderList(%S, %x, %x, %x, %x, %x)\n",
+ ValueName, ValueType, ValueData, ValueLength, Context, EntryContext);
+
+ if (ValueType == REG_BINARY &&
+ ValueData != NULL &&
+ ValueLength >= sizeof(DWORD) &&
+ ValueLength >= (*(PULONG)ValueData + 1) * sizeof(DWORD))
+ {
+ Group = (PSERVICE_GROUP)Context;
+ Group->TagCount = ((PULONG)ValueData)[0];
+ if (Group->TagCount > 0)
+ {
+ if (ValueLength >= (Group->TagCount + 1) * sizeof(DWORD))
+ {
+ Group->TagArray = (PULONG)HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ Group->TagCount * sizeof(DWORD));
+ if (Group->TagArray == NULL)
+ {
+ Group->TagCount = 0;
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlCopyMemory(Group->TagArray,
+ (PULONG)ValueData + 1,
+ Group->TagCount * sizeof(DWORD));
+ }
+ else
+ {
+ Group->TagCount = 0;
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
-/* FUNCTIONS *****************************************************************/
static NTSTATUS STDCALL
CreateGroupListRoutine(PWSTR ValueName,
PVOID Context,
PVOID EntryContext)
{
- PSERVICE_GROUP Group;
+ PSERVICE_GROUP Group;
+ RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+ NTSTATUS Status;
- if (ValueType == REG_SZ)
+ if (ValueType == REG_SZ)
{
- DPRINT("Data: '%S'\n", (PWCHAR)ValueData);
-
- Group = (PSERVICE_GROUP)HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- sizeof(SERVICE_GROUP));
- if (Group == NULL)
- {
- return(STATUS_INSUFFICIENT_RESOURCES);
- }
-
- if (!RtlCreateUnicodeString(&Group->GroupName,
- (PWSTR)ValueData))
- {
- return(STATUS_INSUFFICIENT_RESOURCES);
- }
-
-
- InsertTailList(&GroupListHead,
- &Group->GroupListEntry);
+ DPRINT("Data: '%S'\n", (PWCHAR)ValueData);
+
+ Group = (PSERVICE_GROUP)HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof(SERVICE_GROUP));
+ if (Group == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ if (!RtlCreateUnicodeString(&Group->GroupName,
+ (PWSTR)ValueData))
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory(&QueryTable, sizeof(QueryTable));
+ QueryTable[0].Name = (PWSTR)ValueData;
+ QueryTable[0].QueryRoutine = CreateGroupOrderListRoutine;
+
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
+ L"GroupOrderList",
+ QueryTable,
+ (PVOID)Group,
+ NULL);
+ DPRINT("%x %d %S\n", Status, Group->TagCount, (PWSTR)ValueData);
+
+ InsertTailList(&GroupListHead,
+ &Group->GroupListEntry);
}
- return(STATUS_SUCCESS);
+ return STATUS_SUCCESS;
}
sizeof(SERVICE));
if (Service == NULL)
{
- return(STATUS_INSUFFICIENT_RESOURCES);
+ return STATUS_INSUFFICIENT_RESOURCES;
}
/* Copy service name */
if (Service->ServiceName.Buffer == NULL)
{
HeapFree(GetProcessHeap(), 0, Service);
- return(STATUS_INSUFFICIENT_RESOURCES);
+ return STATUS_INSUFFICIENT_RESOURCES;
}
+
RtlCopyMemory(Service->ServiceName.Buffer,
ServiceName->Buffer,
ServiceName->Length);
{
HeapFree(GetProcessHeap(), 0, Service->ServiceName.Buffer);
HeapFree(GetProcessHeap(), 0, Service);
- return(STATUS_INSUFFICIENT_RESOURCES);
+ return STATUS_INSUFFICIENT_RESOURCES;
}
+
wcscpy(Service->RegistryPath.Buffer,
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
wcscat(Service->RegistryPath.Buffer,
QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
QueryTable[3].EntryContext = &Service->ServiceGroup;
+ QueryTable[4].Name = L"Tag";
+ QueryTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ QueryTable[4].EntryContext = &Service->Tag;
+
Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
ServiceName->Buffer,
QueryTable,
RtlFreeUnicodeString(&Service->RegistryPath);
RtlFreeUnicodeString(&Service->ServiceName);
HeapFree(GetProcessHeap(), 0, Service);
- return(Status);
+ return Status;
}
DPRINT("ServiceName: '%wZ'\n", &Service->ServiceName);
DPRINT("RegistryPath: '%wZ'\n", &Service->RegistryPath);
DPRINT("ServiceGroup: '%wZ'\n", &Service->ServiceGroup);
- DPRINT("Start %lx Type %lx ErrorControl %lx\n",
- Service->Start, Service->Type, Service->ErrorControl);
+ DPRINT("Start %lx Type %lx Tag %lx ErrorControl %lx\n",
+ Service->Start, Service->Type, Service->Tag, Service->ErrorControl);
/* Append service entry */
InsertTailList(&ServiceListHead,
&Service->ServiceListEntry);
- return(STATUS_SUCCESS);
+ Service->CurrentState = SERVICE_STOPPED;
+ Service->ControlsAccepted = 0;
+ Service->Win32ExitCode = 0;
+ Service->ServiceSpecificExitCode = 0;
+ Service->CheckPoint = 0;
+ Service->WaitHint = 2000; /* 2 seconds */
+
+ return STATUS_SUCCESS;
}
{
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING ServicesKeyName;
+ UNICODE_STRING ServicesKeyName =
+ RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
UNICODE_STRING SubKeyName;
HKEY ServicesKey;
ULONG Index;
InitializeListHead(&GroupListHead);
InitializeListHead(&ServiceListHead);
+ /* Initialize the database lock */
+ RtlInitializeResource(&DatabaseLock);
+
/* Build group order list */
RtlZeroMemory(&QueryTable,
sizeof(QueryTable));
NULL,
NULL);
if (!NT_SUCCESS(Status))
- return(Status);
+ return Status;
- RtlInitUnicodeStringFromLiteral(&ServicesKeyName,
+ RtlInitUnicodeString(&ServicesKeyName,
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
InitializeObjectAttributes(&ObjectAttributes,
NULL);
Status = RtlpNtOpenKey(&ServicesKey,
- 0x10001,
+ KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
&ObjectAttributes,
0);
if (!NT_SUCCESS(Status))
- return(Status);
+ return Status;
/* Allocate key info buffer */
KeyInfoLength = sizeof(KEY_BASIC_INFORMATION) + MAX_PATH * sizeof(WCHAR);
if (KeyInfo == NULL)
{
NtClose(ServicesKey);
- return(STATUS_INSUFFICIENT_RESOURCES);
+ return STATUS_INSUFFICIENT_RESOURCES;
}
Index = 0;
DPRINT("KeyName: '%wZ'\n", &SubKeyName);
Status = CreateServiceListEntry(&SubKeyName);
+
+ /* Ignore services without proper registry. */
+ if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ Status = STATUS_SUCCESS;
+ }
}
}
DPRINT("ScmCreateServiceDataBase() done\n");
- return(STATUS_SUCCESS);
+ return STATUS_SUCCESS;
}
UNICODE_STRING DirName;
HANDLE DirHandle;
NTSTATUS Status;
- PDIRECTORY_BASIC_INFORMATION DirInfo;
+ POBJECT_DIRECTORY_INFORMATION DirInfo;
ULONG BufferLength;
ULONG DataLength;
ULONG Index;
if (Service->Type == SERVICE_KERNEL_DRIVER)
{
- RtlInitUnicodeStringFromLiteral(&DirName,
+ RtlInitUnicodeString(&DirName,
L"\\Driver");
}
else
{
- RtlInitUnicodeStringFromLiteral(&DirName,
+ RtlInitUnicodeString(&DirName,
L"\\FileSystem");
}
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
- return(Status);
+ return Status;
}
- BufferLength = sizeof(DIRECTORY_BASIC_INFORMATION) +
+ BufferLength = sizeof(OBJECT_DIRECTORY_INFORMATION) +
2 * MAX_PATH * sizeof(WCHAR);
DirInfo = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
DPRINT("Found: '%wZ' '%wZ'\n", &Service->ServiceName, &DirInfo->ObjectName);
/* Mark service as 'running' */
- Service->ServiceRunning = TRUE;
+ Service->CurrentState = SERVICE_RUNNING;
/* Find the driver's group and mark it as 'running' */
if (Service->ServiceGroup.Buffer != NULL)
DirInfo);
NtClose(DirHandle);
- return(STATUS_SUCCESS);
+ return STATUS_SUCCESS;
}
static NTSTATUS
-ScmStartService(PSERVICE Service,
- PSERVICE_GROUP Group)
+ScmSendStartCommand(PSERVICE Service, LPWSTR Arguments)
+{
+ PSCM_START_PACKET StartPacket;
+ DWORD TotalLength;
+#if 0
+ DWORD Length;
+#endif
+ PWSTR Ptr;
+ DWORD Count;
+
+ DPRINT("ScmSendStartCommand() called\n");
+
+ /* Calculate the total length of the start command line */
+ TotalLength = wcslen(Service->ServiceName.Buffer) + 1;
+#if 0
+ if (Arguments != NULL)
+ {
+ Ptr = Arguments;
+ while (*Ptr)
+ {
+ Length = wcslen(Ptr) + 1;
+ TotalLength += Length;
+ Ptr += Length;
+ }
+ }
+#endif
+ TotalLength++;
+
+ /* Allocate start command packet */
+ StartPacket = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof(SCM_START_PACKET) + (TotalLength - 1) * sizeof(WCHAR));
+ if (StartPacket == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ StartPacket->Command = SCM_START_COMMAND;
+ StartPacket->Size = TotalLength;
+ Ptr = &StartPacket->Arguments[0];
+ wcscpy(Ptr, Service->ServiceName.Buffer);
+ Ptr += (wcslen(Service->ServiceName.Buffer) + 1);
+
+ /* FIXME: Copy argument list */
+
+ *Ptr = 0;
+
+ /* Send the start command */
+ WriteFile(Service->ControlPipeHandle,
+ StartPacket,
+ sizeof(SCM_START_PACKET) + (TotalLength - 1) * sizeof(WCHAR),
+ &Count,
+ NULL);
+
+ /* FIXME: Read the reply */
+
+ HeapFree(GetProcessHeap(),
+ 0,
+ StartPacket);
+
+ DPRINT("ScmSendStartCommand() done\n");
+
+ return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
+ScmStartUserModeService(PSERVICE Service)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[3];
PROCESS_INFORMATION ProcessInformation;
STARTUPINFOW StartupInfo;
UNICODE_STRING ImagePath;
- NTSTATUS Status;
ULONG Type;
BOOL Result;
+ NTSTATUS Status;
- DPRINT("ScmStartService() called\n");
+ RtlInitUnicodeString(&ImagePath, NULL);
- Service->ControlPipeHandle = INVALID_HANDLE_VALUE;
+ /* Get service data */
+ RtlZeroMemory(&QueryTable,
+ sizeof(QueryTable));
- if (Service->Type == SERVICE_KERNEL_DRIVER ||
- Service->Type == SERVICE_FILE_SYSTEM_DRIVER ||
- Service->Type == SERVICE_RECOGNIZER_DRIVER)
+ QueryTable[0].Name = L"Type";
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
+ QueryTable[0].EntryContext = &Type;
+
+ QueryTable[1].Name = L"ImagePath";
+ QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
+ QueryTable[1].EntryContext = &ImagePath;
+
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
+ Service->ServiceName.Buffer,
+ QueryTable,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status))
{
- /* Load driver */
- DPRINT(" Path: %wZ\n", &Service->RegistryPath);
- Status = NtLoadDriver(&Service->RegistryPath);
+ DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
+ return Status;
}
- else
+ DPRINT("ImagePath: '%S'\n", ImagePath.Buffer);
+ DPRINT("Type: %lx\n", Type);
+
+ /* Create '\\.\pipe\net\NtControlPipe' instance */
+ Service->ControlPipeHandle = CreateNamedPipeW(L"\\\\.\\pipe\\net\\NtControlPipe",
+ PIPE_ACCESS_DUPLEX,
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
+ 100,
+ 8000,
+ 4,
+ 30000,
+ NULL);
+ DPRINT("CreateNamedPipeW() done\n");
+ if (Service->ControlPipeHandle == INVALID_HANDLE_VALUE)
{
- RtlInitUnicodeString(&ImagePath, NULL);
+ DPRINT1("Failed to create control pipe!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
- /* Get service data */
- RtlZeroMemory(&QueryTable,
- sizeof(QueryTable));
+ StartupInfo.cb = sizeof(StartupInfo);
+ StartupInfo.lpReserved = NULL;
+ StartupInfo.lpDesktop = NULL;
+ StartupInfo.lpTitle = NULL;
+ StartupInfo.dwFlags = 0;
+ StartupInfo.cbReserved2 = 0;
+ StartupInfo.lpReserved2 = 0;
+
+ Result = CreateProcessW(ImagePath.Buffer,
+ NULL,
+ NULL,
+ NULL,
+ FALSE,
+ DETACHED_PROCESS | CREATE_SUSPENDED,
+ NULL,
+ NULL,
+ &StartupInfo,
+ &ProcessInformation);
+ RtlFreeUnicodeString(&ImagePath);
+
+ if (!Result)
+ {
+ /* Close control pipe */
+ CloseHandle(Service->ControlPipeHandle);
+ Service->ControlPipeHandle = INVALID_HANDLE_VALUE;
- QueryTable[0].Name = L"Type";
- QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
- QueryTable[0].EntryContext = &Type;
+ DPRINT1("Starting '%S' failed!\n", Service->ServiceName.Buffer);
+ return STATUS_UNSUCCESSFUL;
+ }
- QueryTable[1].Name = L"ImagePath";
- QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
- QueryTable[1].EntryContext = &ImagePath;
+ DPRINT("Process Id: %lu Handle %lx\n",
+ ProcessInformation.dwProcessId,
+ ProcessInformation.hProcess);
+ DPRINT("Thread Id: %lu Handle %lx\n",
+ ProcessInformation.dwThreadId,
+ ProcessInformation.hThread);
- Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
- Service->ServiceName.Buffer,
- QueryTable,
- NULL,
- NULL);
- if (NT_SUCCESS(Status))
- {
- DPRINT("ImagePath: '%S'\n", ImagePath.Buffer);
- DPRINT("Type: %lx\n", Type);
-
- /* FIXME: create '\\.\pipe\net\NtControlPipe' instance */
- Service->ControlPipeHandle = CreateNamedPipeW(L"\\\\.\\pipe\\net\\NtControlPipe",
- PIPE_ACCESS_DUPLEX,
- PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
- 100,
- 8000,
- 4,
- 30000,
- NULL);
- DPRINT("CreateNamedPipeW() done\n");
- if (Service->ControlPipeHandle == INVALID_HANDLE_VALUE)
- {
- DPRINT1("Failed to create control pipe!\n");
- Status = STATUS_UNSUCCESSFUL;
- goto Done;
- }
+ /* Get process and thread ids */
+ Service->ProcessId = ProcessInformation.dwProcessId;
+ Service->ThreadId = ProcessInformation.dwThreadId;
- StartupInfo.cb = sizeof(StartupInfo);
- StartupInfo.lpReserved = NULL;
- StartupInfo.lpDesktop = NULL;
- StartupInfo.lpTitle = NULL;
- StartupInfo.dwFlags = 0;
- StartupInfo.cbReserved2 = 0;
- StartupInfo.lpReserved2 = 0;
+ /* Resume Thread */
+ ResumeThread(ProcessInformation.hThread);
- Result = CreateProcessW(ImagePath.Buffer,
- NULL,
- NULL,
- NULL,
- FALSE,
- DETACHED_PROCESS | CREATE_SUSPENDED,
- NULL,
- NULL,
- &StartupInfo,
- &ProcessInformation);
- RtlFreeUnicodeString(&ImagePath);
+ /* Connect control pipe */
+ if (ConnectNamedPipe(Service->ControlPipeHandle, NULL))
+ {
+ DWORD dwProcessId = 0;
+ DWORD dwRead = 0;
- if (!Result)
- {
- /* Close control pipe */
- CloseHandle(Service->ControlPipeHandle);
- Service->ControlPipeHandle = INVALID_HANDLE_VALUE;
+ DPRINT("Control pipe connected!\n");
- DPRINT("Starting '%S' failed!\n", Service->ServiceName.Buffer);
- Status = STATUS_UNSUCCESSFUL;
- }
- else
- {
- DPRINT("Process Id: %lu Handle %lx\n",
- ProcessInformation.dwProcessId,
- ProcessInformation.hProcess);
- DPRINT("Thread Id: %lu Handle %lx\n",
- ProcessInformation.dwThreadId,
- ProcessInformation.hThread);
-
- /* Get process and thread ids */
- Service->ProcessId = ProcessInformation.dwProcessId;
- Service->ThreadId = ProcessInformation.dwThreadId;
-
- /* Resume Thread */
- ResumeThread(ProcessInformation.hThread);
-
- /* FIXME: connect control pipe */
- if (ConnectNamedPipe(Service->ControlPipeHandle, NULL))
- {
- DPRINT("Control pipe connected!\n");
- Status = STATUS_SUCCESS;
- }
- else
- {
- DPRINT1("Connecting control pipe failed!\n");
-
- /* Close control pipe */
- CloseHandle(Service->ControlPipeHandle);
- Service->ControlPipeHandle = INVALID_HANDLE_VALUE;
- Service->ProcessId = 0;
- Service->ThreadId = 0;
- Status = STATUS_UNSUCCESSFUL;
- }
+ /* Read thread id from pipe */
+ if (!ReadFile(Service->ControlPipeHandle,
+ (LPVOID)&dwProcessId,
+ sizeof(DWORD),
+ &dwRead,
+ NULL))
+ {
+ DPRINT1("Reading the service control pipe failed (Error %lu)\n",
+ GetLastError());
+ Status = STATUS_UNSUCCESSFUL;
+ }
+ else
+ {
+ DPRINT("Received process id %lu\n", dwProcessId);
- /* Close process and thread handle */
- CloseHandle(ProcessInformation.hThread);
- CloseHandle(ProcessInformation.hProcess);
- }
+ /* FIXME: Send start command */
+
+ Status = STATUS_SUCCESS;
}
}
+ else
+ {
+ DPRINT("Connecting control pipe failed!\n");
+
+ /* Close control pipe */
+ CloseHandle(Service->ControlPipeHandle);
+ Service->ControlPipeHandle = INVALID_HANDLE_VALUE;
+ Service->ProcessId = 0;
+ Service->ThreadId = 0;
+ Status = STATUS_UNSUCCESSFUL;
+ }
+
+ ScmSendStartCommand(Service, NULL);
+
+ /* Close process and thread handle */
+ CloseHandle(ProcessInformation.hThread);
+ CloseHandle(ProcessInformation.hProcess);
+
+ return Status;
+}
+
+
+static NTSTATUS
+ScmStartService(PSERVICE Service,
+ PSERVICE_GROUP Group)
+{
+ NTSTATUS Status;
+
+ DPRINT("ScmStartService() called\n");
+
+ Service->ControlPipeHandle = INVALID_HANDLE_VALUE;
+ DPRINT("Service->Type: %u\n", Service->Type);
+
+ if (Service->Type == SERVICE_KERNEL_DRIVER ||
+ Service->Type == SERVICE_FILE_SYSTEM_DRIVER ||
+ Service->Type == SERVICE_RECOGNIZER_DRIVER)
+ {
+ /* Load driver */
+ DPRINT(" Path: %wZ\n", &Service->RegistryPath);
+ Status = NtLoadDriver(&Service->RegistryPath);
+ }
+ else
+ {
+ /* Start user-mode service */
+ Status = ScmStartUserModeService(Service);
+ }
+
+ DPRINT("ScmStartService() done (Status %lx)\n", Status);
-Done:
if (NT_SUCCESS(Status))
{
if (Group != NULL)
{
Group->ServicesRunning = TRUE;
}
- Service->ServiceRunning = TRUE;
+ Service->CurrentState = SERVICE_RUNNING;
}
#if 0
else
{
- if (CurrentService->ErrorControl == 1)
+ switch (Service->ErrorControl)
{
- /* Log error */
-
- }
- else if (CurrentService->ErrorControl == 2)
- {
- if (IsLastKnownGood == FALSE)
- {
- /* Boot last known good configuration */
-
- }
- }
- else if (CurrentService->ErrorControl == 3)
- {
- if (IsLastKnownGood == FALSE)
- {
- /* Boot last known good configuration */
-
- }
- else
- {
- /* BSOD! */
-
- }
+ case SERVICE_ERROR_NORMAL:
+ /* FIXME: Log error */
+ break;
+
+ case SERVICE_ERROR_SEVERE:
+ if (IsLastKnownGood == FALSE)
+ {
+ /* FIXME: Boot last known good configuration */
+ }
+ break;
+
+ case SERVICE_ERROR_CRITICAL:
+ if (IsLastKnownGood == FALSE)
+ {
+ /* FIXME: Boot last known good configuration */
+ }
+ else
+ {
+ /* FIXME: BSOD! */
+ }
+ break;
}
}
#endif
- return(STATUS_SUCCESS);
+ return Status;
}
PLIST_ENTRY ServiceEntry;
PSERVICE_GROUP CurrentGroup;
PSERVICE CurrentService;
+ ULONG i;
/* Clear 'ServiceVisited' flag */
ServiceEntry = ServiceListHead.Flink;
DPRINT("Group '%wZ'\n", &CurrentGroup->GroupName);
+ /* Start all services witch have a valid tag */
+ for (i = 0; i < CurrentGroup->TagCount; i++)
+ {
+ ServiceEntry = ServiceListHead.Flink;
+ while (ServiceEntry != &ServiceListHead)
+ {
+ CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
+
+ if ((RtlEqualUnicodeString(&CurrentGroup->GroupName, &CurrentService->ServiceGroup, TRUE)) &&
+ (CurrentService->Start == SERVICE_AUTO_START) &&
+ (CurrentService->ServiceVisited == FALSE) &&
+ (CurrentService->Tag == CurrentGroup->TagArray[i]))
+ {
+ CurrentService->ServiceVisited = TRUE;
+ ScmStartService(CurrentService,
+ CurrentGroup);
+ }
+
+ ServiceEntry = ServiceEntry->Flink;
+ }
+ }
+
+ /* Start all services which have an invalid tag or which do not have a tag */
ServiceEntry = ServiceListHead.Flink;
while (ServiceEntry != &ServiceListHead)
{
{
CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
- if ((CurrentGroup->GroupName.Length > 0) &&
+ if ((CurrentService->ServiceGroup.Length != 0) &&
(CurrentService->Start == SERVICE_AUTO_START) &&
(CurrentService->ServiceVisited == FALSE))
{
{
CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
- if ((CurrentGroup->GroupName.Length == 0) &&
+ if ((CurrentService->ServiceGroup.Length == 0) &&
(CurrentService->Start == SERVICE_AUTO_START) &&
(CurrentService->ServiceVisited == FALSE))
{
}
}
+
+DWORD
+ScmMarkServiceForDelete(PSERVICE pService)
+{
+ DPRINT1("ScmMarkServiceForDelete() called\n");
+
+ return ERROR_SUCCESS;
+}
+
/* EOF */