mirror of
https://github.com/reactos/reactos.git
synced 2025-07-04 14:01:23 +00:00
Use the service contol pipe to send a start command in order to start a service thread.
svn path=/trunk/; revision=13350
This commit is contained in:
parent
91337fece1
commit
9f44705b10
3 changed files with 353 additions and 148 deletions
24
reactos/include/services/services.h
Normal file
24
reactos/include/services/services.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/* $Id$
|
||||||
|
*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS kernel
|
||||||
|
* FILE: include/services/services.h
|
||||||
|
* PURPOSE: Private interface between SERVICES.EXE and ADVAPI32.DLL
|
||||||
|
* PROGRAMMER: Eric Kohl
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SERVICES_SERVICES_H__
|
||||||
|
#define __SERVICES_SERVICES_H__
|
||||||
|
|
||||||
|
#define SCM_START_COMMAND 1
|
||||||
|
|
||||||
|
typedef struct _SCM_START_PACKET
|
||||||
|
{
|
||||||
|
ULONG Command;
|
||||||
|
ULONG Size;
|
||||||
|
WCHAR Arguments[1];
|
||||||
|
} SCM_START_PACKET, *PSCM_START_PACKET;
|
||||||
|
|
||||||
|
#endif /* __SERVICES_SERVICES_H__ */
|
||||||
|
|
||||||
|
/* EOF */
|
|
@ -13,6 +13,8 @@
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include "advapi32.h"
|
#include "advapi32.h"
|
||||||
|
#include <services/services.h>
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
|
@ -23,9 +25,15 @@ typedef struct _ACTIVE_SERVICE
|
||||||
{
|
{
|
||||||
DWORD ThreadId;
|
DWORD ThreadId;
|
||||||
UNICODE_STRING ServiceName;
|
UNICODE_STRING ServiceName;
|
||||||
LPSERVICE_MAIN_FUNCTIONW MainFunction;
|
union
|
||||||
|
{
|
||||||
|
LPSERVICE_MAIN_FUNCTIONA lpFuncA;
|
||||||
|
LPSERVICE_MAIN_FUNCTIONW lpFuncW;
|
||||||
|
} Main;
|
||||||
LPHANDLER_FUNCTION HandlerFunction;
|
LPHANDLER_FUNCTION HandlerFunction;
|
||||||
SERVICE_STATUS ServiceStatus;
|
SERVICE_STATUS ServiceStatus;
|
||||||
|
BOOL bUnicode;
|
||||||
|
LPWSTR Arguments;
|
||||||
} ACTIVE_SERVICE, *PACTIVE_SERVICE;
|
} ACTIVE_SERVICE, *PACTIVE_SERVICE;
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,7 +41,6 @@ typedef struct _ACTIVE_SERVICE
|
||||||
|
|
||||||
static DWORD dwActiveServiceCount = 0;
|
static DWORD dwActiveServiceCount = 0;
|
||||||
static PACTIVE_SERVICE lpActiveServices = NULL;
|
static PACTIVE_SERVICE lpActiveServices = NULL;
|
||||||
/* static PHANDLE ActiveServicesThreadHandles; */ /* uncomment when in use */
|
|
||||||
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
@ -80,15 +87,53 @@ static DWORD WINAPI
|
||||||
ScServiceMainStub(LPVOID Context)
|
ScServiceMainStub(LPVOID Context)
|
||||||
{
|
{
|
||||||
PACTIVE_SERVICE lpService;
|
PACTIVE_SERVICE lpService;
|
||||||
|
DWORD dwArgCount = 0;
|
||||||
|
DWORD dwLength = 0;
|
||||||
|
|
||||||
lpService = (PACTIVE_SERVICE)Context;
|
lpService = (PACTIVE_SERVICE)Context;
|
||||||
|
|
||||||
DPRINT("ScServiceMainStub() called\n");
|
DPRINT("ScServiceMainStub() called\n");
|
||||||
|
|
||||||
/* FIXME: Send argc and argv (from command line) as arguments */
|
/* Count arguments */
|
||||||
|
while (lpService->Arguments[dwLength])
|
||||||
|
{
|
||||||
|
dwLength += wcslen(&lpService->Arguments[dwLength]) + 1;
|
||||||
|
dwArgCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build the argument vector and call the main service routine */
|
||||||
|
if (lpService->bUnicode)
|
||||||
|
{
|
||||||
|
LPWSTR *lpArgVector;
|
||||||
|
LPWSTR Ptr;
|
||||||
|
|
||||||
(lpService->MainFunction)(0, NULL);
|
lpArgVector = HeapAlloc(GetProcessHeap(),
|
||||||
|
HEAP_ZERO_MEMORY,
|
||||||
|
(dwArgCount + 1) * sizeof(LPWSTR));
|
||||||
|
if (lpArgVector == NULL)
|
||||||
|
return ERROR_OUTOFMEMORY;
|
||||||
|
|
||||||
|
dwArgCount = 0;
|
||||||
|
Ptr = lpService->Arguments;
|
||||||
|
while (*Ptr)
|
||||||
|
{
|
||||||
|
lpArgVector[dwArgCount] = Ptr;
|
||||||
|
|
||||||
|
dwArgCount++;
|
||||||
|
Ptr += (wcslen(Ptr) + 1);
|
||||||
|
}
|
||||||
|
lpArgVector[dwArgCount] = NULL;
|
||||||
|
|
||||||
|
(lpService->Main.lpFuncW)(dwArgCount, lpArgVector);
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(),
|
||||||
|
0,
|
||||||
|
lpArgVector);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(lpService->Main.lpFuncA)(0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -141,17 +186,29 @@ ScConnectControlPipe(HANDLE *hPipe)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static BOOL
|
|
||||||
ScServiceDispatcher(HANDLE hPipe,
|
static DWORD
|
||||||
PUCHAR lpBuffer,
|
ScStartService(PSCM_START_PACKET StartPacket)
|
||||||
DWORD dwBufferSize)
|
|
||||||
{
|
{
|
||||||
PACTIVE_SERVICE lpService;
|
PACTIVE_SERVICE lpService;
|
||||||
HANDLE ThreadHandle;
|
HANDLE ThreadHandle;
|
||||||
|
|
||||||
DPRINT("ScDispatcherLoop() called\n");
|
DPRINT("Size: %lu\n", StartPacket->Size);
|
||||||
|
DPRINT("Service: %S\n", &StartPacket->Arguments[0]);
|
||||||
|
|
||||||
lpService = &lpActiveServices[0];
|
lpService = ScLookupServiceByServiceName(&StartPacket->Arguments[0]);
|
||||||
|
if (lpService == NULL)
|
||||||
|
return ERROR_SERVICE_DOES_NOT_EXIST;
|
||||||
|
|
||||||
|
lpService->Arguments = HeapAlloc(GetProcessHeap(),
|
||||||
|
HEAP_ZERO_MEMORY,
|
||||||
|
StartPacket->Size);
|
||||||
|
if (lpService->Arguments == NULL)
|
||||||
|
return ERROR_OUTOFMEMORY;
|
||||||
|
|
||||||
|
memcpy(lpService->Arguments,
|
||||||
|
StartPacket->Arguments,
|
||||||
|
StartPacket->Size * sizeof(WCHAR));
|
||||||
|
|
||||||
ThreadHandle = CreateThread(NULL,
|
ThreadHandle = CreateThread(NULL,
|
||||||
0,
|
0,
|
||||||
|
@ -160,21 +217,63 @@ ScServiceDispatcher(HANDLE hPipe,
|
||||||
CREATE_SUSPENDED,
|
CREATE_SUSPENDED,
|
||||||
&lpService->ThreadId);
|
&lpService->ThreadId);
|
||||||
if (ThreadHandle == NULL)
|
if (ThreadHandle == NULL)
|
||||||
return FALSE;
|
return ERROR_SERVICE_NO_THREAD;
|
||||||
|
|
||||||
ResumeThread(ThreadHandle);
|
ResumeThread(ThreadHandle);
|
||||||
|
|
||||||
CloseHandle(ThreadHandle);
|
CloseHandle(ThreadHandle);
|
||||||
|
|
||||||
#if 0
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
ScServiceDispatcher(HANDLE hPipe,
|
||||||
|
PUCHAR lpBuffer,
|
||||||
|
DWORD dwBufferSize)
|
||||||
|
{
|
||||||
|
LPDWORD Buffer;
|
||||||
|
DWORD Count;
|
||||||
|
BOOL bResult;
|
||||||
|
|
||||||
|
DPRINT("ScDispatcherLoop() called\n");
|
||||||
|
|
||||||
|
Buffer = HeapAlloc(GetProcessHeap(),
|
||||||
|
HEAP_ZERO_MEMORY,
|
||||||
|
1024);
|
||||||
|
if (Buffer == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
/* Read command from the control pipe */
|
/* Read command from the control pipe */
|
||||||
|
bResult = ReadFile(hPipe,
|
||||||
|
Buffer,
|
||||||
|
1024,
|
||||||
|
&Count,
|
||||||
|
NULL);
|
||||||
|
if (bResult == FALSE)
|
||||||
|
{
|
||||||
|
DPRINT1("Pipe read failed\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Execute command */
|
/* Execute command */
|
||||||
|
switch (Buffer[0])
|
||||||
|
{
|
||||||
|
case SCM_START_COMMAND:
|
||||||
|
DPRINT("Start command\n");
|
||||||
|
ScStartService((PSCM_START_PACKET)Buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DPRINT1("Unknown command %lu", Buffer[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
HeapFree(GetProcessHeap(),
|
||||||
|
0,
|
||||||
|
Buffer);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -324,7 +423,8 @@ StartServiceCtrlDispatcherA(LPSERVICE_TABLE_ENTRYA lpServiceStartTable)
|
||||||
{
|
{
|
||||||
RtlCreateUnicodeStringFromAsciiz(&lpActiveServices[i].ServiceName,
|
RtlCreateUnicodeStringFromAsciiz(&lpActiveServices[i].ServiceName,
|
||||||
lpServiceStartTable[i].lpServiceName);
|
lpServiceStartTable[i].lpServiceName);
|
||||||
lpActiveServices[i].MainFunction = (LPSERVICE_MAIN_FUNCTIONW)lpServiceStartTable[i].lpServiceProc;
|
lpActiveServices[i].Main.lpFuncA = lpServiceStartTable[i].lpServiceProc;
|
||||||
|
lpActiveServices[i].bUnicode = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwError = ScConnectControlPipe(&hPipe);
|
dwError = ScConnectControlPipe(&hPipe);
|
||||||
|
@ -400,7 +500,8 @@ StartServiceCtrlDispatcherW(LPSERVICE_TABLE_ENTRYW lpServiceStartTable)
|
||||||
{
|
{
|
||||||
RtlCreateUnicodeString(&lpActiveServices[i].ServiceName,
|
RtlCreateUnicodeString(&lpActiveServices[i].ServiceName,
|
||||||
lpServiceStartTable[i].lpServiceName);
|
lpServiceStartTable[i].lpServiceName);
|
||||||
lpActiveServices[i].MainFunction = lpServiceStartTable[i].lpServiceProc;
|
lpActiveServices[i].Main.lpFuncW = lpServiceStartTable[i].lpServiceProc;
|
||||||
|
lpActiveServices[i].bUnicode = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwError = ScConnectControlPipe(&hPipe);
|
dwError = ScConnectControlPipe(&hPipe);
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
|
|
||||||
|
#include <services/services.h>
|
||||||
#include "services.h"
|
#include "services.h"
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
|
@ -521,8 +522,72 @@ ScmGetBootAndSystemDriverState(VOID)
|
||||||
|
|
||||||
|
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
ScmStartService(PSERVICE Service,
|
ScmSendStartCommand(PSERVICE Service, LPWSTR Arguments)
|
||||||
PSERVICE_GROUP Group)
|
{
|
||||||
|
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];
|
RTL_QUERY_REGISTRY_TABLE QueryTable[3];
|
||||||
PROCESS_INFORMATION ProcessInformation;
|
PROCESS_INFORMATION ProcessInformation;
|
||||||
|
@ -532,6 +597,149 @@ ScmStartService(PSERVICE Service,
|
||||||
BOOL Result;
|
BOOL Result;
|
||||||
NTSTATUS Status;
|
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->ServiceName.Buffer,
|
||||||
|
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->ServiceName.Buffer);
|
||||||
|
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");
|
DPRINT("ScmStartService() called\n");
|
||||||
|
|
||||||
Service->ControlPipeHandle = INVALID_HANDLE_VALUE;
|
Service->ControlPipeHandle = INVALID_HANDLE_VALUE;
|
||||||
|
@ -547,138 +755,10 @@ ScmStartService(PSERVICE Service,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RtlInitUnicodeString(&ImagePath, NULL);
|
/* Start user-mode service */
|
||||||
|
Status = ScmStartUserModeService(Service);
|
||||||
/* 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->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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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->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);
|
|
||||||
|
|
||||||
/* Connect control pipe */
|
|
||||||
if (ConnectNamedPipe(Service->ControlPipeHandle, NULL))
|
|
||||||
{
|
|
||||||
DWORD dwProcessId = 0;
|
|
||||||
DWORD dwRead = 0;
|
|
||||||
|
|
||||||
DPRINT("Control pipe connected!\n");
|
|
||||||
|
|
||||||
/* FIXME: 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());
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Close process and thread handle */
|
|
||||||
CloseHandle(ProcessInformation.hThread);
|
|
||||||
CloseHandle(ProcessInformation.hProcess);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Done:
|
|
||||||
DPRINT("ScmStartService() done (Status %lx)\n", Status);
|
DPRINT("ScmStartService() done (Status %lx)\n", Status);
|
||||||
|
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue