Rob Shearman : services: Move LockServiceDatabase and UnlockServiceDatabase from advapi32. dll to services.exe.

Alexandre Julliard julliard at winehq.org
Sat Mar 29 06:57:05 CDT 2008


Module: wine
Branch: master
Commit: 7afd9a977a84e80a02109351faa8d46182504c05
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=7afd9a977a84e80a02109351faa8d46182504c05

Author: Rob Shearman <rob at codeweavers.com>
Date:   Fri Mar 28 17:06:43 2008 +0000

services: Move LockServiceDatabase and UnlockServiceDatabase from advapi32.dll to services.exe.

---

 dlls/advapi32/service.c      |   34 ++++++++++++++++++++--------
 include/wine/svcctl.idl      |   12 ++++++++++
 programs/services/rpc.c      |   50 ++++++++++++++++++++++++++++++++++++++++++
 programs/services/services.c |   14 +++++++++++
 programs/services/services.h |    3 ++
 5 files changed, 103 insertions(+), 10 deletions(-)

diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c
index 20f7af5..0b29493 100644
--- a/dlls/advapi32/service.c
+++ b/dlls/advapi32/service.c
@@ -954,21 +954,26 @@ BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent )
  */
 SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
 {
-    HANDLE ret;
+    struct sc_manager *hscm;
+    SC_RPC_LOCK hLock;
+    DWORD err;
 
     TRACE("%p\n",hSCManager);
 
-    ret = CreateSemaphoreW( NULL, 1, 1, szSCMLock );
-    if( ret && GetLastError() == ERROR_ALREADY_EXISTS )
+    hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
+    if (!hscm)
     {
-        CloseHandle( ret );
-        ret = NULL;
-        SetLastError( ERROR_SERVICE_DATABASE_LOCKED );
+        SetLastError( ERROR_INVALID_HANDLE );
+        return NULL;
     }
 
-    TRACE("returning %p\n", ret);
-
-    return ret;
+    err = svcctl_LockServiceDatabase(hscm->hdr.server_handle, &hLock);
+    if (err != ERROR_SUCCESS)
+    {
+        SetLastError(err);
+        return NULL;
+    }
+    return hLock;
 }
 
 /******************************************************************************
@@ -976,9 +981,18 @@ SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
  */
 BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock)
 {
+    DWORD err;
+    SC_RPC_LOCK hRpcLock = ScLock;
+
     TRACE("%p\n",ScLock);
 
-    return CloseHandle( ScLock );
+    err = svcctl_UnlockServiceDatabase(&hRpcLock);
+    if (err != ERROR_SUCCESS)
+    {
+        SetLastError(err);
+        return FALSE;
+    }
+    return TRUE;
 }
 
 /******************************************************************************
diff --git a/include/wine/svcctl.idl b/include/wine/svcctl.idl
index c0190e7..a629f6a 100644
--- a/include/wine/svcctl.idl
+++ b/include/wine/svcctl.idl
@@ -43,6 +43,7 @@ interface svcctl
     /* handle types */
     typedef [handle] LPCWSTR MACHINE_HANDLEW;
     typedef [context_handle] void *SC_RPC_HANDLE;
+    typedef [context_handle] void *SC_RPC_LOCK;
 
     /* undocumented access rights */
     cpp_quote("#define SERVICE_SET_STATUS   0x8000")
@@ -86,12 +87,23 @@ cpp_quote("#endif")
         [in] SC_RPC_HANDLE hService
     );
 
+    /* Compatible with Windows function 0x03 */
+    DWORD svcctl_LockServiceDatabase(
+        [in] SC_RPC_HANDLE hSCManager,
+        [out] SC_RPC_LOCK *phLock
+    );
+
     /* Compatible with Windows function 0x07 */
     DWORD svcctl_SetServiceStatus(
         [in] SC_RPC_HANDLE hServiceStatus,
         [in] LPSERVICE_STATUS lpServiceStatus
     );
 
+    /* Compatible with Windows function 0x08 */
+    DWORD svcctl_UnlockServiceDatabase(
+        [in,out] SC_RPC_LOCK *phLock
+    );
+
     /* Compatible with Windows function 0x0b */
     DWORD svcctl_ChangeServiceConfigW(
         [in] SC_RPC_HANDLE hService,
diff --git a/programs/services/rpc.c b/programs/services/rpc.c
index f780f7e..0a59ed4 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -88,6 +88,11 @@ struct sc_service       /* service handle */
     struct service_entry *service_entry;
 };
 
+struct sc_lock
+{
+    char dummy; /* no state currently used */
+};
+
 /* Check if the given handle is of the required type and allows the requested access. */
 static DWORD validate_context_handle(SC_RPC_HANDLE handle, DWORD type, DWORD needed_access, struct sc_handle **out_hdr)
 {
@@ -654,6 +659,51 @@ DWORD svcctl_CloseServiceHandle(
     return ERROR_SUCCESS;
 }
 
+static void SC_RPC_LOCK_destroy(SC_RPC_LOCK hLock)
+{
+    unlock_service_database();
+    HeapFree(GetProcessHeap(), 0, hLock);
+}
+
+void __RPC_USER SC_RPC_LOCK_rundown(SC_RPC_LOCK hLock)
+{
+    SC_RPC_LOCK_destroy(hLock);
+}
+
+DWORD svcctl_LockServiceDatabase(
+    SC_RPC_HANDLE hSCManager,
+    SC_RPC_LOCK *phLock)
+{
+    struct sc_manager *manager;
+    DWORD err;
+
+    WINE_TRACE("(%p, %p)\n", hSCManager, phLock);
+
+    if ((err = validate_scm_handle(hSCManager, SC_MANAGER_LOCK, &manager)) != ERROR_SUCCESS)
+        return err;
+
+    err = lock_service_database();
+    if (err != ERROR_SUCCESS)
+        return err;
+
+    *phLock = HeapAlloc(GetProcessHeap(), 0, sizeof(struct sc_lock));
+    if (!*phLock)
+        return ERROR_NOT_ENOUGH_SERVER_MEMORY;
+
+    return ERROR_SUCCESS;
+}
+
+DWORD svcctl_UnlockServiceDatabase(
+    SC_RPC_LOCK *phLock)
+{
+    WINE_TRACE("(&%p)\n", *phLock);
+
+    SC_RPC_LOCK_destroy(*phLock);
+    *phLock = NULL;
+
+    return ERROR_SUCCESS;
+}
+
 DWORD RPC_MainLoop(void)
 {
     WCHAR transport[] = SVCCTL_TRANSPORT;
diff --git a/programs/services/services.c b/programs/services/services.c
index 2e22469..1962dc9 100644
--- a/programs/services/services.c
+++ b/programs/services/services.c
@@ -274,6 +274,20 @@ BOOL validate_service_config(struct service_entry *entry)
     return TRUE;
 }
 
+static LONG service_lock = FALSE;
+
+DWORD lock_service_database(void)
+{
+    if (InterlockedCompareExchange(&service_lock, TRUE, FALSE))
+        return ERROR_SERVICE_DATABASE_LOCKED;
+    return ERROR_SUCCESS;
+}
+
+void unlock_service_database(void)
+{
+    InterlockedCompareExchange(&service_lock, FALSE, TRUE);
+}
+
 void lock_services(void)
 {
     EnterCriticalSection(&services_list_cs);
diff --git a/programs/services/services.h b/programs/services/services.h
index 30b120e..4c7c656 100644
--- a/programs/services/services.h
+++ b/programs/services/services.h
@@ -45,6 +45,9 @@ DWORD save_service_config(struct service_entry *entry);
 void free_service_entry(struct service_entry *entry);
 void release_service(struct service_entry *service);
 
+DWORD lock_service_database(void);
+void unlock_service_database(void);
+
 void lock_services(void);
 void unlock_services(void);
 




More information about the wine-cvs mailing list