First shot at CreateServiceW. It crashes due to a bug (aka missing feature) in widl. I'm going to fix it as soon as possible.

svn path=/trunk/; revision=18383
This commit is contained in:
Eric Kohl 2005-10-09 20:24:00 +00:00
parent 0f30dcfddd
commit be1c8d7a38
6 changed files with 394 additions and 138 deletions

View file

@ -77,23 +77,23 @@ cpp_quote("#endif")
/* Function 12 */ /* Function 12 */
// DWORD ScmrCreateServiceW([in] handle_t BindingHandle, DWORD ScmrCreateServiceW([in] handle_t BindingHandle,
// [in] SC_HANDLE hSCManager, [in] SC_HANDLE hSCManager,
// [in, string, ref] LPCWSTR lpServiceName, [in, string, ref] LPCWSTR lpServiceName,
// [in, string, ref] LPCWSTR lpDisplayName, [in, string, unique] LPCWSTR lpDisplayName,
// [in] DWORD dwDesiredAccess, [in] DWORD dwDesiredAccess,
// [in] DWORD dwServiceType, [in] DWORD dwServiceType,
// [in] DWORD dwStartType, [in] DWORD dwStartType,
// [in] DWORD dwErrorControl, [in] DWORD dwErrorControl,
// [in, string, ref] LPCWSTR lpBinaryPathName, [in, string, ref] LPCWSTR lpBinaryPathName,
// [in, string, unique] LPCWSTR lpLoadOrderGroup, [in, string, unique] LPCWSTR lpLoadOrderGroup,
// [out] LPDWORD lpdwTagId, [in, out, unique] LPDWORD lpdwTagId,
// [in, size_is(dwDepwndenciesLength), unique] LPCWSTR lpDependencies, [in, size_is(dwDependenciesLength), unique] LPCWSTR lpDependencies,
// [in] DWORD dwDependenciesLength, [in] DWORD dwDependenciesLength,
// [in, string, unique] LPCWSTR lpServiceStartName, [in, string, unique] LPCWSTR lpServiceStartName,
// [in, size_is(dwPasswordLength), unique] LPCWSTR lpPassword, [in, size_is(dwPasswordLength), unique] LPCWSTR lpPassword,
// [in] DWORD dwPasswordLength, [in] DWORD dwPasswordLength,
// [out] SC_HANDLE *hService); [out] SC_HANDLE *hService);
/* Function 15 */ /* Function 15 */

View file

@ -245,25 +245,54 @@ CreateServiceA(
* *
* @unimplemented * @unimplemented
*/ */
SC_HANDLE SC_HANDLE STDCALL
STDCALL CreateServiceW(SC_HANDLE hSCManager,
CreateServiceW( LPCWSTR lpServiceName,
SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
LPCWSTR lpServiceName, DWORD dwDesiredAccess,
LPCWSTR lpDisplayName, DWORD dwServiceType,
DWORD dwDesiredAccess, DWORD dwStartType,
DWORD dwServiceType, DWORD dwErrorControl,
DWORD dwStartType, LPCWSTR lpBinaryPathName,
DWORD dwErrorControl, LPCWSTR lpLoadOrderGroup,
LPCWSTR lpBinaryPathName, LPDWORD lpdwTagId,
LPCWSTR lpLoadOrderGroup, LPCWSTR lpDependencies,
LPDWORD lpdwTagId, LPCWSTR lpServiceStartName,
LPCWSTR lpDependencies, LPCWSTR lpPassword)
LPCWSTR lpServiceStartName,
LPCWSTR lpPassword)
{ {
DPRINT1("CreateServiceW is unimplemented, but returning INVALID_HANDLE_VALUE instead of NULL\n"); SC_HANDLE hService = NULL;
return INVALID_HANDLE_VALUE; DWORD dwError;
DPRINT1("CreateServiceW() called\n");
HandleBind();
/* Call to services.exe using RPC */
dwError = ScmrCreateServiceW(BindingHandle,
(unsigned int)hSCManager,
(LPWSTR)lpServiceName,
(LPWSTR)lpDisplayName,
dwDesiredAccess,
dwServiceType,
dwStartType,
dwErrorControl,
(LPWSTR)lpBinaryPathName,
(LPWSTR)lpLoadOrderGroup,
lpdwTagId,
NULL, /* FIXME: lpDependencies */
0, /* FIXME: dwDependenciesLength */
(LPWSTR)lpServiceStartName,
NULL, /* FIXME: lpPassword */
0, /* FIXME: dwPasswordLength */
(unsigned int *)&hService);
if (dwError != ERROR_SUCCESS)
{
DPRINT1("ScmrCreateServiceW() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return INVALID_HANDLE_VALUE;
}
return hService;
} }

View file

@ -25,9 +25,14 @@
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "services.h" #include <windows.h>
#define NTOS_MODE_USER
#include <ndk/ntndk.h>
#include <services/services.h> #include <services/services.h>
#include "services.h"
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
@ -46,13 +51,13 @@ typedef struct _SERVICE_GROUP
} SERVICE_GROUP, *PSERVICE_GROUP; } SERVICE_GROUP, *PSERVICE_GROUP;
/* GLOBALS *******************************************************************/ /* GLOBALS *******************************************************************/
LIST_ENTRY GroupListHead; LIST_ENTRY GroupListHead;
LIST_ENTRY ServiceListHead; LIST_ENTRY ServiceListHead;
static RTL_RESOURCE DatabaseLock;
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
@ -66,18 +71,18 @@ ScmGetServiceEntryByName(PUNICODE_STRING ServiceName)
ServiceEntry = ServiceListHead.Flink; ServiceEntry = ServiceListHead.Flink;
while (ServiceEntry != &ServiceListHead) while (ServiceEntry != &ServiceListHead)
{
CurrentService = CONTAINING_RECORD(ServiceEntry,
SERVICE,
ServiceListEntry);
if (RtlEqualUnicodeString(&CurrentService->ServiceName, ServiceName, TRUE))
{ {
DPRINT("Found service: '%wZ'\n", &CurrentService->ServiceName); CurrentService = CONTAINING_RECORD(ServiceEntry,
return CurrentService; SERVICE,
} ServiceListEntry);
if (RtlEqualUnicodeString(&CurrentService->ServiceName, ServiceName, TRUE))
{
DPRINT("Found service: '%wZ'\n", &CurrentService->ServiceName);
return CurrentService;
}
ServiceEntry = ServiceEntry->Flink; ServiceEntry = ServiceEntry->Flink;
} }
DPRINT("Couldn't find a matching service\n"); DPRINT("Couldn't find a matching service\n");
@ -87,48 +92,50 @@ ScmGetServiceEntryByName(PUNICODE_STRING ServiceName)
static NTSTATUS STDCALL static NTSTATUS STDCALL
CreateGroupOrderListRoutine(PWSTR ValueName, CreateGroupOrderListRoutine(PWSTR ValueName,
ULONG ValueType, ULONG ValueType,
PVOID ValueData, PVOID ValueData,
ULONG ValueLength, ULONG ValueLength,
PVOID Context, PVOID Context,
PVOID EntryContext) PVOID EntryContext)
{ {
PSERVICE_GROUP Group; PSERVICE_GROUP Group;
DPRINT("IopGetGroupOrderList(%S, %x, %x, %x, %x, %x)\n", DPRINT("IopGetGroupOrderList(%S, %x, %x, %x, %x, %x)\n",
ValueName, ValueType, ValueData, ValueLength, Context, EntryContext); ValueName, ValueType, ValueData, ValueLength, Context, EntryContext);
if (ValueType == REG_BINARY && if (ValueType == REG_BINARY &&
ValueData != NULL && ValueData != NULL &&
ValueLength >= sizeof(DWORD) && ValueLength >= sizeof(DWORD) &&
ValueLength >= (*(PULONG)ValueData + 1) * sizeof(DWORD)) ValueLength >= (*(PULONG)ValueData + 1) * sizeof(DWORD))
{ {
Group = (PSERVICE_GROUP)Context; Group = (PSERVICE_GROUP)Context;
Group->TagCount = ((PULONG)ValueData)[0]; Group->TagCount = ((PULONG)ValueData)[0];
if (Group->TagCount > 0) if (Group->TagCount > 0)
{ {
if (ValueLength >= (Group->TagCount + 1) * sizeof(DWORD)) if (ValueLength >= (Group->TagCount + 1) * sizeof(DWORD))
{ {
Group->TagArray = (PULONG)HeapAlloc(GetProcessHeap(), Group->TagArray = (PULONG)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, HEAP_ZERO_MEMORY,
Group->TagCount * sizeof(DWORD)); Group->TagCount * sizeof(DWORD));
if (Group->TagArray == NULL) if (Group->TagArray == NULL)
{ {
Group->TagCount = 0; Group->TagCount = 0;
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
RtlCopyMemory(Group->TagArray,
(PULONG)ValueData + 1, RtlCopyMemory(Group->TagArray,
Group->TagCount * sizeof(DWORD)); (PULONG)ValueData + 1,
} Group->TagCount * sizeof(DWORD));
else }
{ else
Group->TagCount = 0; {
return STATUS_UNSUCCESSFUL; Group->TagCount = 0;
} return STATUS_UNSUCCESSFUL;
} }
}
} }
return STATUS_SUCCESS;
return STATUS_SUCCESS;
} }
@ -140,45 +147,44 @@ CreateGroupListRoutine(PWSTR ValueName,
PVOID Context, PVOID Context,
PVOID EntryContext) PVOID EntryContext)
{ {
PSERVICE_GROUP Group; PSERVICE_GROUP Group;
RTL_QUERY_REGISTRY_TABLE QueryTable[2]; RTL_QUERY_REGISTRY_TABLE QueryTable[2];
NTSTATUS Status; NTSTATUS Status;
if (ValueType == REG_SZ) if (ValueType == REG_SZ)
{ {
DPRINT("Data: '%S'\n", (PWCHAR)ValueData); DPRINT("Data: '%S'\n", (PWCHAR)ValueData);
Group = (PSERVICE_GROUP)HeapAlloc(GetProcessHeap(), Group = (PSERVICE_GROUP)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, HEAP_ZERO_MEMORY,
sizeof(SERVICE_GROUP)); sizeof(SERVICE_GROUP));
if (Group == NULL) if (Group == NULL)
{ {
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
if (!RtlCreateUnicodeString(&Group->GroupName, if (!RtlCreateUnicodeString(&Group->GroupName,
(PWSTR)ValueData)) (PWSTR)ValueData))
{ {
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
RtlZeroMemory(&QueryTable, sizeof(QueryTable)); RtlZeroMemory(&QueryTable, sizeof(QueryTable));
QueryTable[0].Name = (PWSTR)ValueData; QueryTable[0].Name = (PWSTR)ValueData;
QueryTable[0].QueryRoutine = CreateGroupOrderListRoutine; QueryTable[0].QueryRoutine = CreateGroupOrderListRoutine;
Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
L"GroupOrderList", L"GroupOrderList",
QueryTable, QueryTable,
(PVOID)Group, (PVOID)Group,
NULL); NULL);
DPRINT("%x %d %S\n", Status, Group->TagCount, (PWSTR)ValueData); DPRINT("%x %d %S\n", Status, Group->TagCount, (PWSTR)ValueData);
InsertTailList(&GroupListHead,
InsertTailList(&GroupListHead, &Group->GroupListEntry);
&Group->GroupListEntry);
} }
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -313,6 +319,9 @@ ScmCreateServiceDataBase(VOID)
InitializeListHead(&GroupListHead); InitializeListHead(&GroupListHead);
InitializeListHead(&ServiceListHead); InitializeListHead(&ServiceListHead);
/* Initialize the database lock */
RtlInitializeResource(&DatabaseLock);
/* Build group order list */ /* Build group order list */
RtlZeroMemory(&QueryTable, RtlZeroMemory(&QueryTable,
sizeof(QueryTable)); sizeof(QueryTable));
@ -328,6 +337,9 @@ ScmCreateServiceDataBase(VOID)
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
return Status; return Status;
RtlInitUnicodeString(&ServicesKeyName,
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
InitializeObjectAttributes(&ObjectAttributes, InitializeObjectAttributes(&ObjectAttributes,
&ServicesKeyName, &ServicesKeyName,
OBJ_CASE_INSENSITIVE, OBJ_CASE_INSENSITIVE,
@ -926,4 +938,13 @@ ScmAutoStartServices(VOID)
} }
} }
DWORD
ScmMarkServiceForDelete(PSERVICE pService)
{
DPRINT1("ScmMarkServiceForDelete() called\n");
return ERROR_SUCCESS;
}
/* EOF */ /* EOF */

View file

@ -4,6 +4,10 @@
/* INCLUDES ****************************************************************/ /* INCLUDES ****************************************************************/
#include <windows.h>
#define NTOS_MODE_USER
#include <ndk/ntndk.h>
#include "services.h" #include "services.h"
#include "svcctl_s.h" #include "svcctl_s.h"
@ -107,13 +111,13 @@ ScmStartRpcServer(VOID)
DPRINT("ScmStartRpcServer() called"); DPRINT("ScmStartRpcServer() called");
Status = RpcServerUseProtseqEp(L"ncacn_np", Status = RpcServerUseProtseqEpW(L"ncacn_np",
10, 10,
L"\\pipe\\ntsvcs", L"\\pipe\\ntsvcs",
NULL); NULL);
if (Status != RPC_S_OK) if (Status != RPC_S_OK)
{ {
DPRINT1("RpcServerUseProtseqEp() failed (Status %lx)\n", Status); DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
return; return;
} }
@ -325,6 +329,7 @@ ScmrDeleteService(handle_t BindingHandle,
{ {
PSERVICE_HANDLE hSvc; PSERVICE_HANDLE hSvc;
PSERVICE lpService; PSERVICE lpService;
DWORD dwError;
DPRINT1("ScmrDeleteService() called\n"); DPRINT1("ScmrDeleteService() called\n");
@ -343,9 +348,16 @@ ScmrDeleteService(handle_t BindingHandle,
return ERROR_INVALID_HANDLE; return ERROR_INVALID_HANDLE;
} }
/* FIXME: Mark service for delete */ /* FIXME: Acquire service database lock exclusively */
return ERROR_SUCCESS; /* Mark service for delete */
dwError = ScmMarkServiceForDelete(lpService);
/* FIXME: Release service database lock */
DPRINT1("ScmrDeleteService() done\n");
return dwError;
} }
@ -471,9 +483,49 @@ ScmrNotifyBootConfigStatus(handle_t BindingHandle,
} }
#if 0
static DWORD
CreateServiceKey(LPWSTR lpServiceName, PHKEY phKey)
{
HKEY hServicesKey = NULL;
DWORD dwDisposition;
DWORD dwError;
*phKey = NULL;
dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"System\\CurrentControlSet\\Services",
0,
KEY_WRITE,
&hServicesKey);
if (dwError != ERROR_SUCCESS)
return dwError;
dwError = RegCreateKeyExW(hServicesKey,
lpServiceName,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
phKey,
&dwDisposition);
if ((dwError == ERROR_SUCCESS) &&
(dwDisposition == REG_OPENED_EXISTING_KEY))
{
RegCloseKey(*phKey);
*phKey = NULL;
dwError = ERROR_SERVICE_EXISTS;
}
RegCloseKey(hServicesKey);
return dwError;
}
#endif
/* Function 12 */ /* Function 12 */
#if 0
unsigned long unsigned long
ScmrCreateServiceW(handle_t BindingHandle, ScmrCreateServiceW(handle_t BindingHandle,
unsigned int hSCManager, unsigned int hSCManager,
@ -485,18 +537,169 @@ ScmrCreateServiceW(handle_t BindingHandle,
unsigned long dwErrorControl, unsigned long dwErrorControl,
wchar_t *lpBinaryPathName, wchar_t *lpBinaryPathName,
wchar_t *lpLoadOrderGroup, wchar_t *lpLoadOrderGroup,
unsigned long *lpdwTagId, unsigned long *lpdwTagId, /* in, out */
wchar_t *lpDependencies, wchar_t *lpDependencies,
unsigned long dwDependenciesLength,
wchar_t *lpServiceStartName, wchar_t *lpServiceStartName,
wchar_t *lpPassword) wchar_t *lpPassword,
unsigned long dwPasswordLength,
unsigned int *hService) /* out */
{ {
DPRINT1("ScmrCreateServiceW() called\n"); PMANAGER_HANDLE hManager;
if (lpdwTagId != NULL) DWORD dwError = ERROR_SUCCESS;
*lpdwTagId = 0; #if 0
return ERROR_SUCCESS; HKEY hServiceKey = NULL;
} LPWSTR lpImagePath = NULL;
#endif #endif
DPRINT1("ScmrCreateServiceW() called\n");
DPRINT1("lpServiceName = %S\n", lpServiceName);
DPRINT1("lpDisplayName = %S\n", lpDisplayName);
DPRINT1("dwDesiredAccess = %lx\n", dwDesiredAccess);
DPRINT1("dwServiceType = %lu\n", dwServiceType);
DPRINT1("dwStartType = %lu\n", dwStartType);
DPRINT1("dwErrorControl = %lu\n", dwErrorControl);
DPRINT1("lpBinaryPathName = %S\n", lpBinaryPathName);
DPRINT1("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
hManager = (PMANAGER_HANDLE)hSCManager;
if (hManager->Handle.Tag != MANAGER_TAG)
{
DPRINT1("Invalid manager handle!\n");
return ERROR_INVALID_HANDLE;
}
/* Check access rights */
if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
SC_MANAGER_CREATE_SERVICE))
{
DPRINT1("Insufficient access rights! 0x%lx\n",
hManager->Handle.DesiredAccess);
return ERROR_ACCESS_DENIED;
}
/* FIXME: Fail if the service already exists! */
#if 0
if (dwServiceType & SERVICE_DRIVER)
{
/* FIXME: Adjust the image path */
lpImagePath = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
wcslen(lpBinaryPathName) + sizeof(WCHAR));
if (lpImagePath == NULL)
{
dwError = ERROR_NOT_ENOUGH_MEMORY;
goto done;
}
wcscpy(lpImagePath, lpBinaryPathName);
}
/* FIXME: Allocate and fill a service entry */
// if (lpdwTagId != NULL)
// *lpdwTagId = 0;
// *hService = 0;
/* Write service data to the registry */
/* Create the service key */
dwError = CreateServiceKey(lpServiceName, &hServiceKey);
if (dwError != ERROR_SUCCESS)
goto done;
if ((lpDisplayName != NULL) && (wcslen(lpDisplayName) > 0))
{
RegSetValueExW(hServiceKey,
L"DisplayName",
0,
REG_SZ,
(LPBYTE)lpDisplayName,
(wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
}
/* Set the service type */
dwError = RegSetValueExW(hServiceKey,
L"Type",
0,
REG_DWORD,
(LPBYTE)&dwServiceType,
sizeof(DWORD));
if (dwError != ERROR_SUCCESS)
goto done;
/* Set the start value */
dwError = RegSetValueExW(hServiceKey,
L"Start",
0,
REG_DWORD,
(LPBYTE)&dwStartType,
sizeof(DWORD));
if (dwError != ERROR_SUCCESS)
goto done;
/* Set the error control value */
dwError = RegSetValueExW(hServiceKey,
L"ErrorControl",
0,
REG_DWORD,
(LPBYTE)&dwErrorControl,
sizeof(DWORD));
if (dwError != ERROR_SUCCESS)
goto done;
/* Set the image path */
if (dwServiceType & SERVICE_WIN32)
{
dwError = RegSetValueExW(hServiceKey,
L"ImagePath",
0,
REG_SZ,
(LPBYTE)lpBinaryPathName,
(wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
if (dwError != ERROR_SUCCESS)
goto done;
}
else if (dwServiceType & SERVICE_DRIVER)
{
/* FIXME: Adjust the path name */
dwError = RegSetValueExW(hServiceKey,
L"ImagePath",
0,
REG_SZ,
(LPBYTE)lpImagePath,
(wcslen(lpImagePath) + 1) *sizeof(WCHAR));
if (dwError != ERROR_SUCCESS)
goto done;
}
/* Set the group name */
if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
{
dwError = RegSetValueExW(hServiceKey,
L"Group",
0,
REG_SZ,
(LPBYTE)lpLoadOrderGroup,
(wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
if (dwError != ERROR_SUCCESS)
goto done;
}
done:;
if (hServiceKey != NULL)
RegCloseKey(hServiceKey);
if (lpImagePath != NULL)
HeapFree(GetProcessHeap(), 0, lpImagePath);
#endif
DPRINT1("ScmrCreateServiceW() done (Error %lu)\n", dwError);
return dwError;
}
/* Function 15 */ /* Function 15 */
unsigned long unsigned long

View file

@ -1,5 +1,4 @@
/* $Id$ /*
*
* service control manager * service control manager
* *
* ReactOS Operating System * ReactOS Operating System
@ -29,6 +28,10 @@
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include <windows.h>
#define NTOS_MODE_USER
#include <ndk/ntndk.h>
#include "services.h" #include "services.h"
#define NDEBUG #define NDEBUG

View file

@ -1,12 +1,12 @@
/*
* services.h
*/
#include <stdio.h> #include <stdio.h>
#include <windows.h> #include <windows.h>
#define NTOS_MODE_USER #define NTOS_MODE_USER
#include <ndk/ntndk.h> #include <ndk/ntndk.h>
/*
* services.h
*/
typedef struct _SERVICE typedef struct _SERVICE
{ {
LIST_ENTRY ServiceListEntry; LIST_ENTRY ServiceListEntry;
@ -45,8 +45,8 @@ NTSTATUS ScmCreateServiceDataBase(VOID);
VOID ScmGetBootAndSystemDriverState(VOID); VOID ScmGetBootAndSystemDriverState(VOID);
VOID ScmAutoStartServices(VOID); VOID ScmAutoStartServices(VOID);
PSERVICE PSERVICE ScmGetServiceEntryByName(PUNICODE_STRING ServiceName);
ScmGetServiceEntryByName(PUNICODE_STRING ServiceName); DWORD ScmMarkServiceForDelete(PSERVICE pService);
/* rpcserver.c */ /* rpcserver.c */