ADVAPI32.DLL:
- Implement LockServiceDatabase and UnlockServiceDatabase.

SERVICES.EXE:
- Add stubs: ScmrLockServiceDatabase, ScmrUnlockDerviceDatabase, SamrNotifyBootConfigStatus, and ScmrCreateServiceW.
- Store and check access rights.
Modified: trunk/reactos/include/idl/svcctl.idl
Modified: trunk/reactos/lib/advapi32/service/scm.c
Modified: trunk/reactos/subsys/system/services/rpcserver.c

Modified: trunk/reactos/include/idl/svcctl.idl
--- trunk/reactos/include/idl/svcctl.idl	2005-04-16 11:48:26 UTC (rev 14634)
+++ trunk/reactos/include/idl/svcctl.idl	2005-04-16 12:50:33 UTC (rev 14635)
@@ -8,8 +8,10 @@
 #define DWORD unsigned long
 #define BOOL unsigned long
 #define SC_HANDLE unsigned int
+#define SC_LOCK unsigned int
 #define LPCSTR char*
 #define LPCWSTR wchar_t*
+#define LPDWORD unsigned long*
 
 [
   uuid(367abb81-9844-35f1-ad32-98f038001003),
@@ -32,41 +34,90 @@
   } SERVICE_STATUS, *LPSERVICE_STATUS;
 cpp_quote("#endif");
 
-  /* Service 0 */
+  /* Function 0 */
   DWORD ScmrCloseServiceHandle([in] handle_t BindingHandle,
                                [in] SC_HANDLE hSCObject);
 
-  /* Service 1 */
+  /* Function 1 */
 //  BOOL ScmrControlService([in] handle_t BindingHandle,
 //                          [in] SC_HANDLE hService,
 //                          [in] DWORD dwControl,
 //                          [out] LPSERVICE_STATUS lpServiceStatus);
 
-  /* Service 2 */
+  /* Function 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,
+  /* Function 3 */
+  DWORD ScmrLockServiceDatabase([in] handle_t BindingHandle,
+                                [in] SC_HANDLE hSCManager,
+                                [out] SC_LOCK *hLock);
+
+  /* Function 4 */
+//  DWORD ScmrQueryServiceObjectSecurity();
+
+  /* Function 5 */
+//  DWORD ScmrSetServiceObjectSecurity();
+
+  /* Function 6 */
+//  DWORD ScmrQueryServiceStatus();
+
+  /* Function 7 */
+//  DWORD ScmrSetServiceStatus();
+
+  /* Function 8 */
+  DWORD ScmrUnlockServiceDatabase([in] handle_t BindingHandle,
+                                  [in] SC_LOCK hLock);
+
+  /* Function 9 */
+  DWORD ScmrNotifyBootConfigStatus([in] handle_t BindingHandle,
+                                   [in] BOOL BootAcceptable);
+
+
+  /* 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,
-                           [out] SC_HANDLE *hScm);
+                           [in] DWORD dwServiceType,
+                           [in] DWORD dwStartType,
+                           [in] DWORD dwErrorControl,
+                           [in, string, ref] LPCWSTR lpBinaryPathName,
+                           [in, string, unique] LPCWSTR lpLoadOrderGroup,
+                           [out, unique] LPDWORD lpdwTagId,
+                           [in, string, unique] LPCWSTR lpDependencies,
+                           [in, string, unique] LPCWSTR lpServiceStartName,
+                           [in, string, unique] LPCWSTR lpPassword);
 
+
+  /* Function 15 */
   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,
+  /* Function 16 */
+  SC_HANDLE ScmrOpenServiceW([in] handle_t BindingHandle,
                              [in] SC_HANDLE hSCManager,
-                             [in, string] LPCSTR lpServiceName,
+                             [in, string] LPCWSTR lpServiceName,
                              [in] DWORD dwDesiredAccess,
                              [out] SC_HANDLE *hScm);
 
-  SC_HANDLE ScmrOpenServiceW([in] handle_t BindingHandle,
+
+  /* Function 27 */
+  DWORD ScmrOpenSCManagerA([in] handle_t BindingHandle,
+                           [in, string, unique] LPCSTR lpMachineName,
+                           [in, string, unique] LPCSTR lpDatabaseName,
+                           [in] DWORD dwDesiredAccess,
+                           [out] SC_HANDLE *hScm);
+
+  /* Function 28 */
+  SC_HANDLE ScmrOpenServiceA([in] handle_t BindingHandle,
                              [in] SC_HANDLE hSCManager,
-                             [in, string] LPCWSTR lpServiceName,
+                             [in, string] LPCSTR lpServiceName,
                              [in] DWORD dwDesiredAccess,
                              [out] SC_HANDLE *hScm);
+
 }

Modified: trunk/reactos/lib/advapi32/service/scm.c
--- trunk/reactos/lib/advapi32/service/scm.c	2005-04-16 11:48:26 UTC (rev 14634)
+++ trunk/reactos/lib/advapi32/service/scm.c	2005-04-16 12:50:33 UTC (rev 14635)
@@ -253,7 +253,7 @@
 /**********************************************************************
  *  DeleteService
  *
- * @unimplemented
+ * @implemented
  */
 BOOL STDCALL
 DeleteService(SC_HANDLE hService)
@@ -516,15 +516,32 @@
 /**********************************************************************
  *  LockServiceDatabase
  *
- * @unimplemented
+ * @implemented
  */
-SC_LOCK
-STDCALL
+SC_LOCK STDCALL
 LockServiceDatabase(SC_HANDLE hSCManager)
 {
-    DPRINT1("LockServiceDatabase is unimplemented\n");
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  SC_LOCK hLock;
+  DWORD dwError;
+
+  DPRINT("LockServiceDatabase(%x)\n", hSCManager);
+
+  HandleBind();
+
+  /* Call to services.exe using RPC */
+  dwError = ScmrLockServiceDatabase(BindingHandle,
+                                    (unsigned int)hSCManager,
+                                    (unsigned int *)&hLock);
+  if (dwError != ERROR_SUCCESS)
+  {
+    DPRINT("ScmrLockServiceDatabase() failed (Error %lu)\n", dwError);
+    SetLastError(dwError);
     return NULL;
+  }
+
+  DPRINT("hLock = %p\n", hLock);
+
+  return hLock;
 }
 
 
@@ -533,7 +550,7 @@
 {
   HANDLE hEvent;
 
-  DPRINT1("WaitForSCManager() called\n");
+  DPRINT("WaitForSCManager() called\n");
 
   /* Try to open the existing event */
   hEvent = OpenEventW(SYNCHRONIZE,
@@ -564,7 +581,7 @@
   WaitForSingleObject(hEvent, 180000);
   CloseHandle(hEvent);
 
-  DPRINT1("ScmWaitForSCManager() done\n");
+  DPRINT("ScmWaitForSCManager() done\n");
 }
 
 
@@ -581,7 +598,7 @@
   SC_HANDLE hScm = NULL;
   DWORD dwError;
 
-  DPRINT1("OpenSCManagerA(%s, %s, %lx)\n",
+  DPRINT("OpenSCManagerA(%s, %s, %lx)\n",
          lpMachineName, lpDatabaseName, dwDesiredAccess);
 
   WaitForSCManager();
@@ -594,13 +611,15 @@
                                (LPSTR)lpDatabaseName,
                                dwDesiredAccess,
                                (unsigned int*)&hScm);
-  DPRINT1("hScm = %p\n", hScm);
   if (dwError)
   {
+    DPRINT("ScmrOpenSCManagerA() failed (Error %lu)\n", dwError);
     SetLastError(dwError);
     return NULL;
   }
 
+  DPRINT("hScm = %p\n", hScm);
+
   return hScm;
 }
 
@@ -608,7 +627,7 @@
 /**********************************************************************
  *  OpenSCManagerW
  *
- * @unimplemented
+ * @implemented
  */
 SC_HANDLE STDCALL
 OpenSCManagerW(LPCWSTR lpMachineName,
@@ -618,7 +637,7 @@
   SC_HANDLE hScm = NULL;
   DWORD dwError;
 
-  DPRINT1("OpenSCManagerW(%S, %S, %lx)\n",
+  DPRINT("OpenSCManagerW(%S, %S, %lx)\n",
          lpMachineName, lpDatabaseName, dwDesiredAccess);
 
   WaitForSCManager();
@@ -638,7 +657,7 @@
     return NULL;
   }
 
-  DPRINT1("hScm = %p\n", hScm);
+  DPRINT("hScm = %p\n", hScm);
 
   return hScm;
 }
@@ -651,14 +670,14 @@
  */
 SC_HANDLE STDCALL
 OpenServiceA(SC_HANDLE hSCManager,
-         LPCSTR  lpServiceName,
-         DWORD dwDesiredAccess)
+             LPCSTR lpServiceName,
+             DWORD dwDesiredAccess)
 {
   SC_HANDLE hService = NULL;
   DWORD dwError;
 
-  DPRINT1("OpenServiceA(%p, %s, %lx)\n",
-          hSCManager, lpServiceName, dwDesiredAccess);
+  DPRINT("OpenServiceA(%p, %s, %lx)\n",
+         hSCManager, lpServiceName, dwDesiredAccess);
 
   HandleBind();
 
@@ -675,7 +694,7 @@
     return NULL;
   }
 
-  DPRINT1("hService = %p\n", hService);
+  DPRINT("hService = %p\n", hService);
 
   return hService;
 }
@@ -694,8 +713,8 @@
   SC_HANDLE hService = NULL;
   DWORD dwError;
 
-  DPRINT1("OpenServiceW(%p, %S, %lx)\n",
-          hSCManager, lpServiceName, dwDesiredAccess);
+  DPRINT("OpenServiceW(%p, %S, %lx)\n",
+         hSCManager, lpServiceName, dwDesiredAccess);
 
   HandleBind();
 
@@ -712,7 +731,7 @@
     return NULL;
   }
 
-  DPRINT1("hService = %p\n", hService);
+  DPRINT("hService = %p\n", hService);
 
   return hService;
 }
@@ -891,15 +910,28 @@
 /**********************************************************************
  *  UnlockServiceDatabase
  *
- * @unimplemented
+ * @implemented
  */
-BOOL
-STDCALL
-UnlockServiceDatabase(SC_LOCK   ScLock)
+BOOL STDCALL
+UnlockServiceDatabase(SC_LOCK ScLock)
 {
-    DPRINT1("UnlockServiceDatabase is unimplemented\n");
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  DWORD dwError;
+
+  DPRINT("UnlockServiceDatabase(%x)\n", hSCManager);
+
+  HandleBind();
+
+  /* Call to services.exe using RPC */
+  dwError = ScmrUnlockServiceDatabase(BindingHandle,
+                                      (unsigned int)ScLock);
+  if (dwError != ERROR_SUCCESS)
+  {
+    DPRINT("ScmrUnlockServiceDatabase() failed (Error %lu)\n", dwError);
+    SetLastError(dwError);
     return FALSE;
+  }
+
+  return TRUE;
 }
 
 

Modified: trunk/reactos/subsys/system/services/rpcserver.c
--- trunk/reactos/subsys/system/services/rpcserver.c	2005-04-16 11:48:26 UTC (rev 14634)
+++ trunk/reactos/subsys/system/services/rpcserver.c	2005-04-16 12:50:33 UTC (rev 14635)
@@ -51,6 +51,58 @@
 } SERVICE_HANDLE, *PSERVICE_HANDLE;
 
 
+#define SC_MANAGER_READ \
+  (STANDARD_RIGHTS_READ | \
+   SC_MANAGER_QUERY_LOCK_STATUS | \
+   SC_MANAGER_ENUMERATE_SERVICE)
+
+#define SC_MANAGER_WRITE \
+  (STANDARD_RIGHTS_WRITE | \
+   SC_MANAGER_MODIFY_BOOT_CONFIG | \
+   SC_MANAGER_CREATE_SERVICE)
+
+#define SC_MANAGER_EXECUTE \
+  (STANDARD_RIGHTS_EXECUTE | \
+   SC_MANAGER_LOCK | \
+   SC_MANAGER_ENUMERATE_SERVICE | \
+   SC_MANAGER_CONNECT | \
+   SC_MANAGER_CREATE_SERVICE)
+
+
+#define SERVICE_READ \
+  (STANDARD_RIGHTS_READ | \
+   SERVICE_INTERROGATE | \
+   SERVICE_ENUMERATE_DEPENDENTS | \
+   SERVICE_QUERY_STATUS | \
+   SERVICE_QUERY_CONFIG)
+
+#define SERVICE_WRITE \
+  (STANDARD_RIGHTS_WRITE | \
+   SERVICE_CHANGE_CONFIG)
+
+#define SERVICE_EXECUTE \
+  (STANDARD_RIGHTS_EXECUTE | \
+   SERVICE_USER_DEFINED_CONTROL | \
+   SERVICE_PAUSE_CONTINUE | \
+   SERVICE_STOP | \
+   SERVICE_START)
+
+
+/* VARIABLES ***************************************************************/
+
+static GENERIC_MAPPING
+ScmManagerMapping = {SC_MANAGER_READ,
+                     SC_MANAGER_WRITE,
+                     SC_MANAGER_EXECUTE,
+                     SC_MANAGER_ALL_ACCESS};
+
+static GENERIC_MAPPING
+ScmServiceMapping = {SERVICE_READ,
+                     SERVICE_WRITE,
+                     SERVICE_EXECUTE,
+                     SC_MANAGER_ALL_ACCESS};
+
+
 /* FUNCTIONS ***************************************************************/
 
 VOID
@@ -92,8 +144,7 @@
 
 static DWORD
 ScmCreateManagerHandle(LPWSTR lpDatabaseName,
-                       SC_HANDLE *Handle,
-                       DWORD dwDesiredAccess)
+                       SC_HANDLE *Handle)
 {
   PMANAGER_HANDLE Ptr;
 
@@ -104,7 +155,6 @@
 
   Ptr->Handle.Tag = MANAGER_TAG;
   Ptr->Handle.RefCount = 1;
-  Ptr->Handle.DesiredAccess = dwDesiredAccess;
 
   /* FIXME: initialize more data here */
 
@@ -118,8 +168,7 @@
 
 static DWORD
 ScmCreateServiceHandle(LPVOID lpDatabaseEntry,
-                       SC_HANDLE *Handle,
-                       DWORD dwDesiredAccess)
+                       SC_HANDLE *Handle)
 {
   PMANAGER_HANDLE Ptr;
 
@@ -130,7 +179,6 @@
 
   Ptr->Handle.Tag = SERVICE_TAG;
   Ptr->Handle.RefCount = 1;
-  Ptr->Handle.DesiredAccess = dwDesiredAccess;
 
   /* FIXME: initialize more data here */
   // Ptr->DatabaseEntry = lpDatabaseEntry;
@@ -141,7 +189,37 @@
 }
 
 
-/* Service 0 */
+static DWORD
+ScmCheckAccess(SC_HANDLE Handle,
+               DWORD dwDesiredAccess)
+{
+  PMANAGER_HANDLE hMgr;
+
+  hMgr = (PMANAGER_HANDLE)Handle;
+  if (hMgr->Handle.Tag == MANAGER_TAG)
+  {
+    RtlMapGenericMask(&dwDesiredAccess,
+                      &ScmManagerMapping);
+
+    hMgr->Handle.DesiredAccess = dwDesiredAccess;
+
+    return ERROR_SUCCESS;
+  }
+  else if (hMgr->Handle.Tag == SERVICE_TAG)
+  {
+    RtlMapGenericMask(&dwDesiredAccess,
+                      &ScmServiceMapping);
+
+    hMgr->Handle.DesiredAccess = dwDesiredAccess;
+
+    return ERROR_SUCCESS;
+  }
+
+  return ERROR_INVALID_HANDLE;
+}
+
+
+/* Function 0 */
 unsigned long
 ScmrCloseServiceHandle(handle_t BindingHandle,
                        unsigned int hScObject)
@@ -193,7 +271,7 @@
 }
 
 
-/* Service 1 */
+/* Function 1 */
 #if 0
 unsigned long
 ScmrControlService(handle_t BindingHandle,
@@ -201,7 +279,7 @@
                    unsigned long dwControl,
                    LPSERVICE_STATUS lpServiceStatus)
 {
-  DPRINT("ScmrControlService() called\n");
+  DPRINT1("ScmrControlService() called\n");
 
 #if 0
   lpServiceStatus->dwServiceType = 0x12345678;
@@ -218,28 +296,104 @@
 #endif
 
 
-/* Service 2 */
+/* Function 2 */
 unsigned long
 ScmrDeleteService(handle_t BindingHandle,
                   unsigned int hService)
 {
-  DPRINT("ScmrDeleteService() called\n");
+  PSERVICE_HANDLE hSvc;
+
+  DPRINT1("ScmrDeleteService() called\n");
+
+  hSvc = (PSERVICE_HANDLE)hService;
+  if (hSvc->Handle.Tag != SERVICE_TAG)
+    return ERROR_INVALID_HANDLE;
+
+  if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+                                STANDARD_RIGHTS_REQUIRED))
+    return ERROR_ACCESS_DENIED;
+
+  /* FIXME: Delete the service */
+
   return ERROR_SUCCESS;
 }
 
 
+/* Function 3 */
 unsigned long
-ScmrOpenSCManagerA(handle_t BindingHandle,
-                   char *lpMachineName,
-                   char *lpDatabaseName,
+ScmrLockServiceDatabase(handle_t BindingHandle,
+                        unsigned int hSCManager,
+                        unsigned int *hLock)
+{
+  PMANAGER_HANDLE hMgr;
+
+  DPRINT("ScmrLockServiceDatabase() called\n");
+
+  *hLock = 0;
+
+  hMgr = (PMANAGER_HANDLE)hSCManager;
+  if (hMgr->Handle.Tag != MANAGER_TAG)
+    return ERROR_INVALID_HANDLE;
+
+  if (!RtlAreAllAccessesGranted(hMgr->Handle.DesiredAccess,
+                                SC_MANAGER_LOCK))
+    return ERROR_ACCESS_DENIED;
+
+  /* FIXME: Lock the database */
+  *hLock = 0x12345678; /* Dummy! */
+
+  return ERROR_SUCCESS;
+}
+
+
+
+/* Function 8 */
+unsigned long
+ScmrUnlockServiceDatabase(handle_t BindingHandle,
+                          unsigned int hLock)
+{
+  DPRINT1("ScmrUnlockServiceDatabase() called\n");
+  return ERROR_SUCCESS;
+}
+
+
+/* Function 9 */
+unsigned long
+ScmrNotifyBootConfigStatus(handle_t BindingHandle,
+                           unsigned long BootAcceptable)
+{
+  DPRINT1("ScmrNotifyBootConfigStatus() called\n");
+  return ERROR_SUCCESS;
+}
+
+
+
+/* Function 12 */
+unsigned long
+ScmrCreateServiceW(handle_t BindingHandle,
+                   unsigned int hSCManager,
+                   wchar_t *lpServiceName,
+                   wchar_t *lpDisplayName,
                    unsigned long dwDesiredAccess,
-                   unsigned int *hScm)
+                   unsigned long dwServiceType,
+                   unsigned long dwStartType,
+                   unsigned long dwErrorControl,
+                   wchar_t *lpBinaryPathName,
+                   wchar_t *lpLoadOrderGroup,
+                   unsigned long *lpdwTagId,
+                   wchar_t *lpDependencies,
+                   wchar_t *lpServiceStartName,
+                   wchar_t *lpPassword)
 {
-  DPRINT("ScmrOpenSCManagerA() called\n");
+  DPRINT1("ScmrCreateServiceW() called\n");
+  if (lpdwTagId != NULL)
+    *lpdwTagId = 0;
   return ERROR_SUCCESS;
 }
 
 
+
+/* Function 15 */
 unsigned long
 ScmrOpenSCManagerW(handle_t BindingHandle,
                    wchar_t *lpMachineName,
@@ -258,14 +412,23 @@
   DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
 
   dwError = ScmCreateManagerHandle(lpDatabaseName,
-                                   &hHandle,
-                                   dwDesiredAccess);
+                                   &hHandle);
   if (dwError != ERROR_SUCCESS)
   {
     DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError);
     return dwError;
   }
 
+  /* Check the desired access */
+  dwError = ScmCheckAccess(hHandle,
+                           dwDesiredAccess | SC_MANAGER_CONNECT);
+  if (dwError != ERROR_SUCCESS)
+  {
+    DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError);
+    GlobalFree(hHandle);
+    return dwError;
+  }
+
   *hScm = (unsigned int)hHandle;
   DPRINT("*hScm = %x\n", *hScm);
 
@@ -275,19 +438,8 @@
 }
 
 
+/* Function 16 */
 unsigned int
-ScmrOpenServiceA(handle_t BindingHandle,
-                 unsigned int hSCManager,
-                 char *lpServiceName,
-                 unsigned long dwDesiredAccess,
-                 unsigned int *hService)
-{
-  DPRINT("ScmrOpenServiceA() called\n");
-  return 0;
-}
-
-
-unsigned int
 ScmrOpenServiceW(handle_t BindingHandle,
                  unsigned int hSCManager,
                  wchar_t *lpServiceName,
@@ -317,14 +469,23 @@
 
   /* Create a service handle */
   dwError = ScmCreateServiceHandle(NULL,
-                                   &hHandle,
-                                   dwDesiredAccess);
+                                   &hHandle);
   if (dwError != ERROR_SUCCESS)
   {
     DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError);
     return dwError;
   }
 
+  /* Check the desired access */
+  dwError = ScmCheckAccess(hHandle,
+                           dwDesiredAccess);
+  if (dwError != ERROR_SUCCESS)
+  {
+    DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError);
+    GlobalFree(hHandle);
+    return dwError;
+  }
+
   *hService = (unsigned int)hHandle;
   DPRINT("*hService = %x\n", *hService);
 
@@ -335,6 +496,33 @@
 
 
 
+/* Function 27 */
+unsigned long
+ScmrOpenSCManagerA(handle_t BindingHandle,
+                   char *lpMachineName,
+                   char *lpDatabaseName,
+                   unsigned long dwDesiredAccess,
+                   unsigned int *hScm)
+{
+  DPRINT("ScmrOpenSCManagerA() called\n");
+  return ERROR_SUCCESS;
+}
+
+
+/* Function 28 */
+unsigned int
+ScmrOpenServiceA(handle_t BindingHandle,
+                 unsigned int hSCManager,
+                 char *lpServiceName,
+                 unsigned long dwDesiredAccess,
+                 unsigned int *hService)
+{
+  DPRINT("ScmrOpenServiceA() called\n");
+  return 0;
+}
+
+
+
 void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
 {
   return GlobalAlloc(GPTR, len);