Use the service contol pipe to send a start command in order to start a
service thread.
Added: trunk/reactos/include/services/
Added: trunk/reactos/include/services/services.h
Modified: trunk/reactos/lib/advapi32/service/sctrl.c
Modified: trunk/reactos/subsys/system/services/database.c
_____
Added: trunk/reactos/include/services/services.h
--- trunk/reactos/include/services/services.h 2005-01-28 12:12:42 UTC
(rev 13349)
+++ trunk/reactos/include/services/services.h 2005-01-28 13:28:56 UTC
(rev 13350)
@@ -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 */
_____
Modified: trunk/reactos/lib/advapi32/service/sctrl.c
--- trunk/reactos/lib/advapi32/service/sctrl.c 2005-01-28 12:12:42 UTC
(rev 13349)
+++ trunk/reactos/lib/advapi32/service/sctrl.c 2005-01-28 13:28:56 UTC
(rev 13350)
@@ -13,6 +13,8 @@
/* INCLUDES
******************************************************************/
#include "advapi32.h"
+#include <services/services.h>
+
#define NDEBUG
#include <debug.h>
@@ -23,9 +25,15 @@
{
DWORD ThreadId;
UNICODE_STRING ServiceName;
- LPSERVICE_MAIN_FUNCTIONW MainFunction;
+ union
+ {
+ LPSERVICE_MAIN_FUNCTIONA lpFuncA;
+ LPSERVICE_MAIN_FUNCTIONW lpFuncW;
+ } Main;
LPHANDLER_FUNCTION HandlerFunction;
SERVICE_STATUS ServiceStatus;
+ BOOL bUnicode;
+ LPWSTR Arguments;
} ACTIVE_SERVICE, *PACTIVE_SERVICE;
@@ -33,7 +41,6 @@
static DWORD dwActiveServiceCount = 0;
static PACTIVE_SERVICE lpActiveServices = NULL;
-/* static PHANDLE ActiveServicesThreadHandles; */ /* uncomment when in
use */
/* FUNCTIONS
*****************************************************************/
@@ -80,16 +87,54 @@
ScServiceMainStub(LPVOID Context)
{
PACTIVE_SERVICE lpService;
+ DWORD dwArgCount = 0;
+ DWORD dwLength = 0;
lpService = (PACTIVE_SERVICE)Context;
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;
}
@@ -141,18 +186,30 @@
}
-static BOOL
-ScServiceDispatcher(HANDLE hPipe,
- PUCHAR lpBuffer,
- DWORD dwBufferSize)
+
+static DWORD
+ScStartService(PSCM_START_PACKET StartPacket)
{
PACTIVE_SERVICE lpService;
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,
0,
ScServiceMainStub,
@@ -160,22 +217,64 @@
CREATE_SUSPENDED,
&lpService->ThreadId);
if (ThreadHandle == NULL)
- return FALSE;
+ return ERROR_SERVICE_NO_THREAD;
ResumeThread(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)
{
/* 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 */
+ 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;
}
@@ -324,7 +423,8 @@
{
RtlCreateUnicodeStringFromAsciiz(&lpActiveServices[i].ServiceName,
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);
@@ -400,7 +500,8 @@
{
RtlCreateUnicodeString(&lpActiveServices[i].ServiceName,
lpServiceStartTable[i].lpServiceName);
- lpActiveServices[i].MainFunction =
lpServiceStartTable[i].lpServiceProc;
+ lpActiveServices[i].Main.lpFuncW =
lpServiceStartTable[i].lpServiceProc;
+ lpActiveServices[i].bUnicode = TRUE;
}
dwError = ScConnectControlPipe(&hPipe);
_____
Modified: trunk/reactos/subsys/system/services/database.c
--- trunk/reactos/subsys/system/services/database.c 2005-01-28
12:12:42 UTC (rev 13349)
+++ trunk/reactos/subsys/system/services/database.c 2005-01-28
13:28:56 UTC (rev 13350)
@@ -32,6 +32,7 @@
#include <windows.h>
#include <tchar.h>
+#include <services/services.h>
#include "services.h"
#define NDEBUG
@@ -521,9 +522,73 @@
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;
@@ -532,153 +597,168 @@
BOOL Result;
NTSTATUS Status;
- DPRINT("ScmStartService() called\n");
+ RtlInitUnicodeString(&ImagePath, NULL);
- Service->ControlPipeHandle = INVALID_HANDLE_VALUE;
- DPRINT("Service->Type: %u\n", Service->Type);
+ /* 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;
- QueryTable[0].Name = L"Type";
- QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT |
RTL_QUERY_REGISTRY_REQUIRED;
- QueryTable[0].EntryContext = &Type;
+ Result = CreateProcessW(ImagePath.Buffer,
+ NULL,
+ NULL,
+ NULL,
+ FALSE,
+ DETACHED_PROCESS | CREATE_SUSPENDED,
+ NULL,
+ NULL,
+ &StartupInfo,
+ &ProcessInformation);
+ RtlFreeUnicodeString(&ImagePath);
- QueryTable[1].Name = L"ImagePath";
- QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT |
RTL_QUERY_REGISTRY_REQUIRED;
- QueryTable[1].EntryContext = &ImagePath;
+ if (!Result)
+ {
+ /* Close control pipe */
+ CloseHandle(Service->ControlPipeHandle);
+ Service->ControlPipeHandle = INVALID_HANDLE_VALUE;
- 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);
+ DPRINT1("Starting '%S' failed!\n",
Service->ServiceName.Buffer);
+ return STATUS_UNSUCCESSFUL;
+ }
- /* 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;
- }
+ DPRINT("Process Id: %lu Handle %lx\n",
+ ProcessInformation.dwProcessId,
+ ProcessInformation.hProcess);
+ DPRINT("Thread Id: %lu Handle %lx\n",
+ ProcessInformation.dwThreadId,
+ ProcessInformation.hThread);
- StartupInfo.cb = sizeof(StartupInfo);
- StartupInfo.lpReserved = NULL;
- StartupInfo.lpDesktop = NULL;
- StartupInfo.lpTitle = NULL;
- StartupInfo.dwFlags = 0;
- StartupInfo.cbReserved2 = 0;
- StartupInfo.lpReserved2 = 0;
+ /* Get process and thread ids */
+ Service->ProcessId = ProcessInformation.dwProcessId;
+ Service->ThreadId = ProcessInformation.dwThreadId;
- Result = CreateProcessW(ImagePath.Buffer,
- NULL,
- NULL,
- NULL,
- FALSE,
- DETACHED_PROCESS | CREATE_SUSPENDED,
- NULL,
- NULL,
- &StartupInfo,
- &ProcessInformation);
- RtlFreeUnicodeString(&ImagePath);
+ /* Resume Thread */
+ ResumeThread(ProcessInformation.hThread);
- if (!Result)
- {
- /* Close control pipe */
- CloseHandle(Service->ControlPipeHandle);
- Service->ControlPipeHandle = INVALID_HANDLE_VALUE;
+ /* Connect control pipe */
+ if (ConnectNamedPipe(Service->ControlPipeHandle, NULL))
+ {
+ DWORD dwProcessId = 0;
+ DWORD dwRead = 0;
- 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);
+ DPRINT("Control pipe connected!\n");
- /* Get process and thread ids */
- Service->ProcessId = ProcessInformation.dwProcessId;
- Service->ThreadId = ProcessInformation.dwThreadId;
+ /* 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);
- /* Resume Thread */
- ResumeThread(ProcessInformation.hThread);
+ /* FIXME: Send start command */
- /* Connect control pipe */
- if (ConnectNamedPipe(Service->ControlPipeHandle, NULL))
- {
- DWORD dwProcessId = 0;
- DWORD dwRead = 0;
+ Status = STATUS_SUCCESS;
+ }
+ }
+ else
+ {
+ DPRINT("Connecting control pipe failed!\n");
- DPRINT("Control pipe connected!\n");
+ /* Close control pipe */
+ CloseHandle(Service->ControlPipeHandle);
+ Service->ControlPipeHandle = INVALID_HANDLE_VALUE;
+ Service->ProcessId = 0;
+ Service->ThreadId = 0;
+ Status = STATUS_UNSUCCESSFUL;
+ }
- /* 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);
+ ScmSendStartCommand(Service, NULL);
- /* FIXME: Send start command */
+ /* Close process and thread handle */
+ CloseHandle(ProcessInformation.hThread);
+ CloseHandle(ProcessInformation.hProcess);
- Status = STATUS_SUCCESS;
- }
- }
- else
- {
- DPRINT("Connecting control pipe failed!\n");
+ return Status;
+}
- /* 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);
- }
- }
+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);
+ }
-Done:
DPRINT("ScmStartService() done (Status %lx)\n", Status);
if (NT_SUCCESS(Status))