Use RPC for making calls to the Service Control Manager.
Added: trunk/reactos/include/idl/svcctl.idl
Modified: trunk/reactos/lib/advapi32/makefile
Modified: trunk/reactos/lib/advapi32/service/scm.c
Modified: trunk/reactos/subsys/system/services/makefile
Added: trunk/reactos/subsys/system/services/rpcserver.c
Modified: trunk/reactos/subsys/system/services/services.c
Modified: trunk/reactos/subsys/system/services/services.h

Added: trunk/reactos/include/idl/svcctl.idl
--- trunk/reactos/include/idl/svcctl.idl	2005-04-15 19:33:51 UTC (rev 14629)
+++ trunk/reactos/include/idl/svcctl.idl	2005-04-15 22:02:37 UTC (rev 14630)
@@ -0,0 +1,72 @@
+/*
+ * Service Control Manager (SCM) interface definition
+ */
+
+//#include <windef.h>
+//#include <winsvc.h>
+
+#define DWORD unsigned long
+#define BOOL unsigned long
+#define SC_HANDLE unsigned int
+#define LPCSTR char*
+#define LPCWSTR wchar_t*
+
+[
+  uuid(367abb81-9844-35f1-ad32-98f038001003),
+  version(2.0),
+  pointer_default(unique),
+  explicit_handle
+]
+interface svcctl
+{
+cpp_quote("#if 0");
+  typedef struct _SERVICE_STATUS
+  {
+    DWORD dwServiceType;
+    DWORD dwCurrentState;
+    DWORD dwControlsAccepted;
+    DWORD dwWin32ExitCode;
+    DWORD dwServiceSpecificExitCode;
+    DWORD dwCheckPoint;
+    DWORD dwWaitHint;
+  } SERVICE_STATUS, *LPSERVICE_STATUS;
+cpp_quote("#endif");
+
+  /* Service 0 */
+  DWORD ScmrCloseServiceHandle([in] handle_t BindingHandle,
+                               [in] SC_HANDLE hSCObject);
+
+  /* Service 1 */
+//  BOOL ScmrControlService([in] handle_t BindingHandle,
+//                          [in] SC_HANDLE hService,
+//                          [in] DWORD dwControl,
+//                          [out] LPSERVICE_STATUS lpServiceStatus);
+
+  /* Service 2 */
+  DWORD ScmrDeleteService([in] handle_t BindingHandle,
+                          [in] SC_HANDLE hService);
+
+  DWORD ScmrOpenSCManagerA([in] handle_t BindingHandle,
+                           [in, string, unique] LPCSTR lpMachineName,
+                           [in, string, unique] LPCSTR lpDatabaseName,
+                           [in] DWORD dwDesiredAccess,
+                           [out] SC_HANDLE *hScm);
+
+  DWORD ScmrOpenSCManagerW([in] handle_t BindingHandle,
+                           [in, string, unique] LPCWSTR lpMachineName,
+                           [in, string, unique] LPCWSTR lpDatabaseName,
+                           [in] DWORD dwDesiredAccess,
+                           [out] SC_HANDLE *hScm);
+
+  SC_HANDLE ScmrOpenServiceA([in] handle_t BindingHandle,
+                             [in] SC_HANDLE hSCManager,
+                             [in, string] LPCSTR lpServiceName,
+                             [in] DWORD dwDesiredAccess,
+                             [out] SC_HANDLE *hScm);
+
+  SC_HANDLE ScmrOpenServiceW([in] handle_t BindingHandle,
+                             [in] SC_HANDLE hSCManager,
+                             [in, string] LPCWSTR lpServiceName,
+                             [in] DWORD dwDesiredAccess,
+                             [out] SC_HANDLE *hScm);
+}

Modified: trunk/reactos/lib/advapi32/makefile
--- trunk/reactos/lib/advapi32/makefile	2005-04-15 19:33:51 UTC (rev 14629)
+++ trunk/reactos/lib/advapi32/makefile	2005-04-15 22:02:37 UTC (rev 14630)
@@ -16,7 +16,7 @@
 
 TARGET_LFLAGS = -nostartfiles -nostdlib
 
-TARGET_SDKLIBS = ntdll.a kernel32.a
+TARGET_SDKLIBS = ntdll.a kernel32.a rpcrt4.a
 
 TARGET_BASE = $(TARGET_BASE_LIB_ADVAPI32)
 
@@ -51,7 +51,8 @@
 	service/eventlog.o \
 	service/scm.o \
 	service/sctrl.o \
-	service/undoc.o
+	service/undoc.o \
+	service/svcctl_c.o
 
 TOKEN_OBJECTS = \
 	token/privilege.o \
@@ -67,8 +68,17 @@
 
 DEP_OBJECTS = $(TARGET_OBJECTS)
 
+TARGET_CLEAN = service/svcctl_c.c service/svcctl.h
+
 include $(PATH_TO_TOP)/rules.mak
 
 include $(TOOLS_PATH)/helper.mk
 
 include $(TOOLS_PATH)/depend.mk
+
+WIDL_FLAGS = -o \
+             -D _X86_ -D MIDL_PASS \
+             -I $(PATH_TO_TOP)/w32api/include
+
+service/svcctl_c.c service/svcctl.h: $(PATH_TO_TOP)/include/idl/svcctl.idl
+	$(WIDL) $(WIDL_FLAGS) -h -H service/svcctl.h -c -C service/svcctl_c.c $(PATH_TO_TOP)/include/idl/svcctl.idl

Modified: trunk/reactos/lib/advapi32/service/scm.c
--- trunk/reactos/lib/advapi32/service/scm.c	2005-04-15 19:33:51 UTC (rev 14629)
+++ trunk/reactos/lib/advapi32/service/scm.c	2005-04-15 22:02:37 UTC (rev 14630)
@@ -1,10 +1,10 @@
-/* $Id$
- * 
+/*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
  * FILE:            lib/advapi32/service/scm.c
  * PURPOSE:         Service control manager functions
  * PROGRAMMER:      Emanuele Aliberti
+ *                  Eric Kohl
  * UPDATE HISTORY:
  *  19990413 EA created
  *  19990515 EA
@@ -13,11 +13,70 @@
 /* INCLUDES ******************************************************************/
 
 #include "advapi32.h"
+#include "svcctl.h"
+
 #define NDEBUG
 #include <debug.h>
 
 /* FUNCTIONS *****************************************************************/
 
+handle_t BindingHandle = NULL;
+
+static VOID
+HandleBind(VOID)
+{
+  LPWSTR pszStringBinding;
+  RPC_STATUS status;
+
+  if (BindingHandle != NULL)
+    return;
+
+  status = RpcStringBindingComposeW(NULL,
+                                    L"ncacn_np",
+                                    NULL,
+                                    L"\\pipe\\ntsvcs",
+                                    NULL,
+                                    &pszStringBinding);
+  if (status)
+  {
+    DPRINT1("RpcStringBindingCompose returned 0x%x\n", status);
+    return;
+  }
+
+  /* Set the binding handle that will be used to bind to the server. */
+  status = RpcBindingFromStringBindingW(pszStringBinding,
+                                        &BindingHandle);
+  if (status)
+  {
+    DPRINT1("RpcBindingFromStringBinding returned 0x%x\n", status);
+  }
+
+  status = RpcStringFreeW(&pszStringBinding);
+  if (status)
+  {
+    DPRINT1("RpcStringFree returned 0x%x\n", status);
+  }
+}
+
+
+#if 0
+static VOID
+HandleUnbind(VOID)
+{
+  RPC_STATUS status;
+
+  if (BindingHandle == NULL)
+    return;
+
+  status = RpcBindingFree(&BindingHandle);
+  if (status)
+  {
+    DPRINT1("RpcBindingFree returned 0x%x\n", status);
+  }
+}
+#endif
+
+
 /**********************************************************************
  *  ChangeServiceConfigA
  *
@@ -75,17 +134,27 @@
  *
  * @implemented
  */
-BOOL 
-STDCALL
+BOOL STDCALL
 CloseServiceHandle(SC_HANDLE hSCObject)
 {
-    DPRINT("CloseServiceHandle() - called.\n");
+  DWORD dwError;
 
-    if (!CloseHandle(hSCObject)) {
-        SetLastError(ERROR_INVALID_HANDLE);
-        return FALSE;
-    }
-    return TRUE;
+  DPRINT1("CloseServiceHandle() called\n");
+
+  HandleBind();
+
+  /* Call to services.exe using RPC */
+  dwError = ScmrCloseServiceHandle(BindingHandle,
+                                   (unsigned int)hSCObject);
+  DPRINT1("dwError %lu\n", dwError);
+
+  if (dwError)
+  {
+    SetLastError(dwError);
+    return FALSE;
+  }
+
+  return TRUE;
 }
 
 
@@ -94,15 +163,36 @@
  *
  * @unimplemented
  */
-BOOL
-STDCALL
+BOOL STDCALL
 ControlService(SC_HANDLE        hService,
                DWORD            dwControl,
                LPSERVICE_STATUS lpServiceStatus)
 {
-    DPRINT1("ControlService is unimplemented\n");
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+#if 0
+  DWORD dwError;
+
+  DPRINT1("ControlService(%x, %x, %p)\n",
+          hService, dwControl, lpServiceStatus);
+
+  HandleBind();
+
+  /* Call to services.exe using RPC */
+  dwError = ScmrControlService(BindingHandle,
+                               (unsigned int)hService,
+                               dwControl,
+                               lpServiceStatus);
+  if (dwError != ERROR_SUCCESS)
+  {
+    SetLastError(dwError);
     return FALSE;
+  }
+
+  return TRUE;
+#endif
+
+  DPRINT1("ControlService is unimplemented\n");
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return FALSE;
 }
 
 
@@ -165,13 +255,25 @@
  *
  * @unimplemented
  */
-BOOL
-STDCALL
+BOOL STDCALL
 DeleteService(SC_HANDLE hService)
 {
-    DPRINT1("DeleteService is unimplemented\n");
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  DWORD dwError;
+
+  DPRINT1("DeleteService(%x)\n", hService);
+
+  HandleBind();
+
+  /* Call to services.exe using RPC */
+  dwError = ScmrDeleteService(BindingHandle,
+                              (unsigned int)hService);
+  if (dwError != ERROR_SUCCESS)
+  {
+    SetLastError(dwError);
     return FALSE;
+  }
+
+  return TRUE;
 }
 
 
@@ -410,6 +512,7 @@
     return FALSE;
 }
 
+
 /**********************************************************************
  *  LockServiceDatabase
  *
@@ -417,7 +520,7 @@
  */
 SC_LOCK
 STDCALL
-LockServiceDatabase(SC_HANDLE   hSCManager)
+LockServiceDatabase(SC_HANDLE hSCManager)
 {
     DPRINT1("LockServiceDatabase is unimplemented\n");
     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
@@ -425,36 +528,80 @@
 }
 
 
+static VOID
+WaitForSCManager(VOID)
+{
+  HANDLE hEvent;
+
+  DPRINT1("WaitForSCManager() called\n");
+
+  /* Try to open the existing event */
+  hEvent = OpenEventW(SYNCHRONIZE,
+                      FALSE,
+                      L"SvcctrlStartEvent_A3725DX");
+  if (hEvent == NULL)
+  {
+    if (GetLastError() != ERROR_FILE_NOT_FOUND)
+      return;
+
+    /* Try to create a new event */
+    hEvent = CreateEventW(NULL,
+                          TRUE,
+                          FALSE,
+                          L"SvcctrlStartEvent_A3725DX");
+    if (hEvent == NULL)
+    {
+      /* Try to open the existing event again */
+      hEvent = OpenEventW(SYNCHRONIZE,
+                          FALSE,
+                          L"SvcctrlStartEvent_A3725DX");
+      if (hEvent == NULL)
+        return;
+    }
+  }
+
+  /* Wait for 3 minutes */
+  WaitForSingleObject(hEvent, 180000);
+  CloseHandle(hEvent);
+
+  DPRINT1("ScmWaitForSCManager() done\n");
+}
+
+
 /**********************************************************************
  *  OpenSCManagerA
  *
- * @unplemented
+ * @implemented
  */
 SC_HANDLE STDCALL
 OpenSCManagerA(LPCSTR lpMachineName,
-           LPCSTR lpDatabaseName,
-           DWORD dwDesiredAccess)
+               LPCSTR lpDatabaseName,
+               DWORD dwDesiredAccess)
 {
-  SC_HANDLE Handle;
-  UNICODE_STRING MachineNameW;
-  UNICODE_STRING DatabaseNameW;
-  ANSI_STRING MachineNameA;
-  ANSI_STRING DatabaseNameA;
+  SC_HANDLE hScm = NULL;
+  DWORD dwError;
 
-  DPRINT("OpenSCManagerA(%x, %x, %d)\n", lpMachineName, lpDatabaseName, dwDesiredAccess);
+  DPRINT1("OpenSCManagerA(%s, %s, %lx)\n",
+         lpMachineName, lpDatabaseName, dwDesiredAccess);
 
-  RtlInitAnsiString(&MachineNameA, (LPSTR)lpMachineName);
-  RtlAnsiStringToUnicodeString(&MachineNameW, &MachineNameA, TRUE);
-  RtlInitAnsiString(&DatabaseNameA, (LPSTR)lpDatabaseName);
-  RtlAnsiStringToUnicodeString(&DatabaseNameW, &DatabaseNameA, TRUE);
+  WaitForSCManager();
 
-  Handle = OpenSCManagerW(lpMachineName ? MachineNameW.Buffer : NULL,
-              lpDatabaseName ? DatabaseNameW.Buffer : NULL,
-              dwDesiredAccess);
+  HandleBind();
 
-  RtlFreeHeap(GetProcessHeap(), 0, MachineNameW.Buffer);
-  RtlFreeHeap(GetProcessHeap(), 0, DatabaseNameW.Buffer);
-  return Handle;
+  /* Call to services.exe using RPC */
+  dwError = ScmrOpenSCManagerA(BindingHandle,
+                               (LPSTR)lpMachineName,
+                               (LPSTR)lpDatabaseName,
+                               dwDesiredAccess,
+                               (unsigned int*)&hScm);
+  DPRINT1("hScm = %p\n", hScm);
+  if (dwError)
+  {
+    SetLastError(dwError);
+    return NULL;
+  }
+
+  return hScm;
 }
 
 
@@ -463,215 +610,111 @@
  *
  * @unimplemented
  */
-SC_HANDLE STDCALL OpenSCManagerW(LPCWSTR lpMachineName,
-                                 LPCWSTR lpDatabaseName,
-                                 DWORD dwDesiredAccess)
+SC_HANDLE STDCALL
+OpenSCManagerW(LPCWSTR lpMachineName,
+               LPCWSTR lpDatabaseName,
+               DWORD dwDesiredAccess)
 {
-  HANDLE hPipe;
-  DWORD dwMode;
-  DWORD dwWait;
-  BOOL fSuccess;
-  HANDLE hStartEvent;
-  LPWSTR lpszPipeName = L"\\\\.\\pipe\\Ntsvcs";
+  SC_HANDLE hScm = NULL;
+  DWORD dwError;
 
-  DPRINT("OpenSCManagerW(%x, %x, %d)\n", lpMachineName, lpDatabaseName, dwDesiredAccess);
+  DPRINT1("OpenSCManagerW(%S, %S, %lx)\n",
+         lpMachineName, lpDatabaseName, dwDesiredAccess);
 
-  if (lpMachineName == NULL || wcslen(lpMachineName) == 0)
-    {
-      if (lpDatabaseName != NULL && wcscmp(lpDatabaseName, SERVICES_ACTIVE_DATABASEW) != 0)
-	{
-	  DPRINT("OpenSCManagerW() - Invalid parameters.\n");
-	  return NULL; 
-	}
+  WaitForSCManager();
 
-      DPRINT("OpenSCManagerW() - OpenEvent(\"SvcctrlStartEvent_A3725DX\")\n");
+  HandleBind();
 
-      // Only connect to scm when event "SvcctrlStartEvent_A3725DX" is signaled
-      hStartEvent = OpenEventW(SYNCHRONIZE, FALSE, L"SvcctrlStartEvent_A3725DX");
-      if (hStartEvent == NULL)
-	{
-	  SetLastError(ERROR_DATABASE_DOES_NOT_EXIST);
-	  DPRINT("OpenSCManagerW() - Failed to Open Event \"SvcctrlStartEvent_A3725DX\".\n");
-	  return NULL;
-	}
+  /* Call to services.exe using RPC */
+  dwError = ScmrOpenSCManagerW(BindingHandle,
+                               (LPWSTR)lpMachineName,
+                               (LPWSTR)lpDatabaseName,
+                               dwDesiredAccess,
+                               (unsigned int*)&hScm);
+  if (dwError != ERROR_SUCCESS)
+  {
+    DPRINT1("ScmrOpenSCManagerW() failed (Error %lu)\n", dwError);
+    SetLastError(dwError);
+    return NULL;
+  }
 
-      DPRINT("OpenSCManagerW() - Waiting forever on event handle: %x\n", hStartEvent);
+  DPRINT1("hScm = %p\n", hScm);
 
-#if 1
-      dwWait = WaitForSingleObject(hStartEvent, INFINITE);
-      if (dwWait == WAIT_FAILED)
-	{
-	  DPRINT("OpenSCManagerW() - Wait For Start Event failed.\n");
-	  SetLastError(ERROR_ACCESS_DENIED);
-	  return NULL;
-	}
-#else
-	{
-          DWORD Count;
-
-	  /* wait for event creation (by SCM) for max. 20 seconds */
-	  for (Count = 0; Count < 20; Count++)
-	    {
-	      dwWait = WaitForSingleObject(hStartEvent, 1000);
-	      if (dwWait == WAIT_FAILED)
-		{
-		  DPRINT("OpenSCManagerW() - Wait For Start Event failed.\n");
-		  Sleep(1000);
-		}
-	      else
-		{
-		  break;
-		}
-	    }
-
-	  if (dwWait == WAIT_FAILED)
-	    {
-	      DbgPrint("WL: Failed to wait on event \"SvcctrlStartEvent_A3725DX\"\n");
-	    }
-
-	}
-#endif
-
-      DPRINT("OpenSCManagerW() - Closing handle to event...\n");
-      
-      CloseHandle(hStartEvent);
-      
-      // Try to open a named pipe; wait for it, if necessary
-      while (1)
-      {
-	DWORD dwLastError;
-	DPRINT("OpenSCManagerW() - attempting to open named pipe to SCM.\n");
-	hPipe = CreateFileW(lpszPipeName,     // pipe name
-	    dwDesiredAccess,
-	    0,                // no sharing
-	    NULL,             // no security attributes
-	    OPEN_EXISTING,    // opens existing pipe
-	    0,                // default attributes
-	    NULL);            // no template file
-	
-	DPRINT("OpenSCManagerW() - handle to named pipe: %x\n", hPipe);
-	// Break if the pipe handle is valid
-	if (hPipe != INVALID_HANDLE_VALUE)
-	  {
-	    break;
-	  }
-	
-	// Exit if an error other than ERROR_PIPE_BUSY occurs
-	dwLastError = GetLastError();
-	if (dwLastError != ERROR_PIPE_BUSY)
-	  {
-	    DPRINT("OpenSCManagerW() - returning at 4, dwLastError %d\n", dwLastError);
-	    return NULL;
-	  }
-	
-	// All pipe instances are busy, so wait for 20 seconds
-	if (!WaitNamedPipeW(lpszPipeName, 20000))
-	  {
-	    DPRINT("OpenSCManagerW() - Failed on WaitNamedPipeW(...).\n");
-	    return NULL;
-	  }
-      }
-    
-      // The pipe connected; change to message-read mode
-      dwMode = PIPE_READMODE_MESSAGE;
-      fSuccess = SetNamedPipeHandleState(
-	  hPipe,    // pipe handle
-	  &dwMode,  // new pipe mode
-	  NULL,     // don't set maximum bytes
-	  NULL);    // don't set maximum time
-      if (!fSuccess)
-	{
-	  CloseHandle(hPipe);
-	  DPRINT("OpenSCManagerW() - Failed on SetNamedPipeHandleState(...).\n");
-	  return NULL;
-	}
-#if 0
-      // Send a message to the pipe server
-      lpvMessage = (argc > 1) ? argv[1] : "default message";
-      
-      fSuccess = WriteFile(
-	  hPipe,                  // pipe handle
-	  lpvMessage,             // message
-	  strlen(lpvMessage) + 1, // message length
-	  &cbWritten,             // bytes written
-	  NULL);                  // not overlapped
-      if (!fSuccess)
-	{
-	  CloseHandle(hPipe);
-	  DPRINT("OpenSCManagerW() - Failed to write to pipe.\n");
-	  return NULL;
-	}
-      
-      do
-	{
-	  DPRINT("OpenSCManagerW() - in I/O loop to SCM...\n");
-	  // Read from the pipe
-	  fSuccess = ReadFile(
-	      hPipe,    // pipe handle
-	      chBuf,    // buffer to receive reply
-	      512,      // size of buffer
-	      &cbRead,  // number of bytes read
-	      NULL);    // not overlapped
-	  
-	  if (!fSuccess && GetLastError() != ERROR_MORE_DATA)
-	    {
-	      break;
-	    }
-	  
-	  // Reply from the pipe is written to STDOUT.
-	  if (!WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), chBuf, cbRead, &cbWritten, NULL))
-	    {
-	      break;
-	    }
-	} while(!fSuccess);  // repeat loop if ERROR_MORE_DATA
-      
-      DPRINT("OpenSCManagerW() - I/O loop completed.\n");
-      //CloseHandle(hPipe);
-#endif
-      DPRINT("OpenSCManagerW() - success, returning handle to pipe %x\n", hPipe);
-      return hPipe;
-    }
-  else
-    {
-      /* FIXME: Connect to remote SCM */
-      DPRINT("OpenSCManagerW() - FIXME: Connect to remote SCM is unimplemented.\n");
-      return NULL;
-    }
+  return hScm;
 }
 
 
 /**********************************************************************
  *  OpenServiceA
  *
- * @unimplemented
+ * @implemented
  */
 SC_HANDLE STDCALL
 OpenServiceA(SC_HANDLE hSCManager,
          LPCSTR  lpServiceName,
          DWORD dwDesiredAccess)
 {
-  DPRINT1("OpenServiceA is unimplemented, returning ERROR_SERVICE_DOES_NOT_EXIST for %s\n", lpServiceName);
-  SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
-  return NULL;
+  SC_HANDLE hService = NULL;
+  DWORD dwError;
+
+  DPRINT1("OpenServiceA(%p, %s, %lx)\n",
+          hSCManager, lpServiceName, dwDesiredAccess);
+
+  HandleBind();
+
+  /* Call to services.exe using RPC */
+  dwError = ScmrOpenServiceA(BindingHandle,
+                             (unsigned int)hSCManager,
+                             (LPSTR)lpServiceName,
+                             dwDesiredAccess,
+                             (unsigned int*)&hService);
+  if (dwError != ERROR_SUCCESS)
+  {
+    DPRINT1("ScmrOpenServiceA() failed (Error %lu)\n", dwError);
+    SetLastError(dwError);
+    return NULL;
+  }
+
+  DPRINT1("hService = %p\n", hService);
+
+  return hService;
 }
 
 
 /**********************************************************************
  *  OpenServiceW
  *
- * @unimplemented
+ * @implemented
  */
-SC_HANDLE
-STDCALL
-OpenServiceW(
-    SC_HANDLE   hSCManager,
-    LPCWSTR     lpServiceName,
-    DWORD       dwDesiredAccess
-    )
+SC_HANDLE STDCALL
+OpenServiceW(SC_HANDLE hSCManager,
+             LPCWSTR lpServiceName,
+             DWORD dwDesiredAccess)
 {
-  DPRINT1("OpenServiceW is unimplemented, returning ERROR_SERVICE_DOES_NOT_EXIST for %S\n", lpServiceName);
-  SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
-  return NULL;
+  SC_HANDLE hService = NULL;
+  DWORD dwError;
+
+  DPRINT1("OpenServiceW(%p, %S, %lx)\n",
+          hSCManager, lpServiceName, dwDesiredAccess);
+
+  HandleBind();
+
+  /* Call to services.exe using RPC */
+  dwError = ScmrOpenServiceW(BindingHandle,
+                             (unsigned int)hSCManager,
+                             (LPWSTR)lpServiceName,
+                             dwDesiredAccess,
+                             (unsigned int*)&hService);
+  if (dwError != ERROR_SUCCESS)
+  {
+    DPRINT1("ScmrOpenServiceW() failed (Error %lu)\n", dwError);
+    SetLastError(dwError);
+    return NULL;
+  }
+
+  DPRINT1("hService = %p\n", hService);
+
+  return hService;
 }
 
 
@@ -860,4 +903,14 @@
 }
 
 
+void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
+{
+  return GlobalAlloc(GPTR,len);
+}
+
+void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
+{
+  GlobalFree(ptr);
+}
+
 /* EOF */

Modified: trunk/reactos/subsys/system/services/makefile
--- trunk/reactos/subsys/system/services/makefile	2005-04-15 19:33:51 UTC (rev 14629)
+++ trunk/reactos/subsys/system/services/makefile	2005-04-15 22:02:37 UTC (rev 14630)
@@ -10,14 +10,29 @@
 
 TARGET_INSTALLDIR = system32
 
-TARGET_SDKLIBS = ntdll.a kernel32.a user32.a
+TARGET_SDKLIBS = ntdll.a kernel32.a user32.a rpcrt4.a
 
-TARGET_OBJECTS = $(TARGET_NAME).o database.o
+TARGET_OBJECTS = svcctl_s.o database.o services.o rpcserver.o
 
-TARGET_CFLAGS = -D__USE_W32API -Wall -Werror
+TARGET_CFLAGS = -Wall -Werror -fno-builtin \
+                -D__USE_W32API \
+                -D_WIN32_IE=0x0500 \
+                -D_WIN32_WINNT=0x501 \
+                -DWINVER=0x600 \
+                -DUNICODE \
+                -D_UNICODE
 
+TARGET_CLEAN = svcctl_s.c svcctl_s.h
+
+DEP_OBJECTS = $(TARGET_OBJECTS)
+
 include $(PATH_TO_TOP)/rules.mak
 
 include $(TOOLS_PATH)/helper.mk
 
+include $(TOOLS_PATH)/depend.mk
+
+svcctl_s.c svcctl_s.h: $(PATH_TO_TOP)/include/idl/svcctl.idl
+	$(WIDL) -o -h -H svcctl_s.h -s -S svcctl_s.c $(PATH_TO_TOP)/include/idl/svcctl.idl
+
 # EOF

Added: trunk/reactos/subsys/system/services/rpcserver.c
--- trunk/reactos/subsys/system/services/rpcserver.c	2005-04-15 19:33:51 UTC (rev 14629)
+++ trunk/reactos/subsys/system/services/rpcserver.c	2005-04-15 22:02:37 UTC (rev 14630)
@@ -0,0 +1,349 @@
+/*
+
+ */
+
+/* INCLUDES ****************************************************************/
+
+#define NTOS_MODE_USER
+#include <ntos.h>
+#include <stdio.h>
+#include <windows.h>
+
+#include "services.h"
+#include "svcctl_s.h"
+
+#define NDEBUG
+#include <debug.h>
+
+
+/* GLOBALS *****************************************************************/
+
+#define MANAGER_TAG 0x72674D68  /* 'hMgr' */
+#define SERVICE_TAG 0x63765368  /* 'hSvc' */
+
+typedef struct _SCMGR_HANDLE
+{
+  DWORD Tag;
+  DWORD RefCount;
+  DWORD DesiredAccess;
+} SCMGR_HANDLE;
+
+
+typedef struct _MANAGER_HANDLE
+{
+  SCMGR_HANDLE Handle;
+
+  /* FIXME: Insert more data here */
+
+  WCHAR DatabaseName[1];
+} MANAGER_HANDLE, *PMANAGER_HANDLE;
+
+
+typedef struct _SERVICE_HANDLE
+{
+  SCMGR_HANDLE Handle;
+
+  DWORD DesiredAccess;
+  PVOID DatabaseEntry; /* FIXME */
+
+  /* FIXME: Insert more data here */
+
+} SERVICE_HANDLE, *PSERVICE_HANDLE;
+
+
+/* FUNCTIONS ***************************************************************/
+
+VOID
+ScmStartRpcServer(VOID)
+{
+  RPC_STATUS Status;
+
+  DPRINT("ScmStartRpcServer() called");
+
+  Status = RpcServerUseProtseqEp(L"ncacn_np",
+                                 10,
+                                 L"\\pipe\\ntsvcs",
+                                 NULL);
+  if (Status != RPC_S_OK)
+  {
+    DPRINT1("RpcServerUseProtseqEp() failed (Status %lx)\n", Status);
+    return;
+  }
+
+  Status = RpcServerRegisterIf(svcctl_ServerIfHandle,
+                               NULL,
+                               NULL);
+  if (Status != RPC_S_OK)
+  {
+    DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
+    return;
+  }
+
+  Status = RpcServerListen(1, 20, TRUE);
+  if (Status != RPC_S_OK)
+  {
+    DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
+    return;
+  }
+
+  DPRINT("ScmStartRpcServer() done");
+}
+
+
+static DWORD
+ScmCreateManagerHandle(LPWSTR lpDatabaseName,
+                       SC_HANDLE *Handle,
+                       DWORD dwDesiredAccess)
+{
+  PMANAGER_HANDLE Ptr;
+
+  Ptr = GlobalAlloc(GPTR,
+                    sizeof(MANAGER_HANDLE) + wcslen(lpDatabaseName) * sizeof(WCHAR));
+  if (Ptr == NULL)
+    return ERROR_NOT_ENOUGH_MEMORY;
+
+  Ptr->Handle.Tag = MANAGER_TAG;
+  Ptr->Handle.RefCount = 1;
+  Ptr->Handle.DesiredAccess = dwDesiredAccess;
+
+  /* FIXME: initialize more data here */
+
+  wcscpy(Ptr->DatabaseName, lpDatabaseName);
+
+  *Handle = (SC_HANDLE)Ptr;
+
+  return ERROR_SUCCESS;
+}
+
+
+static DWORD
+ScmCreateServiceHandle(LPVOID lpDatabaseEntry,
+                       SC_HANDLE *Handle,
+                       DWORD dwDesiredAccess)
+{
+  PMANAGER_HANDLE Ptr;
+
+  Ptr = GlobalAlloc(GPTR,
+                    sizeof(SERVICE_HANDLE));
+  if (Ptr == NULL)
+    return ERROR_NOT_ENOUGH_MEMORY;
+
+  Ptr->Handle.Tag = SERVICE_TAG;
+  Ptr->Handle.RefCount = 1;
+  Ptr->Handle.DesiredAccess = dwDesiredAccess;
+
+  /* FIXME: initialize more data here */
+  // Ptr->DatabaseEntry = lpDatabaseEntry;
+
+  *Handle = (SC_HANDLE)Ptr;
+
+  return ERROR_SUCCESS;
+}
+
+
+/* Service 0 */
+unsigned long
+ScmrCloseServiceHandle(handle_t BindingHandle,
+                       unsigned int hScObject)
+{
+  PMANAGER_HANDLE hManager;
+
+  DPRINT("ScmrCloseServiceHandle() called\n");
+
+  DPRINT("hScObject = %X\n", hScObject);
+
+  if (hScObject == 0)
+    return ERROR_INVALID_HANDLE;
+
+  hManager = (PMANAGER_HANDLE)hScObject;
+  if (hManager->Handle.Tag == MANAGER_TAG)
+  {
+    DPRINT("Found manager handle\n");
+
+    hManager->Handle.RefCount--;
+    if (hManager->Handle.RefCount == 0)
+    {
+      /* FIXME: add cleanup code */
+
+      GlobalFree(hManager);
+    }
+
+    DPRINT("ScmrCloseServiceHandle() done\n");
+    return ERROR_SUCCESS;
+  }
+  else if (hManager->Handle.Tag == SERVICE_TAG)
+  {
+    DPRINT("Found service handle\n");
+
+    hManager->Handle.RefCount--;
+    if (hManager->Handle.RefCount == 0)
+    {
+      /* FIXME: add cleanup code */
+
+      GlobalFree(hManager);
+    }
+
+    DPRINT("ScmrCloseServiceHandle() done\n");
+    return ERROR_SUCCESS;
+  }
+
+  DPRINT1("Invalid handle tag (Tag %lx)\n", hManager->Handle.Tag);
+
+  return ERROR_INVALID_HANDLE;
+}
+
+
+/* Service 1 */
+#if 0
+unsigned long
+ScmrControlService(handle_t BindingHandle,
+                   unsigned int hService,
+                   unsigned long dwControl,
+                   LPSERVICE_STATUS lpServiceStatus)
+{
+  DPRINT("ScmrControlService() called\n");
+
+#if 0
+  lpServiceStatus->dwServiceType = 0x12345678;
+  lpServiceStatus->dwCurrentState = 0x98765432;
+  lpServiceStatus->dwControlsAccepted = 0xdeadbabe;
+  lpServiceStatus->dwWin32ExitCode = 0xbaadf00d;
+  lpServiceStatus->dwServiceSpecificExitCode = 0xdeadf00d;
+  lpServiceStatus->dwCheckPoint = 0xbaadbabe;
+  lpServiceStatus->dwWaitHint = 0x2468ACE1;
+#endif
+
+  return TRUE;
+}
+#endif
+
[truncated at 1000 lines; 487 more skipped]