database.c
来自「ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机」· C语言 代码 · 共 1,004 行 · 第 1/2 页
C
1,004 行
if (!NT_SUCCESS(Status))
break;
DPRINT("Comparing: '%S' '%wZ'\n", Service->lpServiceName, &DirInfo->Name);
if (_wcsicmp(Service->lpServiceName, DirInfo->Name.Buffer) == 0)
{
DPRINT("Found: '%S' '%wZ'\n",
Service->lpServiceName, &DirInfo->Name);
/* 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");
}
DWORD
ScmControlService(PSERVICE Service,
DWORD dwControl,
LPSERVICE_STATUS lpServiceStatus)
{
PSCM_CONTROL_PACKET ControlPacket;
DWORD Count;
DPRINT("ScmControlService() called\n");
ControlPacket = (SCM_CONTROL_PACKET*) HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(SCM_CONTROL_PACKET));
if (ControlPacket == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
ControlPacket->dwControl = dwControl;
/* Send the start command */
WriteFile(Service->ControlPipeHandle,
ControlPacket,
sizeof(SCM_CONTROL_PACKET),
&Count,
NULL);
/* FIXME: Read the reply */
/* Release the contol packet */
HeapFree(GetProcessHeap(),
0,
ControlPacket);
DPRINT("ScmControlService) done\n");
return ERROR_SUCCESS;
}
static DWORD
ScmSendStartCommand(PSERVICE Service,
LPWSTR Arguments)
{
PSCM_CONTROL_PACKET ControlPacket;
DWORD TotalLength;
DWORD ArgsLength = 0;
DWORD Length;
PWSTR Ptr;
DWORD Count;
DPRINT("ScmSendStartCommand() called\n");
/* Calculate the total length of the start command line */
TotalLength = wcslen(Service->lpServiceName) + 1;
if (Arguments != NULL)
{
Ptr = Arguments;
while (*Ptr)
{
Length = wcslen(Ptr) + 1;
TotalLength += Length;
ArgsLength += Length;
Ptr += Length;
DPRINT("Arg: %S\n", Ptr);
}
}
TotalLength++;
DPRINT("ArgsLength: %ld TotalLength: %ld\n", ArgsLength, TotalLength);
/* Allocate a control packet */
ControlPacket = (SCM_CONTROL_PACKET*) HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(SCM_CONTROL_PACKET) + (TotalLength - 1) * sizeof(WCHAR));
if (ControlPacket == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
ControlPacket->dwControl = SERVICE_CONTROL_START;
ControlPacket->dwSize = TotalLength;
Ptr = &ControlPacket->szArguments[0];
wcscpy(Ptr, Service->lpServiceName);
Ptr += (wcslen(Service->lpServiceName) + 1);
/* Copy argument list */
if (Arguments != NULL)
{
memcpy(Ptr, Arguments, ArgsLength);
Ptr += ArgsLength;
}
/* Terminate the argument list */
*Ptr = 0;
/* Send the start command */
WriteFile(Service->ControlPipeHandle,
ControlPacket,
sizeof(SCM_CONTROL_PACKET) + (TotalLength - 1) * sizeof(WCHAR),
&Count,
NULL);
/* FIXME: Read the reply */
/* Release the contol packet */
HeapFree(GetProcessHeap(),
0,
ControlPacket);
DPRINT("ScmSendStartCommand() done\n");
return ERROR_SUCCESS;
}
static DWORD
ScmStartUserModeService(PSERVICE Service,
LPWSTR lpArgs)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[3];
PROCESS_INFORMATION ProcessInformation;
STARTUPINFOW StartupInfo;
UNICODE_STRING ImagePath;
ULONG Type;
BOOL Result;
NTSTATUS Status;
DWORD dwError = ERROR_SUCCESS;
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 RtlNtStatusToDosError(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 GetLastError();
}
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)
{
dwError = GetLastError();
/* Close control pipe */
CloseHandle(Service->ControlPipeHandle);
Service->ControlPipeHandle = INVALID_HANDLE_VALUE;
DPRINT1("Starting '%S' failed!\n", Service->lpServiceName);
return dwError;
}
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) ?
TRUE : (dwError = GetLastError()) == ERROR_PIPE_CONNECTED)
{
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))
{
dwError = GetLastError();
DPRINT1("Reading the service control pipe failed (Error %lu)\n",
dwError);
}
else
{
DPRINT("Received process id %lu\n", dwProcessId);
/* Send start command */
dwError = ScmSendStartCommand(Service, lpArgs);
}
}
else
{
DPRINT1("Connecting control pipe failed! (Error %lu)\n", dwError);
/* Close control pipe */
CloseHandle(Service->ControlPipeHandle);
Service->ControlPipeHandle = INVALID_HANDLE_VALUE;
Service->ProcessId = 0;
Service->ThreadId = 0;
}
/* Close process and thread handle */
CloseHandle(ProcessInformation.hThread);
CloseHandle(ProcessInformation.hProcess);
return dwError;
}
DWORD
ScmStartService(PSERVICE Service, LPWSTR lpArgs)
{
PSERVICE_GROUP Group = Service->lpGroup;
DWORD dwError = ERROR_SUCCESS;
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 */
dwError = ScmLoadDriver(Service);
if (dwError == ERROR_SUCCESS)
Service->Status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
}
else
{
/* Start user-mode service */
dwError = ScmStartUserModeService(Service, lpArgs);
}
DPRINT("ScmStartService() done (Error %lu)\n", dwError);
if (dwError == ERROR_SUCCESS)
{
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 dwError;
}
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, NULL);
}
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, NULL);
}
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 + -
显示快捷键?