database.c
来自「一个类似windows」· C语言 代码 · 共 928 行 · 第 1/2 页
C
928 行
/* FIXME: Add current service to 'failed service' list */
DPRINT("Service '%S' failed\n", Service->lpServiceName);
break;
}
if (!NT_SUCCESS(Status))
break;
DPRINT("Comparing: '%S' '%wZ'\n", Service->lpServiceName, &DirInfo->ObjectName);
if (_wcsicmp(Service->lpServiceName, DirInfo->ObjectName.Buffer) == 0)
{
DPRINT("Found: '%S' '%wZ'\n",
Service->lpServiceName, &DirInfo->ObjectName);
/* Mark service as 'running' */
Service->Status.dwCurrentState = SERVICE_RUNNING;
/* Mark the service group as 'running' */
if (Service->lpGroup != NULL)
{
Service->lpGroup->ServicesRunning = TRUE;
}
break;
}
}
HeapFree(GetProcessHeap(),
0,
DirInfo);
NtClose(DirHandle);
return STATUS_SUCCESS;
}
VOID
ScmGetBootAndSystemDriverState(VOID)
{
PLIST_ENTRY ServiceEntry;
PSERVICE CurrentService;
DPRINT("ScmGetBootAndSystemDriverState() called\n");
ServiceEntry = ServiceListHead.Flink;
while (ServiceEntry != &ServiceListHead)
{
CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
if (CurrentService->dwStartType == SERVICE_BOOT_START ||
CurrentService->dwStartType == SERVICE_SYSTEM_START)
{
/* Check driver */
DPRINT(" Checking service: %S\n", CurrentService->lpServiceName);
ScmCheckDriver(CurrentService);
}
ServiceEntry = ServiceEntry->Flink;
}
DPRINT("ScmGetBootAndSystemDriverState() done\n");
}
static NTSTATUS
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->lpServiceName) + 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->lpServiceName);
Ptr += (wcslen(Service->lpServiceName) + 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;
ULONG Type;
BOOL Result;
NTSTATUS Status;
RtlInitUnicodeString(&ImagePath, NULL);
/* Get service data */
RtlZeroMemory(&QueryTable,
sizeof(QueryTable));
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->lpServiceName,
QueryTable,
NULL,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
return Status;
}
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)
{
DPRINT1("Failed to create control pipe!\n");
return STATUS_UNSUCCESSFUL;
}
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;
DPRINT1("Starting '%S' failed!\n", Service->lpServiceName);
return STATUS_UNSUCCESSFUL;
}
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);
/* Connect control pipe */
if (ConnectNamedPipe(Service->ControlPipeHandle, NULL))
{
DWORD dwProcessId = 0;
DWORD dwRead = 0;
DPRINT("Control pipe connected!\n");
/* 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);
/* 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: %lu\n", Service->Status.dwServiceType);
if (Service->Status.dwServiceType & SERVICE_DRIVER)
{
/* Load driver */
Status = ScmLoadDriver(Service);
if (Status == STATUS_SUCCESS)
Service->Status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
}
else
{
/* Start user-mode service */
Status = ScmStartUserModeService(Service);
}
DPRINT("ScmStartService() done (Status %lx)\n", Status);
if (NT_SUCCESS(Status))
{
if (Group != NULL)
{
Group->ServicesRunning = TRUE;
}
Service->Status.dwCurrentState = SERVICE_RUNNING;
}
#if 0
else
{
switch (Service->ErrorControl)
{
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;
}
VOID
ScmAutoStartServices(VOID)
{
PLIST_ENTRY GroupEntry;
PLIST_ENTRY ServiceEntry;
PSERVICE_GROUP CurrentGroup;
PSERVICE CurrentService;
ULONG i;
/* Clear 'ServiceVisited' flag */
ServiceEntry = ServiceListHead.Flink;
while (ServiceEntry != &ServiceListHead)
{
CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
CurrentService->ServiceVisited = FALSE;
ServiceEntry = ServiceEntry->Flink;
}
/* Start all services which are members of an existing group */
GroupEntry = GroupListHead.Flink;
while (GroupEntry != &GroupListHead)
{
CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
DPRINT("Group '%S'\n", CurrentGroup->lpGroupName);
/* 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 ((CurrentService->lpGroup == CurrentGroup) &&
(CurrentService->dwStartType == SERVICE_AUTO_START) &&
(CurrentService->ServiceVisited == FALSE) &&
(CurrentService->dwTag == 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 ((CurrentService->lpGroup == CurrentGroup) &&
(CurrentService->dwStartType == SERVICE_AUTO_START) &&
(CurrentService->ServiceVisited == FALSE))
{
CurrentService->ServiceVisited = TRUE;
ScmStartService(CurrentService,
CurrentGroup);
}
ServiceEntry = ServiceEntry->Flink;
}
GroupEntry = GroupEntry->Flink;
}
/* Start all services which are members of any non-existing group */
ServiceEntry = ServiceListHead.Flink;
while (ServiceEntry != &ServiceListHead)
{
CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
if ((CurrentService->lpGroup != NULL) &&
(CurrentService->dwStartType == SERVICE_AUTO_START) &&
(CurrentService->ServiceVisited == FALSE))
{
CurrentService->ServiceVisited = TRUE;
ScmStartService(CurrentService,
NULL);
}
ServiceEntry = ServiceEntry->Flink;
}
/* Start all services which are not a member of any group */
ServiceEntry = ServiceListHead.Flink;
while (ServiceEntry != &ServiceListHead)
{
CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
if ((CurrentService->lpGroup == NULL) &&
(CurrentService->dwStartType == SERVICE_AUTO_START) &&
(CurrentService->ServiceVisited == FALSE))
{
CurrentService->ServiceVisited = TRUE;
ScmStartService(CurrentService,
NULL);
}
ServiceEntry = ServiceEntry->Flink;
}
/* Clear 'ServiceVisited' flag again */
ServiceEntry = ServiceListHead.Flink;
while (ServiceEntry != &ServiceListHead)
{
CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
CurrentService->ServiceVisited = FALSE;
ServiceEntry = ServiceEntry->Flink;
}
}
/* EOF */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?