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.
Modified: trunk/reactos/include/idl/svcctl.idl
Modified: trunk/reactos/lib/advapi32/service/scm.c
Modified: trunk/reactos/subsys/system/services/database.c
Modified: trunk/reactos/subsys/system/services/rpcserver.c
Modified: trunk/reactos/subsys/system/services/services.c
Modified: trunk/reactos/subsys/system/services/services.h

Modified: trunk/reactos/include/idl/svcctl.idl
--- trunk/reactos/include/idl/svcctl.idl	2005-10-09 19:08:18 UTC (rev 18382)
+++ trunk/reactos/include/idl/svcctl.idl	2005-10-09 20:24:00 UTC (rev 18383)
@@ -77,23 +77,23 @@
 
 
   /* 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 */

Modified: trunk/reactos/lib/advapi32/service/scm.c
--- trunk/reactos/lib/advapi32/service/scm.c	2005-10-09 19:08:18 UTC (rev 18382)
+++ trunk/reactos/lib/advapi32/service/scm.c	2005-10-09 20:24:00 UTC (rev 18383)
@@ -245,25 +245,54 @@
  *
  * @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;
 }
 
 

Modified: trunk/reactos/subsys/system/services/database.c
--- trunk/reactos/subsys/system/services/database.c	2005-10-09 19:08:18 UTC (rev 18382)
+++ trunk/reactos/subsys/system/services/database.c	2005-10-09 20:24:00 UTC (rev 18383)
@@ -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,14 +51,14 @@
 } SERVICE_GROUP, *PSERVICE_GROUP;
 
 
-
-
 /* GLOBALS *******************************************************************/
 
 LIST_ENTRY GroupListHead;
 LIST_ENTRY ServiceListHead;
 
+static RTL_RESOURCE DatabaseLock;
 
+
 /* FUNCTIONS *****************************************************************/
 
 PSERVICE
@@ -66,19 +71,19 @@
 
   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");
 
   return NULL;
@@ -87,48 +92,50 @@
 
 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 @@
 		       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 @@
 {
   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 @@
   InitializeListHead(&GroupListHead);
   InitializeListHead(&ServiceListHead);
 
+  /* Initialize the database lock */
+  RtlInitializeResource(&DatabaseLock);
+
   /* Build group order list */
   RtlZeroMemory(&QueryTable,
 		sizeof(QueryTable));
@@ -328,6 +337,9 @@
   if (!NT_SUCCESS(Status))
     return Status;
 
+  RtlInitUnicodeString(&ServicesKeyName,
+		       L"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
+
   InitializeObjectAttributes(&ObjectAttributes,
 			     &ServicesKeyName,
 			     OBJ_CASE_INSENSITIVE,
@@ -926,4 +938,13 @@
     }
 }
 
+
+DWORD
+ScmMarkServiceForDelete(PSERVICE pService)
+{
+  DPRINT1("ScmMarkServiceForDelete() called\n");
+
+  return ERROR_SUCCESS;
+}
+
 /* EOF */

Modified: trunk/reactos/subsys/system/services/rpcserver.c
--- trunk/reactos/subsys/system/services/rpcserver.c	2005-10-09 19:08:18 UTC (rev 18382)
+++ trunk/reactos/subsys/system/services/rpcserver.c	2005-10-09 20:24:00 UTC (rev 18383)
@@ -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 @@
 
   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 @@
                        SC_HANDLE *Handle)
 {
   PMANAGER_HANDLE Ptr;
-  
+
   if (lpDatabaseName == NULL)
     lpDatabaseName = SERVICES_ACTIVE_DATABASEW;
 
@@ -325,6 +329,7 @@
 {
   PSERVICE_HANDLE hSvc;
   PSERVICE lpService;
+  DWORD dwError;
 
   DPRINT1("ScmrDeleteService() called\n");
 
@@ -343,9 +348,16 @@
     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 @@
 }
 
 
+#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,19 +537,170 @@
                    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
 ScmrOpenSCManagerW(handle_t BindingHandle,

Modified: trunk/reactos/subsys/system/services/services.c
--- trunk/reactos/subsys/system/services/services.c	2005-10-09 19:08:18 UTC (rev 18382)
+++ trunk/reactos/subsys/system/services/services.c	2005-10-09 20:24:00 UTC (rev 18383)
@@ -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

Modified: trunk/reactos/subsys/system/services/services.h
--- trunk/reactos/subsys/system/services/services.h	2005-10-09 19:08:18 UTC (rev 18382)
+++ trunk/reactos/subsys/system/services/services.h	2005-10-09 20:24:00 UTC (rev 18383)
@@ -1,3 +1,7 @@
+/*
+ * services.h
+ */
+
 #include <stdio.h>
 #include <windows.h>
 #define NTOS_MODE_USER
@@ -3,8 +7,4 @@
 #include <ndk/ntndk.h>
 
-/*
- * services.h
- */
-
 typedef struct _SERVICE
 {
@@ -45,8 +45,8 @@
 VOID ScmGetBootAndSystemDriverState(VOID);
 VOID ScmAutoStartServices(VOID);
 
-PSERVICE
-ScmGetServiceEntryByName(PUNICODE_STRING ServiceName);
+PSERVICE ScmGetServiceEntryByName(PUNICODE_STRING ServiceName);
+DWORD ScmMarkServiceForDelete(PSERVICE pService);
 
 
 /* rpcserver.c */