mirror of
https://github.com/reactos/reactos.git
synced 2025-07-04 09:01:21 +00:00
[SERVICES]
Implement service image records. This will enable us to run executables that contain multiple services and control them individually. svn path=/trunk/; revision=52717
This commit is contained in:
parent
094e863db8
commit
17c51414f2
3 changed files with 273 additions and 147 deletions
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
/* GLOBALS *******************************************************************/
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
|
LIST_ENTRY ImageListHead;
|
||||||
LIST_ENTRY ServiceListHead;
|
LIST_ENTRY ServiceListHead;
|
||||||
|
|
||||||
static RTL_RESOURCE DatabaseLock;
|
static RTL_RESOURCE DatabaseLock;
|
||||||
|
@ -34,6 +35,227 @@ static CRITICAL_SECTION ControlServiceCriticalSection;
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
static DWORD
|
||||||
|
ScmCreateNewControlPipe(PSERVICE_IMAGE pServiceImage)
|
||||||
|
{
|
||||||
|
WCHAR szControlPipeName[MAX_PATH + 1];
|
||||||
|
HKEY hServiceCurrentKey = INVALID_HANDLE_VALUE;
|
||||||
|
DWORD ServiceCurrent = 0;
|
||||||
|
DWORD KeyDisposition;
|
||||||
|
DWORD dwKeySize;
|
||||||
|
DWORD dwError;
|
||||||
|
|
||||||
|
/* Get the service number */
|
||||||
|
/* TODO: Create registry entry with correct write access */
|
||||||
|
dwError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
|
||||||
|
L"SYSTEM\\CurrentControlSet\\Control\\ServiceCurrent", 0, NULL,
|
||||||
|
REG_OPTION_VOLATILE,
|
||||||
|
KEY_WRITE | KEY_READ,
|
||||||
|
NULL,
|
||||||
|
&hServiceCurrentKey,
|
||||||
|
&KeyDisposition);
|
||||||
|
if (dwError != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT1("RegCreateKeyEx() failed with error %lu\n", dwError);
|
||||||
|
return dwError;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (KeyDisposition == REG_OPENED_EXISTING_KEY)
|
||||||
|
{
|
||||||
|
dwKeySize = sizeof(DWORD);
|
||||||
|
dwError = RegQueryValueExW(hServiceCurrentKey,
|
||||||
|
L"", 0, NULL, (BYTE*)&ServiceCurrent, &dwKeySize);
|
||||||
|
|
||||||
|
if (dwError != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
RegCloseKey(hServiceCurrentKey);
|
||||||
|
DPRINT1("RegQueryValueEx() failed with error %lu\n", dwError);
|
||||||
|
return dwError;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServiceCurrent++;
|
||||||
|
}
|
||||||
|
|
||||||
|
dwError = RegSetValueExW(hServiceCurrentKey, L"", 0, REG_DWORD, (BYTE*)&ServiceCurrent, sizeof(ServiceCurrent));
|
||||||
|
|
||||||
|
RegCloseKey(hServiceCurrentKey);
|
||||||
|
|
||||||
|
if (dwError != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT1("RegSetValueExW() failed (Error %lu)\n", dwError);
|
||||||
|
return dwError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create '\\.\pipe\net\NtControlPipeXXX' instance */
|
||||||
|
swprintf(szControlPipeName, L"\\\\.\\pipe\\net\\NtControlPipe%u", ServiceCurrent);
|
||||||
|
|
||||||
|
DPRINT("PipeName: %S\n", szControlPipeName);
|
||||||
|
|
||||||
|
pServiceImage->hControlPipe = CreateNamedPipeW(szControlPipeName,
|
||||||
|
PIPE_ACCESS_DUPLEX,
|
||||||
|
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
|
||||||
|
100,
|
||||||
|
8000,
|
||||||
|
4,
|
||||||
|
30000,
|
||||||
|
NULL);
|
||||||
|
DPRINT("CreateNamedPipeW(%S) done\n", szControlPipeName);
|
||||||
|
if (pServiceImage->hControlPipe == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to create control pipe!\n");
|
||||||
|
return GetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PSERVICE_IMAGE
|
||||||
|
ScmGetServiceImageByImagePath(LPWSTR lpImagePath)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY ImageEntry;
|
||||||
|
PSERVICE_IMAGE CurrentImage;
|
||||||
|
|
||||||
|
DPRINT("ScmGetServiceImageByImagePath() called\n");
|
||||||
|
|
||||||
|
ImageEntry = ImageListHead.Flink;
|
||||||
|
while (ImageEntry != &ImageListHead)
|
||||||
|
{
|
||||||
|
CurrentImage = CONTAINING_RECORD(ImageEntry,
|
||||||
|
SERVICE_IMAGE,
|
||||||
|
ImageListEntry);
|
||||||
|
if (_wcsicmp(CurrentImage->szImagePath, lpImagePath) == 0)
|
||||||
|
{
|
||||||
|
DPRINT("Found image: '%S'\n", CurrentImage->szImagePath);
|
||||||
|
return CurrentImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageEntry = ImageEntry->Flink;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT1("Couldn't find a matching image\n");
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static DWORD
|
||||||
|
ScmCreateOrReferenceServiceImage(PSERVICE pService)
|
||||||
|
{
|
||||||
|
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
|
||||||
|
UNICODE_STRING ImagePath;
|
||||||
|
PSERVICE_IMAGE pServiceImage = NULL;
|
||||||
|
NTSTATUS Status;
|
||||||
|
DWORD dwError = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
DPRINT("ScmCreateOrReferenceServiceImage()");
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&ImagePath, NULL);
|
||||||
|
|
||||||
|
/* Get service data */
|
||||||
|
RtlZeroMemory(&QueryTable,
|
||||||
|
sizeof(QueryTable));
|
||||||
|
|
||||||
|
QueryTable[0].Name = L"ImagePath";
|
||||||
|
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
|
||||||
|
QueryTable[0].EntryContext = &ImagePath;
|
||||||
|
|
||||||
|
Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
|
||||||
|
pService->lpServiceName,
|
||||||
|
QueryTable,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
|
||||||
|
return RtlNtStatusToDosError(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("ImagePath: '%wZ'\n", &ImagePath);
|
||||||
|
|
||||||
|
pServiceImage = ScmGetServiceImageByImagePath(ImagePath.Buffer);
|
||||||
|
if (pServiceImage == NULL)
|
||||||
|
{
|
||||||
|
/* Create a new service image */
|
||||||
|
pServiceImage = (PSERVICE_IMAGE)HeapAlloc(GetProcessHeap(),
|
||||||
|
HEAP_ZERO_MEMORY,
|
||||||
|
sizeof(SERVICE_IMAGE) + ((wcslen(ImagePath.Buffer) + 1) * sizeof(WCHAR)));
|
||||||
|
if (pServiceImage == NULL)
|
||||||
|
{
|
||||||
|
dwError = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
pServiceImage->dwImageRunCount = 1;
|
||||||
|
pServiceImage->hControlPipe = INVALID_HANDLE_VALUE;
|
||||||
|
pServiceImage->hProcess = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
|
/* Set the image path */
|
||||||
|
wcscpy(pServiceImage->szImagePath,
|
||||||
|
ImagePath.Buffer);
|
||||||
|
|
||||||
|
RtlFreeUnicodeString(&ImagePath);
|
||||||
|
|
||||||
|
/* Create the control pipe */
|
||||||
|
dwError = ScmCreateNewControlPipe(pServiceImage);
|
||||||
|
if (dwError != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, pServiceImage);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: Add more initialization code here */
|
||||||
|
|
||||||
|
|
||||||
|
/* Append service record */
|
||||||
|
InsertTailList(&ImageListHead,
|
||||||
|
&pServiceImage->ImageListEntry);
|
||||||
|
|
||||||
|
pService->lpImage = pServiceImage;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Create a new service image */
|
||||||
|
pService->lpImage->dwImageRunCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:;
|
||||||
|
RtlFreeUnicodeString(&ImagePath);
|
||||||
|
|
||||||
|
return dwError;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static VOID
|
||||||
|
ScmDereferenceServiceImage(PSERVICE_IMAGE pServiceImage)
|
||||||
|
{
|
||||||
|
DPRINT1("ScmDereferenceServiceImage() called\n");
|
||||||
|
|
||||||
|
pServiceImage->dwImageRunCount--;
|
||||||
|
|
||||||
|
if (pServiceImage->dwImageRunCount == 0)
|
||||||
|
{
|
||||||
|
DPRINT1("dwImageRunCount == 0\n");
|
||||||
|
|
||||||
|
/* FIXME: Terminate the process */
|
||||||
|
|
||||||
|
/* Remove the service image from the list */
|
||||||
|
RemoveEntryList(&pServiceImage->ImageListEntry);
|
||||||
|
|
||||||
|
/* Close the control pipe */
|
||||||
|
if (pServiceImage->hControlPipe != INVALID_HANDLE_VALUE)
|
||||||
|
CloseHandle(pServiceImage->hControlPipe);
|
||||||
|
|
||||||
|
/* Close the process handle */
|
||||||
|
if (pServiceImage->hProcess != INVALID_HANDLE_VALUE)
|
||||||
|
CloseHandle(pServiceImage->hProcess);
|
||||||
|
|
||||||
|
/* Release the service image */
|
||||||
|
HeapFree(GetProcessHeap(), 0, pServiceImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PSERVICE
|
PSERVICE
|
||||||
ScmGetServiceEntryByName(LPCWSTR lpServiceName)
|
ScmGetServiceEntryByName(LPCWSTR lpServiceName)
|
||||||
|
@ -173,9 +395,9 @@ ScmDeleteServiceRecord(PSERVICE lpService)
|
||||||
lpService->lpDisplayName != lpService->lpServiceName)
|
lpService->lpDisplayName != lpService->lpServiceName)
|
||||||
HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
|
HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
|
||||||
|
|
||||||
/* Decrement the image reference counter */
|
/* Dereference the service image */
|
||||||
if (lpService->lpImage)
|
if (lpService->lpImage)
|
||||||
lpService->lpImage->dwServiceRefCount--;
|
ScmDereferenceServiceImage(lpService->lpImage);
|
||||||
|
|
||||||
/* Decrement the group reference counter */
|
/* Decrement the group reference counter */
|
||||||
if (lpService->lpGroup)
|
if (lpService->lpGroup)
|
||||||
|
@ -183,9 +405,6 @@ ScmDeleteServiceRecord(PSERVICE lpService)
|
||||||
|
|
||||||
/* FIXME: SecurityDescriptor */
|
/* FIXME: SecurityDescriptor */
|
||||||
|
|
||||||
/* Close the control pipe */
|
|
||||||
if (lpService->ControlPipeHandle != INVALID_HANDLE_VALUE)
|
|
||||||
CloseHandle(lpService->ControlPipeHandle);
|
|
||||||
|
|
||||||
/* Remove the Service from the List */
|
/* Remove the Service from the List */
|
||||||
RemoveEntryList(&lpService->ServiceListEntry);
|
RemoveEntryList(&lpService->ServiceListEntry);
|
||||||
|
@ -330,6 +549,12 @@ done:;
|
||||||
if (lpDisplayName != NULL)
|
if (lpDisplayName != NULL)
|
||||||
HeapFree(GetProcessHeap(), 0, lpDisplayName);
|
HeapFree(GetProcessHeap(), 0, lpDisplayName);
|
||||||
|
|
||||||
|
if (lpService != NULL)
|
||||||
|
{
|
||||||
|
if (lpService->lpImage != NULL)
|
||||||
|
ScmDereferenceServiceImage(lpService->lpImage);
|
||||||
|
}
|
||||||
|
|
||||||
return dwError;
|
return dwError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,6 +704,7 @@ ScmCreateServiceDatabase(VOID)
|
||||||
return dwError;
|
return dwError;
|
||||||
|
|
||||||
/* Initialize basic variables */
|
/* Initialize basic variables */
|
||||||
|
InitializeListHead(&ImageListHead);
|
||||||
InitializeListHead(&ServiceListHead);
|
InitializeListHead(&ServiceListHead);
|
||||||
|
|
||||||
/* Initialize the database lock */
|
/* Initialize the database lock */
|
||||||
|
@ -711,14 +937,14 @@ ScmControlService(PSERVICE Service,
|
||||||
wcscpy(&ControlPacket->szArguments[0], Service->lpServiceName);
|
wcscpy(&ControlPacket->szArguments[0], Service->lpServiceName);
|
||||||
|
|
||||||
/* Send the control packet */
|
/* Send the control packet */
|
||||||
WriteFile(Service->ControlPipeHandle,
|
WriteFile(Service->lpImage->hControlPipe,
|
||||||
ControlPacket,
|
ControlPacket,
|
||||||
sizeof(SCM_CONTROL_PACKET) + (TotalLength * sizeof(WCHAR)),
|
sizeof(SCM_CONTROL_PACKET) + (TotalLength * sizeof(WCHAR)),
|
||||||
&dwWriteCount,
|
&dwWriteCount,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
/* Read the reply */
|
/* Read the reply */
|
||||||
ReadFile(Service->ControlPipeHandle,
|
ReadFile(Service->lpImage->hControlPipe,
|
||||||
&ReplyPacket,
|
&ReplyPacket,
|
||||||
sizeof(SCM_REPLY_PACKET),
|
sizeof(SCM_REPLY_PACKET),
|
||||||
&dwReadCount,
|
&dwReadCount,
|
||||||
|
@ -734,6 +960,12 @@ ScmControlService(PSERVICE Service,
|
||||||
dwError = ReplyPacket.dwError;
|
dwError = ReplyPacket.dwError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dwError == ERROR_SUCCESS &&
|
||||||
|
dwControl == SERVICE_CONTROL_STOP)
|
||||||
|
{
|
||||||
|
ScmDereferenceServiceImage(Service->lpImage);
|
||||||
|
}
|
||||||
|
|
||||||
LeaveCriticalSection(&ControlServiceCriticalSection);
|
LeaveCriticalSection(&ControlServiceCriticalSection);
|
||||||
|
|
||||||
DPRINT("ScmControlService() done\n");
|
DPRINT("ScmControlService() done\n");
|
||||||
|
@ -804,14 +1036,14 @@ ScmSendStartCommand(PSERVICE Service,
|
||||||
*Ptr = 0;
|
*Ptr = 0;
|
||||||
|
|
||||||
/* Send the start command */
|
/* Send the start command */
|
||||||
WriteFile(Service->ControlPipeHandle,
|
WriteFile(Service->lpImage->hControlPipe,
|
||||||
ControlPacket,
|
ControlPacket,
|
||||||
sizeof(SCM_CONTROL_PACKET) + (TotalLength - 1) * sizeof(WCHAR),
|
sizeof(SCM_CONTROL_PACKET) + (TotalLength - 1) * sizeof(WCHAR),
|
||||||
&dwWriteCount,
|
&dwWriteCount,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
/* Read the reply */
|
/* Read the reply */
|
||||||
ReadFile(Service->ControlPipeHandle,
|
ReadFile(Service->lpImage->hControlPipe,
|
||||||
&ReplyPacket,
|
&ReplyPacket,
|
||||||
sizeof(SCM_REPLY_PACKET),
|
sizeof(SCM_REPLY_PACKET),
|
||||||
&dwReadCount,
|
&dwReadCount,
|
||||||
|
@ -838,108 +1070,12 @@ ScmStartUserModeService(PSERVICE Service,
|
||||||
DWORD argc,
|
DWORD argc,
|
||||||
LPWSTR *argv)
|
LPWSTR *argv)
|
||||||
{
|
{
|
||||||
RTL_QUERY_REGISTRY_TABLE QueryTable[3];
|
|
||||||
PROCESS_INFORMATION ProcessInformation;
|
PROCESS_INFORMATION ProcessInformation;
|
||||||
STARTUPINFOW StartupInfo;
|
STARTUPINFOW StartupInfo;
|
||||||
UNICODE_STRING ImagePath;
|
|
||||||
ULONG Type;
|
|
||||||
DWORD ServiceCurrent = 0;
|
|
||||||
BOOL Result;
|
BOOL Result;
|
||||||
NTSTATUS Status;
|
|
||||||
DWORD dwError = ERROR_SUCCESS;
|
DWORD dwError = ERROR_SUCCESS;
|
||||||
WCHAR NtControlPipeName[MAX_PATH + 1];
|
|
||||||
HKEY hServiceCurrentKey = INVALID_HANDLE_VALUE;
|
|
||||||
DWORD KeyDisposition;
|
|
||||||
DWORD dwProcessId;
|
DWORD dwProcessId;
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
/* Get the service number */
|
|
||||||
/* TODO: Create registry entry with correct write access */
|
|
||||||
Status = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
|
|
||||||
L"SYSTEM\\CurrentControlSet\\Control\\ServiceCurrent", 0, NULL,
|
|
||||||
REG_OPTION_VOLATILE,
|
|
||||||
KEY_WRITE | KEY_READ,
|
|
||||||
NULL,
|
|
||||||
&hServiceCurrentKey,
|
|
||||||
&KeyDisposition);
|
|
||||||
|
|
||||||
if (ERROR_SUCCESS != Status)
|
|
||||||
{
|
|
||||||
DPRINT1("RegCreateKeyEx() failed with status %u\n", Status);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (REG_OPENED_EXISTING_KEY == KeyDisposition)
|
|
||||||
{
|
|
||||||
DWORD KeySize = sizeof(ServiceCurrent);
|
|
||||||
Status = RegQueryValueExW(hServiceCurrentKey, L"", 0, NULL, (BYTE*)&ServiceCurrent, &KeySize);
|
|
||||||
|
|
||||||
if (ERROR_SUCCESS != Status)
|
|
||||||
{
|
|
||||||
RegCloseKey(hServiceCurrentKey);
|
|
||||||
DPRINT1("RegQueryValueEx() failed with status %u\n", Status);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
ServiceCurrent++;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = RegSetValueExW(hServiceCurrentKey, L"", 0, REG_DWORD, (BYTE*)&ServiceCurrent, sizeof(ServiceCurrent));
|
|
||||||
|
|
||||||
RegCloseKey(hServiceCurrentKey);
|
|
||||||
|
|
||||||
if (ERROR_SUCCESS != Status)
|
|
||||||
{
|
|
||||||
DPRINT1("RegSetValueExW() failed (Status %lx)\n", Status);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create '\\.\pipe\net\NtControlPipeXXX' instance */
|
|
||||||
swprintf(NtControlPipeName, L"\\\\.\\pipe\\net\\NtControlPipe%u", ServiceCurrent);
|
|
||||||
|
|
||||||
DPRINT("Service: %p ImagePath: %wZ PipeName: %S\n", Service, &ImagePath, NtControlPipeName);
|
|
||||||
|
|
||||||
Service->ControlPipeHandle = CreateNamedPipeW(NtControlPipeName,
|
|
||||||
PIPE_ACCESS_DUPLEX,
|
|
||||||
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
|
|
||||||
100,
|
|
||||||
8000,
|
|
||||||
4,
|
|
||||||
30000,
|
|
||||||
NULL);
|
|
||||||
DPRINT("CreateNamedPipeW(%S) done\n", NtControlPipeName);
|
|
||||||
if (Service->ControlPipeHandle == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
DPRINT1("Failed to create control pipe!\n");
|
|
||||||
return GetLastError();
|
|
||||||
}
|
|
||||||
|
|
||||||
StartupInfo.cb = sizeof(StartupInfo);
|
StartupInfo.cb = sizeof(StartupInfo);
|
||||||
StartupInfo.lpReserved = NULL;
|
StartupInfo.lpReserved = NULL;
|
||||||
StartupInfo.lpDesktop = NULL;
|
StartupInfo.lpDesktop = NULL;
|
||||||
|
@ -949,7 +1085,7 @@ ScmStartUserModeService(PSERVICE Service,
|
||||||
StartupInfo.lpReserved2 = 0;
|
StartupInfo.lpReserved2 = 0;
|
||||||
|
|
||||||
Result = CreateProcessW(NULL,
|
Result = CreateProcessW(NULL,
|
||||||
ImagePath.Buffer,
|
Service->lpImage->szImagePath,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
FALSE,
|
FALSE,
|
||||||
|
@ -958,15 +1094,9 @@ ScmStartUserModeService(PSERVICE Service,
|
||||||
NULL,
|
NULL,
|
||||||
&StartupInfo,
|
&StartupInfo,
|
||||||
&ProcessInformation);
|
&ProcessInformation);
|
||||||
RtlFreeUnicodeString(&ImagePath);
|
|
||||||
|
|
||||||
if (!Result)
|
if (!Result)
|
||||||
{
|
{
|
||||||
dwError = GetLastError();
|
dwError = GetLastError();
|
||||||
/* Close control pipe */
|
|
||||||
CloseHandle(Service->ControlPipeHandle);
|
|
||||||
Service->ControlPipeHandle = INVALID_HANDLE_VALUE;
|
|
||||||
|
|
||||||
DPRINT1("Starting '%S' failed!\n", Service->lpServiceName);
|
DPRINT1("Starting '%S' failed!\n", Service->lpServiceName);
|
||||||
return dwError;
|
return dwError;
|
||||||
}
|
}
|
||||||
|
@ -978,15 +1108,15 @@ ScmStartUserModeService(PSERVICE Service,
|
||||||
ProcessInformation.dwThreadId,
|
ProcessInformation.dwThreadId,
|
||||||
ProcessInformation.hThread);
|
ProcessInformation.hThread);
|
||||||
|
|
||||||
/* Get process and thread ids */
|
/* Get process handle and id */
|
||||||
Service->ProcessId = ProcessInformation.dwProcessId;
|
Service->lpImage->dwProcessId = ProcessInformation.dwProcessId;
|
||||||
Service->ThreadId = ProcessInformation.dwThreadId;
|
Service->lpImage->hProcess = ProcessInformation.hProcess;
|
||||||
|
|
||||||
/* Resume Thread */
|
/* Resume Thread */
|
||||||
ResumeThread(ProcessInformation.hThread);
|
ResumeThread(ProcessInformation.hThread);
|
||||||
|
|
||||||
/* Connect control pipe */
|
/* Connect control pipe */
|
||||||
if (ConnectNamedPipe(Service->ControlPipeHandle, NULL) ?
|
if (ConnectNamedPipe(Service->lpImage->hControlPipe, NULL) ?
|
||||||
TRUE : (dwError = GetLastError()) == ERROR_PIPE_CONNECTED)
|
TRUE : (dwError = GetLastError()) == ERROR_PIPE_CONNECTED)
|
||||||
{
|
{
|
||||||
DWORD dwRead = 0;
|
DWORD dwRead = 0;
|
||||||
|
@ -994,7 +1124,7 @@ ScmStartUserModeService(PSERVICE Service,
|
||||||
DPRINT("Control pipe connected!\n");
|
DPRINT("Control pipe connected!\n");
|
||||||
|
|
||||||
/* Read SERVICE_STATUS_HANDLE from pipe */
|
/* Read SERVICE_STATUS_HANDLE from pipe */
|
||||||
if (!ReadFile(Service->ControlPipeHandle,
|
if (!ReadFile(Service->lpImage->hControlPipe,
|
||||||
(LPVOID)&dwProcessId,
|
(LPVOID)&dwProcessId,
|
||||||
sizeof(DWORD),
|
sizeof(DWORD),
|
||||||
&dwRead,
|
&dwRead,
|
||||||
|
@ -1015,17 +1145,10 @@ ScmStartUserModeService(PSERVICE Service,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DPRINT1("Connecting control pipe failed! (Error %lu)\n", dwError);
|
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 */
|
/* Close thread handle */
|
||||||
CloseHandle(ProcessInformation.hThread);
|
CloseHandle(ProcessInformation.hThread);
|
||||||
CloseHandle(ProcessInformation.hProcess);
|
|
||||||
|
|
||||||
return dwError;
|
return dwError;
|
||||||
}
|
}
|
||||||
|
@ -1051,7 +1174,6 @@ ScmStartService(PSERVICE Service, DWORD argc, LPWSTR *argv)
|
||||||
return ERROR_SERVICE_ALREADY_RUNNING;
|
return ERROR_SERVICE_ALREADY_RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
Service->ControlPipeHandle = INVALID_HANDLE_VALUE;
|
|
||||||
DPRINT("Service->Type: %lu\n", Service->Status.dwServiceType);
|
DPRINT("Service->Type: %lu\n", Service->Status.dwServiceType);
|
||||||
|
|
||||||
if (Service->Status.dwServiceType & SERVICE_DRIVER)
|
if (Service->Status.dwServiceType & SERVICE_DRIVER)
|
||||||
|
@ -1067,6 +1189,9 @@ ScmStartService(PSERVICE Service, DWORD argc, LPWSTR *argv)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Start user-mode service */
|
/* Start user-mode service */
|
||||||
|
dwError = ScmCreateOrReferenceServiceImage(Service);
|
||||||
|
if (dwError == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
dwError = ScmStartUserModeService(Service, argc, argv);
|
dwError = ScmStartUserModeService(Service, argc, argv);
|
||||||
if (dwError == ERROR_SUCCESS)
|
if (dwError == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
|
@ -1076,6 +1201,12 @@ ScmStartService(PSERVICE Service, DWORD argc, LPWSTR *argv)
|
||||||
Service->Status.dwCurrentState = SERVICE_RUNNING;
|
Service->Status.dwCurrentState = SERVICE_RUNNING;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScmDereferenceServiceImage(Service->lpImage);
|
||||||
|
Service->lpImage = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LeaveCriticalSection(&ControlServiceCriticalSection);
|
LeaveCriticalSection(&ControlServiceCriticalSection);
|
||||||
|
|
|
@ -723,15 +723,6 @@ DWORD RControlService(
|
||||||
if ((dwError == ERROR_SUCCESS) && (pcbBytesNeeded))
|
if ((dwError == ERROR_SUCCESS) && (pcbBytesNeeded))
|
||||||
dwError = ERROR_DEPENDENT_SERVICES_RUNNING;
|
dwError = ERROR_DEPENDENT_SERVICES_RUNNING;
|
||||||
|
|
||||||
if (dwError == ERROR_SUCCESS &&
|
|
||||||
dwControl == SERVICE_CONTROL_STOP &&
|
|
||||||
lpServiceStatus->dwCurrentState == SERVICE_STOPPED)
|
|
||||||
{
|
|
||||||
lpService->ProcessId = 0; /* FIXME */
|
|
||||||
lpService->ThreadId = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return dwError;
|
return dwError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4897,7 +4888,7 @@ DWORD RQueryServiceStatusEx(
|
||||||
&lpService->Status,
|
&lpService->Status,
|
||||||
sizeof(SERVICE_STATUS));
|
sizeof(SERVICE_STATUS));
|
||||||
|
|
||||||
lpStatus->dwProcessId = lpService->ProcessId; /* FIXME */
|
lpStatus->dwProcessId = (lpService->lpImage != NULL) ? lpService->lpImage->dwProcessId : 0; /* FIXME */
|
||||||
lpStatus->dwServiceFlags = 0; /* FIXME */
|
lpStatus->dwServiceFlags = 0; /* FIXME */
|
||||||
|
|
||||||
/* Unlock the service database */
|
/* Unlock the service database */
|
||||||
|
@ -5282,7 +5273,8 @@ DWORD REnumServicesStatusExW(
|
||||||
memcpy(&lpStatusPtr->ServiceStatusProcess,
|
memcpy(&lpStatusPtr->ServiceStatusProcess,
|
||||||
&CurrentService->Status,
|
&CurrentService->Status,
|
||||||
sizeof(SERVICE_STATUS));
|
sizeof(SERVICE_STATUS));
|
||||||
lpStatusPtr->ServiceStatusProcess.dwProcessId = CurrentService->ProcessId; /* FIXME */
|
lpStatusPtr->ServiceStatusProcess.dwProcessId =
|
||||||
|
(CurrentService->lpImage != NULL) ? CurrentService->lpImage->dwProcessId : 0; /* FIXME */
|
||||||
lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
|
lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
|
||||||
|
|
||||||
lpStatusPtr++;
|
lpStatusPtr++;
|
||||||
|
|
|
@ -27,8 +27,14 @@ typedef struct _SERVICE_GROUP
|
||||||
|
|
||||||
typedef struct _SERVICE_IMAGE
|
typedef struct _SERVICE_IMAGE
|
||||||
{
|
{
|
||||||
DWORD dwServiceRefCount; // Number of running services of this image
|
LIST_ENTRY ImageListEntry;
|
||||||
DWORD Dummy;
|
DWORD dwImageRunCount;
|
||||||
|
|
||||||
|
HANDLE hControlPipe;
|
||||||
|
HANDLE hProcess;
|
||||||
|
DWORD dwProcessId;
|
||||||
|
|
||||||
|
WCHAR szImagePath[1];
|
||||||
} SERVICE_IMAGE, *PSERVICE_IMAGE;
|
} SERVICE_IMAGE, *PSERVICE_IMAGE;
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,10 +60,6 @@ typedef struct _SERVICE
|
||||||
|
|
||||||
BOOLEAN ServiceVisited;
|
BOOLEAN ServiceVisited;
|
||||||
|
|
||||||
HANDLE ControlPipeHandle;
|
|
||||||
ULONG ProcessId;
|
|
||||||
ULONG ThreadId;
|
|
||||||
|
|
||||||
WCHAR szServiceName[1];
|
WCHAR szServiceName[1];
|
||||||
} SERVICE, *PSERVICE;
|
} SERVICE, *PSERVICE;
|
||||||
|
|
||||||
|
@ -66,6 +68,7 @@ typedef struct _SERVICE
|
||||||
|
|
||||||
extern LIST_ENTRY ServiceListHead;
|
extern LIST_ENTRY ServiceListHead;
|
||||||
extern LIST_ENTRY GroupListHead;
|
extern LIST_ENTRY GroupListHead;
|
||||||
|
extern LIST_ENTRY ImageListHead;
|
||||||
extern BOOL ScmShutdown;
|
extern BOOL ScmShutdown;
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue