- Initial hacky implementation of some SCM calls needed by coLinux.

svn path=/trunk/; revision=9110
This commit is contained in:
Filip Navara 2004-04-12 17:14:55 +00:00
parent 318d9e885e
commit 15d5f5709e
5 changed files with 986 additions and 84 deletions

View file

@ -0,0 +1,115 @@
/*
* Service Control Manager - Protocol Header
*
* Copyright (C) 2004 Filip Navara
*
* This software is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; see the file COPYING.LIB. If not, write
* to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
* MA 02139, USA.
*
* $Id: scmprot.h,v 1.1 2004/04/12 17:14:26 navaraf Exp $
*/
#ifndef _SCM_H
#define _SCM_H
/*
* NOTE:
* This protocol isn't compatible with the Windows (R) one. Since
* Windows (R) XP (or 2000?) all the communcation goes through RPC.
* We don't have RPC implemented yet, so it can't be used yet :(
*/
typedef struct
{
ULONG Length;
WCHAR Buffer[256];
} SCM_STRING;
#define INIT_SCM_STRING(x, y) x.Length = wcslen(y) * sizeof(WCHAR), RtlCopyMemory(x.Buffer, y, x.Length + sizeof(UNICODE_NULL))
/*
* Global requests
*/
#define SCM_OPENSERVICE 0x14
#define SCM_CREATESERVICE 0x20
typedef struct _SCM_OPENSERVICE_REQUEST
{
DWORD RequestCode;
SCM_STRING ServiceName;
DWORD dwDesiredAccess;
} SCM_OPENSERVICE_REQUEST, *PSCM_OPENSERVICE_REQUEST;
typedef struct _SCM_OPENSERVICE_REPLY
{
DWORD ReplyStatus;
WCHAR PipeName[128];
} SCM_OPENSERVICE_REPLY, *PSCM_OPENSERVICE_REPLY;
typedef struct _SCM_CREATESERVICE_REQUEST
{
DWORD RequestCode;
SCM_STRING ServiceName;
SCM_STRING DisplayName;
DWORD dwDesiredAccess;
DWORD dwServiceType;
DWORD dwStartType;
DWORD dwErrorControl;
SCM_STRING BinaryPathName;
SCM_STRING LoadOrderGroup;
SCM_STRING Dependencies;
SCM_STRING ServiceStartName;
SCM_STRING Password;
} SCM_CREATESERVICE_REQUEST, *PSCM_CREATESERVICE_REQUEST;
typedef struct _SCM_CREATESERVICE_REPLY
{
DWORD ReplyStatus;
WCHAR PipeName[128];
} SCM_CREATESERVICE_REPLY, *PSCM_CREATESERVICE_REPLY;
typedef union _SCM_REQUEST
{
DWORD RequestCode;
SCM_OPENSERVICE_REQUEST OpenService;
SCM_CREATESERVICE_REQUEST CreateService;
} SCM_REQUEST, *PSCM_REQUEST;
typedef union _SCM_REPLY
{
DWORD ReplyStatus;
SCM_OPENSERVICE_REPLY OpenService;
SCM_CREATESERVICE_REPLY CreateService;
} SCM_REPLY, *PSCM_REPLY;
/*
* Per service requests
*/
#define SCM_DELETESERVICE 0x10
#define SCM_STARTSERVICE 0x11
typedef union _SCM_SERVICE_REQUEST
{
DWORD RequestCode;
} SCM_SERVICE_REQUEST, *PSCM_SERVICE_REQUEST;
typedef union _SCM_SERVICE_REPLY
{
DWORD ReplyStatus;
} SCM_SERVICE_REPLY, *PSCM_SERVICE_REPLY;
#endif

View file

@ -1,4 +1,4 @@
/* $Id: scm.c,v 1.19 2003/08/07 04:03:22 royce Exp $
/* $Id: scm.c,v 1.20 2004/04/12 17:14:54 navaraf Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
@ -17,8 +17,9 @@
#include <windows.h>
#include <wchar.h>
#include <tchar.h>
#include <services/scmprot.h>
#define DBG
//#define DBG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
@ -82,14 +83,14 @@ BOOL
STDCALL
CloseServiceHandle(SC_HANDLE hSCObject)
{
HANDLE hPipe;
DPRINT("CloseServiceHandle() - called.\n");
// SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
DPRINT("CloseServiceHandle\n");
if (!CloseHandle(hPipe)) {
if (!CloseHandle(hSCObject))
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
return TRUE;
}
@ -132,8 +133,48 @@ CreateServiceA(
LPCSTR lpServiceStartName,
LPCSTR lpPassword)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return NULL;
UNICODE_STRING lpServiceNameW;
UNICODE_STRING lpDisplayNameW;
UNICODE_STRING lpBinaryPathNameW;
UNICODE_STRING lpLoadOrderGroupW;
UNICODE_STRING lpServiceStartNameW;
UNICODE_STRING lpPasswordW;
SC_HANDLE hService;
RtlCreateUnicodeStringFromAsciiz(&lpServiceNameW, (LPSTR)lpServiceName);
RtlCreateUnicodeStringFromAsciiz(&lpDisplayNameW, (LPSTR)lpDisplayName);
RtlCreateUnicodeStringFromAsciiz(&lpBinaryPathNameW, (LPSTR)lpBinaryPathName);
RtlCreateUnicodeStringFromAsciiz(&lpLoadOrderGroupW, (LPSTR)lpLoadOrderGroup);
RtlCreateUnicodeStringFromAsciiz(&lpServiceStartNameW, (LPSTR)lpServiceStartName);
RtlCreateUnicodeStringFromAsciiz(&lpPasswordW, (LPSTR)lpPassword);
if (lpDependencies != NULL)
{
DPRINT1("Unimplemented case\n");
}
hService = CreateServiceW(
hSCManager,
lpServiceNameW.Buffer,
lpDisplayNameW.Buffer,
dwDesiredAccess,
dwServiceType,
dwStartType,
dwErrorControl,
lpBinaryPathNameW.Buffer,
lpLoadOrderGroupW.Buffer,
lpdwTagId,
NULL,
lpServiceStartNameW.Buffer,
lpPasswordW.Buffer);
RtlFreeUnicodeString(&lpServiceNameW);
RtlFreeUnicodeString(&lpDisplayNameW);
RtlFreeUnicodeString(&lpBinaryPathNameW);
RtlFreeUnicodeString(&lpLoadOrderGroupW);
RtlFreeUnicodeString(&lpServiceStartNameW);
RtlFreeUnicodeString(&lpPasswordW);
return hService;
}
@ -159,8 +200,104 @@ CreateServiceW(
LPCWSTR lpServiceStartName,
LPCWSTR lpPassword)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return NULL;
SCM_CREATESERVICE_REQUEST Request;
SCM_CREATESERVICE_REPLY Reply;
BOOL fSuccess;
DWORD cbWritten, cbRead;
SC_HANDLE hService;
DPRINT("CreateServiceW\n");
if (lpServiceName == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
Request.RequestCode = SCM_CREATESERVICE;
INIT_SCM_STRING(Request.ServiceName, lpServiceName);
INIT_SCM_STRING(Request.DisplayName, lpDisplayName);
Request.dwDesiredAccess = dwDesiredAccess;
Request.dwServiceType = dwServiceType;
Request.dwStartType = dwStartType;
Request.dwErrorControl = dwErrorControl;
#if 0
INIT_SCM_STRING(Request.BinaryPathName, lpBinaryPathName);
#else
Request.BinaryPathName.Length = (wcslen(lpBinaryPathName) + 4) * sizeof(WCHAR);
swprintf(Request.BinaryPathName.Buffer, L"\\??\\%s", lpBinaryPathName);
#endif
INIT_SCM_STRING(Request.LoadOrderGroup, lpLoadOrderGroup);
INIT_SCM_STRING(Request.ServiceStartName, lpServiceStartName);
INIT_SCM_STRING(Request.Password, lpPassword);
if (lpDependencies != NULL)
{
DWORD Length;
for (Length = 0;
lpDependencies[Length++];
Length += lstrlenW(&lpDependencies[Length]) + 1)
;
Request.Dependencies.Length = Length;
}
else
{
Request.Dependencies.Length = 0;
}
RtlCopyMemory(
Request.Dependencies.Buffer,
lpDependencies,
Request.Dependencies.Length);
fSuccess = WriteFile(
hSCManager, // pipe handle
&Request, // message
sizeof(Request), // message length
&cbWritten, // bytes written
NULL); // not overlapped
if (!fSuccess || cbWritten != sizeof(Request))
{
DPRINT("CreateServiceW - Failed to write to pipe.\n");
return NULL;
}
fSuccess = ReadFile(
hSCManager, // pipe handle
&Reply, // buffer to receive reply
sizeof(Reply), // size of buffer
&cbRead, // number of bytes read
NULL); // not overlapped
if (!fSuccess && GetLastError() != ERROR_MORE_DATA)
{
DPRINT("CreateServiceW - Error\n");
return NULL;
}
if (Reply.ReplyStatus != NO_ERROR)
{
DPRINT("CreateServiceW - Error (%x)\n", Reply.ReplyStatus);
SetLastError(Reply.ReplyStatus);
return NULL;
}
hService = CreateFileW(
Reply.PipeName, // pipe name
FILE_GENERIC_READ | FILE_GENERIC_WRITE,
0, // no sharing
NULL, // no security attributes
OPEN_EXISTING, // opens existing pipe
0, // default attributes
NULL); // no template file
if (hService == INVALID_HANDLE_VALUE)
{
/* FIXME: Set last error! */
return NULL;
}
DPRINT("CreateServiceW - Success - %x\n", hService);
return hService;
}
@ -173,8 +310,51 @@ BOOL
STDCALL
DeleteService(SC_HANDLE hService)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
SCM_SERVICE_REQUEST Request;
SCM_SERVICE_REPLY Reply;
BOOL fSuccess;
DWORD cbWritten, cbRead;
DPRINT("DeleteService\n");
Request.RequestCode = SCM_DELETESERVICE;
fSuccess = WriteFile(
hService, // pipe handle
&Request, // message
sizeof(DWORD), // message length
&cbWritten, // bytes written
NULL); // not overlapped
if (!fSuccess || cbWritten != sizeof(DWORD))
{
DPRINT("Error: %x . %x\n", GetLastError(), hService);
/* FIXME: Set last error */
return FALSE;
}
fSuccess = ReadFile(
hService, // pipe handle
&Reply, // buffer to receive reply
sizeof(DWORD), // size of buffer
&cbRead, // number of bytes read
NULL); // not overlapped
if (!fSuccess && GetLastError() != ERROR_MORE_DATA)
{
CHECKPOINT;
/* FIXME: Set last error */
return FALSE;
}
if (Reply.ReplyStatus != NO_ERROR)
{
CHECKPOINT;
SetLastError(Reply.ReplyStatus);
return FALSE;
}
return TRUE;
}
@ -634,22 +814,34 @@ SC_HANDLE STDCALL OpenSCManagerW(LPCWSTR lpMachineName,
/**********************************************************************
* OpenServiceA
*
* @unimplemented
* @implemented
*/
SC_HANDLE STDCALL
OpenServiceA(SC_HANDLE hSCManager,
LPCSTR lpServiceName,
DWORD dwDesiredAccess)
SC_HANDLE
STDCALL
OpenServiceA(
SC_HANDLE hSCManager,
LPCSTR lpServiceName,
DWORD dwDesiredAccess
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return NULL;
UNICODE_STRING lpServiceNameW;
SC_HANDLE hService;
RtlCreateUnicodeStringFromAsciiz(&lpServiceNameW, (LPSTR)lpServiceName);
hService = OpenServiceW(
hSCManager,
lpServiceNameW.Buffer,
dwDesiredAccess);
RtlFreeUnicodeString(&lpServiceNameW);
return hService;
}
/**********************************************************************
* OpenServiceW
*
* @unimplemented
* @implemented
*/
SC_HANDLE
STDCALL
@ -659,8 +851,74 @@ OpenServiceW(
DWORD dwDesiredAccess
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return NULL;
SCM_OPENSERVICE_REQUEST Request;
SCM_OPENSERVICE_REPLY Reply;
BOOL fSuccess;
DWORD cbWritten, cbRead;
SC_HANDLE hService;
DPRINT("OpenServiceW\n");
if (lpServiceName == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
Request.RequestCode = SCM_OPENSERVICE;
INIT_SCM_STRING(Request.ServiceName, lpServiceName);
Request.dwDesiredAccess = dwDesiredAccess;
fSuccess = WriteFile(
hSCManager, // pipe handle
&Request, // message
sizeof(Request), // message length
&cbWritten, // bytes written
NULL); // not overlapped
if (!fSuccess || cbWritten != sizeof(Request))
{
DPRINT("OpenServiceW - Failed to write to pipe.\n");
return NULL;
}
fSuccess = ReadFile(
hSCManager, // pipe handle
&Reply, // buffer to receive reply
sizeof(Reply), // size of buffer
&cbRead, // number of bytes read
NULL); // not overlapped
if (!fSuccess && GetLastError() != ERROR_MORE_DATA)
{
DPRINT("OpenServiceW - Failed to read from pipe\n");
return NULL;
}
if (Reply.ReplyStatus != NO_ERROR)
{
DPRINT("OpenServiceW - Error (%x)\n", Reply.ReplyStatus);
SetLastError(Reply.ReplyStatus);
return NULL;
}
hService = CreateFileW(
Reply.PipeName, // pipe name
FILE_GENERIC_READ | FILE_GENERIC_WRITE,
0, // no sharing
NULL, // no security attributes
OPEN_EXISTING, // opens existing pipe
0, // default attributes
NULL); // no template file
if (hService == INVALID_HANDLE_VALUE)
{
DPRINT("OpenServiceW - Failed to connect to pipe\n");
return NULL;
}
DPRINT("OpenServiceW - Success - %x\n", hService);
return hService;
}
@ -801,8 +1059,63 @@ StartServiceA(
DWORD dwNumServiceArgs,
LPCSTR *lpServiceArgVectors)
{
#if 0
DPRINT("StartServiceA\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
#else
SCM_SERVICE_REQUEST Request;
SCM_SERVICE_REPLY Reply;
BOOL fSuccess;
DWORD cbWritten, cbRead;
DPRINT("StartServiceA\n");
if (dwNumServiceArgs != 0)
{
UNIMPLEMENTED;
}
Request.RequestCode = SCM_STARTSERVICE;
fSuccess = WriteFile(
hService, // pipe handle
&Request, // message
sizeof(DWORD), // message length
&cbWritten, // bytes written
NULL); // not overlapped
if (!fSuccess || cbWritten != sizeof(DWORD))
{
DPRINT("Error: %x . %x\n", GetLastError(), hService);
/* FIXME: Set last error */
return FALSE;
}
fSuccess = ReadFile(
hService, // pipe handle
&Reply, // buffer to receive reply
sizeof(DWORD), // size of buffer
&cbRead, // number of bytes read
NULL); // not overlapped
if (!fSuccess && GetLastError() != ERROR_MORE_DATA)
{
CHECKPOINT;
/* FIXME: Set last error */
return FALSE;
}
if (Reply.ReplyStatus != NO_ERROR)
{
CHECKPOINT;
SetLastError(Reply.ReplyStatus);
return FALSE;
}
CHECKPOINT;
return TRUE;
#endif
}
@ -820,6 +1133,7 @@ StartServiceW(
DWORD dwNumServiceArgs,
LPCWSTR *lpServiceArgVectors)
{
DPRINT("StartServiceW\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}

View file

@ -1,4 +1,4 @@
/* $Id: database.c,v 1.14 2004/04/11 16:10:05 jfilby Exp $
/* $Id: database.c,v 1.15 2004/04/12 17:14:54 navaraf Exp $
*
* service control manager
*
@ -38,39 +38,6 @@
#include <debug.h>
/* TYPES *********************************************************************/
typedef struct _SERVICE_GROUP
{
LIST_ENTRY GroupListEntry;
UNICODE_STRING GroupName;
BOOLEAN ServicesRunning;
} SERVICE_GROUP, *PSERVICE_GROUP;
typedef struct _SERVICE
{
LIST_ENTRY ServiceListEntry;
UNICODE_STRING ServiceName;
UNICODE_STRING RegistryPath;
UNICODE_STRING ServiceGroup;
ULONG Start;
ULONG Type;
ULONG ErrorControl;
ULONG Tag;
BOOLEAN ServiceRunning;
BOOLEAN ServiceVisited;
HANDLE ControlPipeHandle;
ULONG ProcessId;
ULONG ThreadId;
} SERVICE, *PSERVICE;
/* GLOBALS *******************************************************************/
LIST_ENTRY GroupListHead;
@ -116,8 +83,8 @@ CreateGroupListRoutine(PWSTR ValueName,
}
static NTSTATUS STDCALL
CreateServiceListEntry(PUNICODE_STRING ServiceName)
PSERVICE FASTCALL
ScmCreateServiceListEntry(PUNICODE_STRING ServiceName)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[6];
PSERVICE Service = NULL;
@ -130,7 +97,7 @@ CreateServiceListEntry(PUNICODE_STRING ServiceName)
sizeof(SERVICE));
if (Service == NULL)
{
return(STATUS_INSUFFICIENT_RESOURCES);
return NULL;
}
/* Copy service name */
@ -141,7 +108,7 @@ CreateServiceListEntry(PUNICODE_STRING ServiceName)
if (Service->ServiceName.Buffer == NULL)
{
HeapFree(GetProcessHeap(), 0, Service);
return(STATUS_INSUFFICIENT_RESOURCES);
return NULL;
}
RtlCopyMemory(Service->ServiceName.Buffer,
ServiceName->Buffer,
@ -156,7 +123,7 @@ CreateServiceListEntry(PUNICODE_STRING ServiceName)
{
HeapFree(GetProcessHeap(), 0, Service->ServiceName.Buffer);
HeapFree(GetProcessHeap(), 0, Service);
return(STATUS_INSUFFICIENT_RESOURCES);
return NULL;
}
wcscpy(Service->RegistryPath.Buffer,
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
@ -195,7 +162,7 @@ CreateServiceListEntry(PUNICODE_STRING ServiceName)
RtlFreeUnicodeString(&Service->RegistryPath);
RtlFreeUnicodeString(&Service->ServiceName);
HeapFree(GetProcessHeap(), 0, Service);
return(Status);
return NULL;
}
DPRINT("ServiceName: '%wZ'\n", &Service->ServiceName);
@ -208,7 +175,7 @@ CreateServiceListEntry(PUNICODE_STRING ServiceName)
InsertTailList(&ServiceListHead,
&Service->ServiceListEntry);
return(STATUS_SUCCESS);
return Service;
}
@ -293,7 +260,10 @@ ScmCreateServiceDataBase(VOID)
SubKeyName.Buffer[SubKeyName.Length / sizeof(WCHAR)] = 0;
DPRINT("KeyName: '%wZ'\n", &SubKeyName);
Status = CreateServiceListEntry(&SubKeyName);
if (ScmCreateServiceListEntry(&SubKeyName) == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
}
}
@ -446,7 +416,7 @@ ScmGetBootAndSystemDriverState(VOID)
}
static NTSTATUS
NTSTATUS FASTCALL
ScmStartService(PSERVICE Service,
PSERVICE_GROUP Group)
{
@ -625,7 +595,7 @@ Done:
}
#endif
return(STATUS_SUCCESS);
return Status; //(STATUS_SUCCESS);
}
@ -720,4 +690,27 @@ ScmAutoStartServices(VOID)
}
}
/*
* FIXME: Doesn't work!!!
*/
PSERVICE FASTCALL
ScmFindService(PUNICODE_STRING ServiceName)
{
PSERVICE CurrentService;
PLIST_ENTRY ServiceEntry;
ServiceEntry = ServiceListHead.Flink;
while (ServiceEntry != &ServiceListHead)
{
CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
if (!RtlCompareUnicodeString(ServiceName, &CurrentService->ServiceName, TRUE))
{
return CurrentService;
}
ServiceEntry = ServiceEntry->Flink;
}
return NULL;
}
/* EOF */

View file

@ -1,4 +1,4 @@
/* $Id: services.c,v 1.16 2004/04/12 15:22:53 navaraf Exp $
/* $Id: services.c,v 1.17 2004/04/12 17:14:55 navaraf Exp $
*
* service control manager
*
@ -33,8 +33,11 @@
#include <ntos.h>
#include <stdio.h>
#include <windows.h>
#undef CreateService
#undef OpenService
#include "services.h"
#include <services/scmprot.h>
#define NDEBUG
#include <debug.h>
@ -43,8 +46,7 @@
/* GLOBALS ******************************************************************/
#define PIPE_BUFSIZE 1024
#define PIPE_TIMEOUT 1000
#define PIPE_TIMEOUT 10000
/* FUNCTIONS *****************************************************************/
@ -91,17 +93,461 @@ ScmCreateStartEvent(PHANDLE StartEvent)
}
BOOL
ScmNamedPipeHandleRequest(
PVOID Request,
typedef struct _SERVICE_THREAD_DATA
{
HANDLE hPipe;
PSERVICE pService;
} SERVICE_THREAD_DATA, *PSERVICE_THREAD_DATA;
VOID FASTCALL
ScmHandleDeleteServiceRequest(
PSERVICE_THREAD_DATA pServiceThreadData,
PSCM_SERVICE_REQUEST Request,
DWORD RequestSize,
PVOID Reply,
PSCM_SERVICE_REPLY Reply,
LPDWORD ReplySize)
{
DbgPrint("SCM READ: %s\n", Request);
Reply->ReplyStatus = RtlNtStatusToDosError(
ScmStartService(pServiceThreadData->pService, NULL));
*ReplySize = sizeof(DWORD);
}
*ReplySize = 0;
return FALSE;
VOID FASTCALL
ScmHandleStartServiceRequest(
PSERVICE_THREAD_DATA pServiceThreadData,
PSCM_SERVICE_REQUEST Request,
DWORD RequestSize,
PSCM_SERVICE_REPLY Reply,
LPDWORD ReplySize)
{
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
HANDLE KeyHandle;
InitializeObjectAttributes(
&ObjectAttributes,
&pServiceThreadData->pService->RegistryPath,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwOpenKey(
&KeyHandle,
KEY_READ,
&ObjectAttributes);
if (NT_SUCCESS(Status))
{
Status = ZwDeleteKey(KeyHandle);
if (NT_SUCCESS(Status))
{
ZwClose(KeyHandle);
CHECKPOINT;
RemoveEntryList(&pServiceThreadData->pService->ServiceListEntry);
}
}
Reply->ReplyStatus = RtlNtStatusToDosError(Status);
*ReplySize = sizeof(DWORD);
}
DWORD
WINAPI
ScmNamedPipeServiceThread(LPVOID Context)
{
SCM_SERVICE_REQUEST Request;
SCM_SERVICE_REPLY Reply;
DWORD cbBytesRead;
DWORD cbWritten, cbReplyBytes;
BOOL fSuccess;
PSERVICE_THREAD_DATA pServiceThreadData = Context;
ConnectNamedPipe(pServiceThreadData->hPipe, NULL);
for (;;)
{
fSuccess = ReadFile(
pServiceThreadData->hPipe,
&Request,
sizeof(Request),
&cbBytesRead,
NULL);
if (!fSuccess || cbBytesRead == 0)
{
break;
}
switch (Request.RequestCode)
{
case SCM_DELETESERVICE:
ScmHandleDeleteServiceRequest(
pServiceThreadData,
&Request,
cbBytesRead,
&Reply,
&cbReplyBytes);
break;
case SCM_STARTSERVICE:
ScmHandleStartServiceRequest(
pServiceThreadData,
&Request,
cbBytesRead,
&Reply,
&cbReplyBytes);
break;
}
fSuccess = WriteFile(
pServiceThreadData->hPipe,
&Reply,
cbReplyBytes,
&cbWritten,
NULL);
if (!fSuccess || cbReplyBytes != cbWritten)
{
break;
}
}
FlushFileBuffers(pServiceThreadData->hPipe);
DisconnectNamedPipe(pServiceThreadData->hPipe);
CloseHandle(pServiceThreadData->hPipe);
return NO_ERROR;
}
VOID FASTCALL
ScmCreateServiceThread(
HANDLE hSCMPipe,
PSCM_OPENSERVICE_REPLY Reply,
LPDWORD ReplySize,
PSERVICE Service)
{
HANDLE hPipe, hThread;
DWORD dwThreadId;
PSERVICE_THREAD_DATA ServiceThreadData;
ServiceThreadData = HeapAlloc(
GetProcessHeap(),
0,
sizeof(SERVICE_THREAD_DATA));
if (ServiceThreadData == NULL)
{
Reply->ReplyStatus = ERROR_NO_SYSTEM_RESOURCES;
CHECKPOINT;
return;
}
swprintf(Reply->PipeName, L"\\\\.\\pipe\\SCM.%08X.%08X", hSCMPipe, Service);
hPipe = CreateNamedPipeW(
Reply->PipeName,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
sizeof(SCM_SERVICE_REQUEST),
sizeof(SCM_SERVICE_REPLY),
PIPE_TIMEOUT,
NULL);
if (hPipe == INVALID_HANDLE_VALUE)
{
Reply->ReplyStatus = ERROR_NO_SYSTEM_RESOURCES;
CHECKPOINT;
return;
}
ServiceThreadData->hPipe = hPipe;
ServiceThreadData->pService = Service;
hThread = CreateThread(
NULL,
0,
ScmNamedPipeServiceThread,
ServiceThreadData,
0,
&dwThreadId);
if (!hThread)
{
Reply->ReplyStatus = ERROR_NO_SYSTEM_RESOURCES;
CHECKPOINT;
CloseHandle(hPipe);
return;
}
Reply->ReplyStatus = NO_ERROR;
*ReplySize = sizeof(SCM_OPENSERVICE_REPLY);
}
VOID FASTCALL
ScmHandleOpenServiceRequest(
HANDLE hPipe,
PSCM_REQUEST Request,
DWORD RequestSize,
PSCM_REPLY Reply,
LPDWORD ReplySize)
{
PSERVICE Service;
UNICODE_STRING ServiceName;
DPRINT("OpenService\n");
if (RequestSize != sizeof(SCM_OPENSERVICE_REQUEST))
{
Reply->ReplyStatus = ERROR_INVALID_PARAMETER;
return;
}
ServiceName.Length = Request->OpenService.ServiceName.Length;
ServiceName.Buffer = Request->OpenService.ServiceName.Buffer;
Service = ScmFindService(&ServiceName);
if (Service == NULL)
{
DPRINT("OpenService - Service not found\n");
Reply->ReplyStatus = ERROR_SERVICE_DOES_NOT_EXIST;
return;
}
DPRINT("OpenService - Service found\n");
ScmCreateServiceThread(
hPipe,
&Reply->OpenService,
ReplySize,
Service);
}
VOID FASTCALL
ScmHandleCreateServiceRequest(
HANDLE hPipe,
PSCM_REQUEST Request,
DWORD RequestSize,
PSCM_REPLY Reply,
LPDWORD ReplySize)
{
PSERVICE Service;
NTSTATUS Status;
UNICODE_STRING ServiceName;
DPRINT("CreateService - %S\n", Request->CreateService.ServiceName.Buffer);
if (RequestSize != sizeof(SCM_CREATESERVICE_REQUEST))
{
Reply->ReplyStatus = ERROR_INVALID_PARAMETER;
return;
}
Status = RtlCheckRegistryKey(
RTL_REGISTRY_SERVICES,
Request->CreateService.ServiceName.Buffer);
if (NT_SUCCESS(Status))
{
DPRINT("CreateService - Already exists\n");
Reply->ReplyStatus = ERROR_SERVICE_EXISTS;
return;
}
Status = RtlCreateRegistryKey(
RTL_REGISTRY_SERVICES,
Request->CreateService.ServiceName.Buffer);
if (!NT_SUCCESS(Status))
{
DPRINT("CreateService - Can't create key (%x)\n", Status);
Reply->ReplyStatus = Status;
return;
}
Status = RtlWriteRegistryValue(
RTL_REGISTRY_SERVICES,
Request->CreateService.ServiceName.Buffer,
L"Type",
REG_DWORD,
&Request->CreateService.dwServiceType,
sizeof(DWORD));
if (!NT_SUCCESS(Status))
{
DPRINT("CreateService - Error writing value\n");
Reply->ReplyStatus = RtlNtStatusToDosError(Status);
return;
}
Status = RtlWriteRegistryValue(
RTL_REGISTRY_SERVICES,
Request->CreateService.ServiceName.Buffer,
L"Start",
REG_DWORD,
&Request->CreateService.dwStartType,
sizeof(DWORD));
if (!NT_SUCCESS(Status))
{
Reply->ReplyStatus = RtlNtStatusToDosError(Status);
return;
}
Status = RtlWriteRegistryValue(
RTL_REGISTRY_SERVICES,
Request->CreateService.ServiceName.Buffer,
L"ErrorControl",
REG_DWORD,
&Request->CreateService.dwErrorControl,
sizeof(DWORD));
if (!NT_SUCCESS(Status))
{
Reply->ReplyStatus = RtlNtStatusToDosError(Status);
return;
}
if (Request->CreateService.BinaryPathName.Length)
{
Status = RtlWriteRegistryValue(
RTL_REGISTRY_SERVICES,
Request->CreateService.ServiceName.Buffer,
L"ImagePath",
REG_SZ,
Request->CreateService.BinaryPathName.Buffer,
Request->CreateService.BinaryPathName.Length + sizeof(UNICODE_NULL));
if (!NT_SUCCESS(Status))
{
DPRINT("CreateService - Error writing value\n");
Reply->ReplyStatus = RtlNtStatusToDosError(Status);
return;
}
}
if (Request->CreateService.LoadOrderGroup.Length)
{
Status = RtlWriteRegistryValue(
RTL_REGISTRY_SERVICES,
Request->CreateService.ServiceName.Buffer,
L"Group",
REG_SZ,
Request->CreateService.LoadOrderGroup.Buffer,
Request->CreateService.LoadOrderGroup.Length + sizeof(UNICODE_NULL));
if (!NT_SUCCESS(Status))
{
Reply->ReplyStatus = RtlNtStatusToDosError(Status);
return;
}
}
if (Request->CreateService.Dependencies.Length)
{
Status = RtlWriteRegistryValue(
RTL_REGISTRY_SERVICES,
Request->CreateService.ServiceName.Buffer,
L"Dependencies",
REG_SZ,
Request->CreateService.Dependencies.Buffer,
Request->CreateService.Dependencies.Length + sizeof(UNICODE_NULL));
if (!NT_SUCCESS(Status))
{
Reply->ReplyStatus = RtlNtStatusToDosError(Status);
return;
}
}
if (Request->CreateService.DisplayName.Length)
{
Status = RtlWriteRegistryValue(
RTL_REGISTRY_SERVICES,
Request->CreateService.ServiceName.Buffer,
L"DisplayName",
REG_SZ,
Request->CreateService.DisplayName.Buffer,
Request->CreateService.DisplayName.Length + sizeof(UNICODE_NULL));
if (!NT_SUCCESS(Status))
{
Reply->ReplyStatus = RtlNtStatusToDosError(Status);
return;
}
}
if (Request->CreateService.ServiceStartName.Length ||
Request->CreateService.Password.Length)
{
DPRINT1("Unimplemented case\n");
}
ServiceName.Length = Request->OpenService.ServiceName.Length;
ServiceName.Buffer = Request->OpenService.ServiceName.Buffer;
Service = ScmCreateServiceListEntry(&ServiceName);
if (Service == NULL)
{
DPRINT("CreateService - Error creating service list entry\n");
Reply->ReplyStatus = ERROR_NOT_ENOUGH_MEMORY;
return;
}
DPRINT("CreateService - Success\n");
ScmCreateServiceThread(
hPipe,
&Reply->OpenService,
ReplySize,
Service);
}
BOOL
ScmNamedPipeHandleRequest(
HANDLE hPipe,
PSCM_REQUEST Request,
DWORD RequestSize,
PSCM_REPLY Reply,
LPDWORD ReplySize)
{
*ReplySize = sizeof(DWORD);
if (RequestSize < sizeof(DWORD))
{
Reply->ReplyStatus = ERROR_INVALID_PARAMETER;
return TRUE;
}
DPRINT("RequestCode: %x\n", Request->RequestCode);
switch (Request->RequestCode)
{
case SCM_OPENSERVICE:
ScmHandleOpenServiceRequest(
hPipe,
Request,
RequestSize,
Reply,
ReplySize);
break;
case SCM_CREATESERVICE:
ScmHandleCreateServiceRequest(
hPipe,
Request,
RequestSize,
Reply,
ReplySize);
break;
default:
Reply->ReplyStatus = ERROR_INVALID_PARAMETER;
}
return TRUE;
}
@ -109,8 +555,8 @@ DWORD
WINAPI
ScmNamedPipeThread(LPVOID Context)
{
CHAR chRequest[PIPE_BUFSIZE];
CHAR chReply[PIPE_BUFSIZE];
SCM_REQUEST Request;
SCM_REPLY Reply;
DWORD cbReplyBytes;
DWORD cbBytesRead;
DWORD cbWritten;
@ -123,16 +569,16 @@ ScmNamedPipeThread(LPVOID Context)
for (;;) {
fSuccess = ReadFile(hPipe,
&chRequest,
PIPE_BUFSIZE,
&Request,
sizeof(Request),
&cbBytesRead,
NULL);
if (!fSuccess || cbBytesRead == 0) {
break;
}
if (ScmNamedPipeHandleRequest(&chRequest, cbBytesRead, &chReply, &cbReplyBytes)) {
if (ScmNamedPipeHandleRequest(hPipe, &Request, cbBytesRead, &Reply, &cbReplyBytes)) {
fSuccess = WriteFile(hPipe,
&chReply,
&Reply,
cbReplyBytes,
&cbWritten,
NULL);
@ -162,8 +608,8 @@ BOOL ScmCreateNamedPipe(VOID)
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
PIPE_BUFSIZE,
PIPE_BUFSIZE,
sizeof(SCM_REQUEST),
sizeof(SCM_REPLY),
PIPE_TIMEOUT,
NULL);
if (hPipe == INVALID_HANDLE_VALUE) {

View file

@ -2,6 +2,34 @@
* services.h
*/
typedef struct _SERVICE_GROUP
{
LIST_ENTRY GroupListEntry;
UNICODE_STRING GroupName;
BOOLEAN ServicesRunning;
} SERVICE_GROUP, *PSERVICE_GROUP;
typedef struct _SERVICE
{
LIST_ENTRY ServiceListEntry;
UNICODE_STRING ServiceName;
UNICODE_STRING RegistryPath;
UNICODE_STRING ServiceGroup;
ULONG Start;
ULONG Type;
ULONG ErrorControl;
ULONG Tag;
BOOLEAN ServiceRunning;
BOOLEAN ServiceVisited;
HANDLE ControlPipeHandle;
ULONG ProcessId;
ULONG ThreadId;
} SERVICE, *PSERVICE;
/* services.c */
@ -14,6 +42,12 @@ NTSTATUS ScmCreateServiceDataBase(VOID);
VOID ScmGetBootAndSystemDriverState(VOID);
VOID ScmAutoStartServices(VOID);
PSERVICE FASTCALL
ScmCreateServiceListEntry(PUNICODE_STRING ServiceName);
PSERVICE FASTCALL
ScmFindService(PUNICODE_STRING ServiceName);
NTSTATUS FASTCALL
ScmStartService(PSERVICE Service, PSERVICE_GROUP Group);
/* EOF */