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 */
// DWORD ScmrCreateServiceW([in] handle_t BindingHandle,
// [in] SC_HANDLE hSCManager,
// [in, string, ref] LPCWSTR lpServiceName,
// [in, string, ref] LPCWSTR lpDisplayName,
// [in] DWORD dwDesiredAccess,
// [in] DWORD dwServiceType,
// [in] DWORD dwStartType,
// [in] DWORD dwErrorControl,
// [in, string, ref] LPCWSTR lpBinaryPathName,
// [in, string, unique] LPCWSTR lpLoadOrderGroup,
// [out] LPDWORD lpdwTagId,
// [in, size_is(dwDepwndenciesLength), unique] LPCWSTR lpDependencies,
// [in] DWORD dwDependenciesLength,
// [in, string, unique] LPCWSTR lpServiceStartName,
// [in, size_is(dwPasswordLength), unique] LPCWSTR lpPassword,
// [in] DWORD dwPasswordLength,
// [out] SC_HANDLE *hService);
DWORD ScmrCreateServiceW([in] handle_t BindingHandle,
[in] SC_HANDLE hSCManager,
[in, string, ref] LPCWSTR lpServiceName,
[in, string, unique] LPCWSTR lpDisplayName,
[in] DWORD dwDesiredAccess,
[in] DWORD dwServiceType,
[in] DWORD dwStartType,
[in] DWORD dwErrorControl,
[in, string, ref] LPCWSTR lpBinaryPathName,
[in, string, unique] LPCWSTR lpLoadOrderGroup,
[in, out, unique] LPDWORD lpdwTagId,
[in, size_is(dwDependenciesLength), unique] LPCWSTR lpDependencies,
[in] DWORD dwDependenciesLength,
[in, string, unique] LPCWSTR lpServiceStartName,
[in, size_is(dwPasswordLength), unique] LPCWSTR lpPassword,
[in] DWORD dwPasswordLength,
[out] SC_HANDLE *hService);
/* Function 15 */

View file

@ -245,25 +245,54 @@ CreateServiceA(
*
* @unimplemented
*/
SC_HANDLE
STDCALL
CreateServiceW(
SC_HANDLE hSCManager,
LPCWSTR lpServiceName,
LPCWSTR lpDisplayName,
DWORD dwDesiredAccess,
DWORD dwServiceType,
DWORD dwStartType,
DWORD dwErrorControl,
LPCWSTR lpBinaryPathName,
LPCWSTR lpLoadOrderGroup,
LPDWORD lpdwTagId,
LPCWSTR lpDependencies,
LPCWSTR lpServiceStartName,
LPCWSTR lpPassword)
SC_HANDLE STDCALL
CreateServiceW(SC_HANDLE hSCManager,
LPCWSTR lpServiceName,
LPCWSTR lpDisplayName,
DWORD dwDesiredAccess,
DWORD dwServiceType,
DWORD dwStartType,
DWORD dwErrorControl,
LPCWSTR lpBinaryPathName,
LPCWSTR lpLoadOrderGroup,
LPDWORD lpdwTagId,
LPCWSTR lpDependencies,
LPCWSTR lpServiceStartName,
LPCWSTR lpPassword)
{
DPRINT1("CreateServiceW is unimplemented, but returning INVALID_HANDLE_VALUE instead of NULL\n");
return INVALID_HANDLE_VALUE;
SC_HANDLE hService = NULL;
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 *****************************************************************/
#include "services.h"
#include <windows.h>
#define NTOS_MODE_USER
#include <ndk/ntndk.h>
#include <services/services.h>
#include "services.h"
#define NDEBUG
#include <debug.h>
@ -46,13 +51,13 @@ typedef struct _SERVICE_GROUP
} SERVICE_GROUP, *PSERVICE_GROUP;
/* GLOBALS *******************************************************************/
LIST_ENTRY GroupListHead;
LIST_ENTRY ServiceListHead;
static RTL_RESOURCE DatabaseLock;
/* FUNCTIONS *****************************************************************/
@ -66,18 +71,18 @@ ScmGetServiceEntryByName(PUNICODE_STRING ServiceName)
ServiceEntry = ServiceListHead.Flink;
while (ServiceEntry != &ServiceListHead)
{
CurrentService = CONTAINING_RECORD(ServiceEntry,
SERVICE,
ServiceListEntry);
if (RtlEqualUnicodeString(&CurrentService->ServiceName, ServiceName, TRUE))
{
DPRINT("Found service: '%wZ'\n", &CurrentService->ServiceName);
return CurrentService;
}
CurrentService = CONTAINING_RECORD(ServiceEntry,
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");
@ -87,48 +92,50 @@ ScmGetServiceEntryByName(PUNICODE_STRING ServiceName)
static NTSTATUS STDCALL
CreateGroupOrderListRoutine(PWSTR ValueName,
ULONG ValueType,
PVOID ValueData,
ULONG ValueLength,
PVOID Context,
PVOID EntryContext)
ULONG ValueType,
PVOID ValueData,
ULONG ValueLength,
PVOID Context,
PVOID EntryContext)
{
PSERVICE_GROUP Group;
PSERVICE_GROUP Group;
DPRINT("IopGetGroupOrderList(%S, %x, %x, %x, %x, %x)\n",
ValueName, ValueType, ValueData, ValueLength, Context, EntryContext);
DPRINT("IopGetGroupOrderList(%S, %x, %x, %x, %x, %x)\n",
ValueName, ValueType, ValueData, ValueLength, Context, EntryContext);
if (ValueType == REG_BINARY &&
ValueData != NULL &&
ValueLength >= sizeof(DWORD) &&
ValueLength >= (*(PULONG)ValueData + 1) * sizeof(DWORD))
if (ValueType == REG_BINARY &&
ValueData != NULL &&
ValueLength >= sizeof(DWORD) &&
ValueLength >= (*(PULONG)ValueData + 1) * sizeof(DWORD))
{
Group = (PSERVICE_GROUP)Context;
Group->TagCount = ((PULONG)ValueData)[0];
if (Group->TagCount > 0)
Group = (PSERVICE_GROUP)Context;
Group->TagCount = ((PULONG)ValueData)[0];
if (Group->TagCount > 0)
{
if (ValueLength >= (Group->TagCount + 1) * sizeof(DWORD))
if (ValueLength >= (Group->TagCount + 1) * sizeof(DWORD))
{
Group->TagArray = (PULONG)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
Group->TagCount * sizeof(DWORD));
if (Group->TagArray == NULL)
{
Group->TagCount = 0;
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(Group->TagArray,
(PULONG)ValueData + 1,
Group->TagCount * sizeof(DWORD));
}
else
{
Group->TagCount = 0;
return STATUS_UNSUCCESSFUL;
}
}
Group->TagArray = (PULONG)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
Group->TagCount * sizeof(DWORD));
if (Group->TagArray == NULL)
{
Group->TagCount = 0;
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(Group->TagArray,
(PULONG)ValueData + 1,
Group->TagCount * sizeof(DWORD));
}
else
{
Group->TagCount = 0;
return STATUS_UNSUCCESSFUL;
}
}
}
return STATUS_SUCCESS;
return STATUS_SUCCESS;
}
@ -140,45 +147,44 @@ CreateGroupListRoutine(PWSTR ValueName,
PVOID Context,
PVOID EntryContext)
{
PSERVICE_GROUP Group;
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
NTSTATUS Status;
PSERVICE_GROUP Group;
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
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(),
HEAP_ZERO_MEMORY,
sizeof(SERVICE_GROUP));
if (Group == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Group = (PSERVICE_GROUP)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(SERVICE_GROUP));
if (Group == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
if (!RtlCreateUnicodeString(&Group->GroupName,
(PWSTR)ValueData))
{
return STATUS_INSUFFICIENT_RESOURCES;
}
if (!RtlCreateUnicodeString(&Group->GroupName,
(PWSTR)ValueData))
{
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(&QueryTable, sizeof(QueryTable));
QueryTable[0].Name = (PWSTR)ValueData;
QueryTable[0].QueryRoutine = CreateGroupOrderListRoutine;
RtlZeroMemory(&QueryTable, sizeof(QueryTable));
QueryTable[0].Name = (PWSTR)ValueData;
QueryTable[0].QueryRoutine = CreateGroupOrderListRoutine;
Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
L"GroupOrderList",
QueryTable,
(PVOID)Group,
NULL);
DPRINT("%x %d %S\n", Status, Group->TagCount, (PWSTR)ValueData);
Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
L"GroupOrderList",
QueryTable,
(PVOID)Group,
NULL);
DPRINT("%x %d %S\n", Status, Group->TagCount, (PWSTR)ValueData);
InsertTailList(&GroupListHead,
&Group->GroupListEntry);
InsertTailList(&GroupListHead,
&Group->GroupListEntry);
}
return STATUS_SUCCESS;
return STATUS_SUCCESS;
}
@ -296,7 +302,7 @@ ScmCreateServiceDataBase(VOID)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING ServicesKeyName =
UNICODE_STRING ServicesKeyName =
RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
UNICODE_STRING SubKeyName;
HKEY ServicesKey;
@ -313,6 +319,9 @@ ScmCreateServiceDataBase(VOID)
InitializeListHead(&GroupListHead);
InitializeListHead(&ServiceListHead);
/* Initialize the database lock */
RtlInitializeResource(&DatabaseLock);
/* Build group order list */
RtlZeroMemory(&QueryTable,
sizeof(QueryTable));
@ -328,6 +337,9 @@ ScmCreateServiceDataBase(VOID)
if (!NT_SUCCESS(Status))
return Status;
RtlInitUnicodeString(&ServicesKeyName,
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
InitializeObjectAttributes(&ObjectAttributes,
&ServicesKeyName,
OBJ_CASE_INSENSITIVE,
@ -926,4 +938,13 @@ ScmAutoStartServices(VOID)
}
}
DWORD
ScmMarkServiceForDelete(PSERVICE pService)
{
DPRINT1("ScmMarkServiceForDelete() called\n");
return ERROR_SUCCESS;
}
/* EOF */

View file

@ -4,6 +4,10 @@
/* INCLUDES ****************************************************************/
#include <windows.h>
#define NTOS_MODE_USER
#include <ndk/ntndk.h>
#include "services.h"
#include "svcctl_s.h"
@ -107,13 +111,13 @@ ScmStartRpcServer(VOID)
DPRINT("ScmStartRpcServer() called");
Status = RpcServerUseProtseqEp(L"ncacn_np",
10,
L"\\pipe\\ntsvcs",
NULL);
Status = RpcServerUseProtseqEpW(L"ncacn_np",
10,
L"\\pipe\\ntsvcs",
NULL);
if (Status != RPC_S_OK)
{
DPRINT1("RpcServerUseProtseqEp() failed (Status %lx)\n", Status);
DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
return;
}
@ -142,7 +146,7 @@ ScmCreateManagerHandle(LPWSTR lpDatabaseName,
SC_HANDLE *Handle)
{
PMANAGER_HANDLE Ptr;
if (lpDatabaseName == NULL)
lpDatabaseName = SERVICES_ACTIVE_DATABASEW;
@ -325,6 +329,7 @@ ScmrDeleteService(handle_t BindingHandle,
{
PSERVICE_HANDLE hSvc;
PSERVICE lpService;
DWORD dwError;
DPRINT1("ScmrDeleteService() called\n");
@ -343,9 +348,16 @@ ScmrDeleteService(handle_t BindingHandle,
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 */
#if 0
unsigned long
ScmrCreateServiceW(handle_t BindingHandle,
unsigned int hSCManager,
@ -485,18 +537,169 @@ ScmrCreateServiceW(handle_t BindingHandle,
unsigned long dwErrorControl,
wchar_t *lpBinaryPathName,
wchar_t *lpLoadOrderGroup,
unsigned long *lpdwTagId,
unsigned long *lpdwTagId, /* in, out */
wchar_t *lpDependencies,
unsigned long dwDependenciesLength,
wchar_t *lpServiceStartName,
wchar_t *lpPassword)
wchar_t *lpPassword,
unsigned long dwPasswordLength,
unsigned int *hService) /* out */
{
DPRINT1("ScmrCreateServiceW() called\n");
if (lpdwTagId != NULL)
*lpdwTagId = 0;
return ERROR_SUCCESS;
}
PMANAGER_HANDLE hManager;
DWORD dwError = ERROR_SUCCESS;
#if 0
HKEY hServiceKey = NULL;
LPWSTR lpImagePath = NULL;
#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 */
unsigned long

View file

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

View file

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