SC_HANDLEs are changed from HKEYs to pointers to internal structures

Alexander Yaworsky yaworsky at migusoft.ru
Fri Aug 27 04:38:45 CDT 2004


Hello

The reason is the necessity to tie service name with handle returned
by OpenService or CreateService. When some global objects
will be introduced, the service name will be a part of their names.
So ControlService and QueryServiceStatus should be able to obtain
service name by handle.
Currently the only benefit is simplification of DeleteService.

ChangeLog:

SC_HANDLEs are changed from HKEYs to pointers to internal structures.

Index: dlls/advapi32/service.c
===================================================================
RCS file: /home/wine/wine/dlls/advapi32/service.c,v
retrieving revision 1.47
diff -u -r1.47 service.c
--- dlls/advapi32/service.c 26 Aug 2004 18:10:01 -0000 1.47
+++ dlls/advapi32/service.c 27 Aug 2004 09:22:45 -0000
@@ -44,6 +44,110 @@
       'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
       'S','e','r','v','i','c','e','s','\\',0 };
 
+/******************************************************************************
+ * SC_HANDLEs
+ */
+
+#define MAX_SERVICE_NAME 256
+
+typedef enum { SC_HTYPE_MANAGER, SC_HTYPE_SERVICE } SC_HANDLE_TYPE;
+
+struct sc_handle;
+
+struct sc_manager       /* SCM handle */
+{
+    HKEY hkey_scm_db;   /* handle to services database in the registry */
+    LONG ref_count;     /* handle must remain alive until any related service */
+                        /* handle exists because DeleteService requires it */
+};
+
+struct sc_service       /* service handle */
+{
+    HKEY hkey;          /* handle to service entry in the registry (under hkey_scm_db) */
+    struct sc_handle *sc_manager;  /* pointer to SCM handle */
+    WCHAR name[ MAX_SERVICE_NAME ];
+};
+
+struct sc_handle
+{
+    SC_HANDLE_TYPE htype;
+    union
+    {
+        struct sc_manager manager;
+        struct sc_service service;
+    } u;
+};
+
+static struct sc_handle* alloc_sc_handle( SC_HANDLE_TYPE htype )
+{
+    struct sc_handle *retval;
+
+    retval = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct sc_handle) );
+    if( retval != NULL )
+    {
+        retval->htype = htype;
+    }
+    TRACE("SC_HANDLE type=%d -> %p\n",htype,retval);
+    return retval;
+}
+
+static void free_sc_handle( struct sc_handle* handle )
+{
+    switch( handle->htype )
+    {
+        case SC_HTYPE_MANAGER:
+        {
+            if( InterlockedDecrement( &handle->u.manager.ref_count ) )
+                /* there are references to this handle */
+                return;
+
+            if( handle->u.manager.hkey_scm_db )
+                RegCloseKey( handle->u.manager.hkey_scm_db );
+            break;
+        }
+
+        case SC_HTYPE_SERVICE:
+        {
+            struct sc_handle *h = handle->u.service.sc_manager;
+
+            if( h )
+            {
+                /* release SCM handle */
+                if( 0 == InterlockedDecrement( &h->u.manager.ref_count ) )
+                {
+                    /* it's time to destroy SCM handle */
+                    if( h->u.manager.hkey_scm_db )
+                        RegCloseKey( h->u.manager.hkey_scm_db );
+                    
+                    TRACE("SC_HANDLE (SCM) %p type=%d\n",h,h->htype);
+                    
+                    HeapFree( GetProcessHeap(), 0, h );
+                }
+            }
+            if( handle->u.service.hkey )
+                RegCloseKey( handle->u.service.hkey );
+            break;
+        }
+    }
+
+    TRACE("SC_HANDLE %p type=%d\n",handle,handle->htype);
+
+    HeapFree( GetProcessHeap(), 0, handle );
+}
+
+static void init_service_handle( struct sc_handle* handle,
+                                 struct sc_handle* sc_manager,
+                                 HKEY hKey, LPCWSTR lpServiceName )
+{
+    /* init sc_service structure */
+    handle->u.service.hkey = hKey;
+    strncpyW( handle->u.service.name, lpServiceName, MAX_SERVICE_NAME-1 );
+    handle->u.service.name[ MAX_SERVICE_NAME-1 ] = 0;
+
+    /* add reference to SCM handle */
+    InterlockedIncrement( &sc_manager->u.manager.ref_count );
+    handle->u.service.sc_manager = sc_manager;
+}
 
 /******************************************************************************
  * EnumServicesStatusA [ADVAPI32.@]
@@ -274,7 +378,8 @@
 SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
                                  DWORD dwDesiredAccess )
 {
-    HKEY hReg, hKey = NULL;
+    struct sc_handle *retval;
+    HKEY hReg;
     LONG r;
 
     TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
@@ -286,16 +391,28 @@
      * docs, but what if it isn't?
      */
 
+    retval = alloc_sc_handle( SC_HTYPE_MANAGER );
+    if( NULL == retval ) return NULL;
+
+    retval->u.manager.ref_count = 1;
+
     r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg);
-    if (r==ERROR_SUCCESS)
-    {
-        r = RegOpenKeyExW(hReg, szServiceManagerKey,0, dwDesiredAccess, &hKey );
-        RegCloseKey( hReg );
-    }
+    if (r!=ERROR_SUCCESS)
+        goto error;
+
+    r = RegOpenKeyExW(hReg, szServiceManagerKey,
+                      0, KEY_ALL_ACCESS, &retval->u.manager.hkey_scm_db);
+    RegCloseKey( hReg );
+    if (r!=ERROR_SUCCESS)
+        goto error;
+
+    TRACE("returning %p\n", retval);
 
-    TRACE("returning %p\n", hKey);
+    return (SC_HANDLE) retval;
 
-    return hKey;
+error:
+    free_sc_handle( retval );
+    return NULL;
 }
 
 
@@ -353,7 +470,7 @@
 {
     TRACE("(%p)\n", hSCObject);
 
-    RegCloseKey(hSCObject);
+    free_sc_handle( (struct sc_handle*) hSCObject );
 
     return TRUE;
 }
@@ -397,19 +514,31 @@
 SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
                                DWORD dwDesiredAccess)
 {
+    struct sc_handle *hscm = hSCManager;
+    struct sc_handle *retval;
     HKEY hKey;
     long r;
 
     TRACE("(%p,%p,%ld)\n",hSCManager, lpServiceName,
           dwDesiredAccess);
 
-    r = RegOpenKeyExW(hSCManager, lpServiceName, 0, KEY_ALL_ACCESS, &hKey );
+    retval = alloc_sc_handle( SC_HTYPE_SERVICE );
+    if( NULL == retval )
+        return NULL;
+
+    r = RegOpenKeyExW( hscm->u.manager.hkey_scm_db,
+                       lpServiceName, 0, KEY_ALL_ACCESS, &hKey );
     if (r!=ERROR_SUCCESS)
-        return 0;
+    {
+        free_sc_handle( retval );
+        return NULL;
+    }
+    
+    init_service_handle( retval, hscm, hKey, lpServiceName );
 
-    TRACE("returning %p\n",hKey);
+    TRACE("returning %p\n",retval);
 
-    return hKey;
+    return (SC_HANDLE) retval;
 }
 
 /******************************************************************************
@@ -424,6 +553,8 @@
                   LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
                   LPCWSTR lpPassword )
 {
+    struct sc_handle *hscm = hSCManager;
+    struct sc_handle *retval;
     HKEY hKey;
     LONG r;
     DWORD dp;
@@ -438,41 +569,47 @@
     FIXME("%p %s %s\n", hSCManager, 
           debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
 
-    r = RegCreateKeyExW(hSCManager, lpServiceName, 0, NULL,
+    retval = alloc_sc_handle( SC_HTYPE_SERVICE );
+    if( NULL == retval )
+        return NULL;
+
+    r = RegCreateKeyExW(hscm->u.manager.hkey_scm_db, lpServiceName, 0, NULL,
                        REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dp);
     if (r!=ERROR_SUCCESS)
-        return 0;
+        goto error;
+
+    init_service_handle( retval, hscm, hKey, lpServiceName );
 
     if (dp != REG_CREATED_NEW_KEY)
-        return 0;
+        goto error;
 
     if(lpDisplayName)
     {
         r = RegSetValueExW(hKey, szDisplayName, 0, REG_SZ, (LPBYTE)lpDisplayName,
                            (strlenW(lpDisplayName)+1)*sizeof(WCHAR) );
         if (r!=ERROR_SUCCESS)
-            return 0;
+            goto error;
     }
 
     r = RegSetValueExW(hKey, szType, 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
     if (r!=ERROR_SUCCESS)
-        return 0;
+        goto error;
 
     r = RegSetValueExW(hKey, szStart, 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
     if (r!=ERROR_SUCCESS)
-        return 0;
+        goto error;
 
     r = RegSetValueExW(hKey, szError, 0, REG_DWORD,
                            (LPVOID)&dwErrorControl, sizeof (DWORD) );
     if (r!=ERROR_SUCCESS)
-        return 0;
+        goto error;
 
     if(lpBinaryPathName)
     {
         r = RegSetValueExW(hKey, szImagePath, 0, REG_SZ, (LPBYTE)lpBinaryPathName,
                            (strlenW(lpBinaryPathName)+1)*sizeof(WCHAR) );
         if (r!=ERROR_SUCCESS)
-            return 0;
+            goto error;
     }
 
     if(lpLoadOrderGroup)
@@ -480,7 +617,7 @@
         r = RegSetValueExW(hKey, szGroup, 0, REG_SZ, (LPBYTE)lpLoadOrderGroup,
                            (strlenW(lpLoadOrderGroup)+1)*sizeof(WCHAR) );
         if (r!=ERROR_SUCCESS)
-            return 0;
+            goto error;
     }
 
     if(lpDependencies)
@@ -495,7 +632,7 @@
         r = RegSetValueExW(hKey, szDependencies, 0, REG_MULTI_SZ,
                            (LPBYTE)lpDependencies, len );
         if (r!=ERROR_SUCCESS)
-            return 0;
+            goto error;
     }
 
     if(lpPassword)
@@ -508,7 +645,11 @@
         FIXME("Don't know how to add a ServiceStartName for a service.\n");
     }
 
-    return hKey;
+    return (SC_HANDLE) retval;
+    
+error:
+    free_sc_handle( retval );
+    return NULL;
 }
 
 
@@ -607,63 +748,30 @@
  */
 BOOL WINAPI DeleteService( SC_HANDLE hService )
 {
+    struct sc_handle *hsvc = hService;
+    HKEY hKey = hsvc->u.service.hkey;
     WCHAR valname[MAX_PATH+1];
     INT index = 0;
     LONG rc;
-    DWORD value = 0x1;
     DWORD size;
-    HKEY hKey;
-
-    static const WCHAR szDeleted[] = {'D','e','l','e','t','e','d',0};
 
-    FIXME("(%p): stub\n",hService);
-   
     size = MAX_PATH+1; 
     /* Clean out the values */
-    rc = RegEnumValueW(hService, index, valname,&size,0,0,0,0);
+    rc = RegEnumValueW(hKey, index, valname,&size,0,0,0,0);
     while (rc == ERROR_SUCCESS)
     {
-        RegDeleteValueW(hService,valname);
+        RegDeleteValueW(hKey,valname);
         index++;
         size = MAX_PATH+1; 
-        rc = RegEnumValueW(hService, index, valname, &size,0,0,0,0);
+        rc = RegEnumValueW(hKey, index, valname, &size,0,0,0,0);
     }
 
-    /* tag for deletion */
-    RegSetValueExW(hService, szDeleted, 0, REG_DWORD, (LPVOID)&value, 
-                    sizeof (DWORD) );
-
-    RegCloseKey(hService);
-
-    /* find and delete the key */
-    rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szServiceManagerKey,0,
-                        KEY_ALL_ACCESS, &hKey );
-    index = 0;
-    size = MAX_PATH+1; 
-    rc = RegEnumKeyExW(hKey,0, valname, &size, 0, 0, 0, 0);
-    while (rc == ERROR_SUCCESS)
-    {
-        HKEY checking;
-        rc = RegOpenKeyExW(hKey,valname,0,KEY_ALL_ACCESS,&checking);
-        if (rc == ERROR_SUCCESS)
-        {
-            DWORD deleted = 0;
-            DWORD size = sizeof(DWORD);
-            rc = RegQueryValueExW(checking, szDeleted , NULL, NULL,
-                                  (LPVOID)&deleted, &size);
-            if (deleted)
-            {
-                RegDeleteValueW(checking,szDeleted);
-                RegDeleteKeyW(hKey,valname);
-            }
-            else
-                index ++;
-            RegCloseKey(checking);
-        }
-        size = MAX_PATH+1; 
-        rc = RegEnumKeyExW(hKey, index, valname, &size, 0, 0, 0, 0);
-    }
     RegCloseKey(hKey);
+    hsvc->u.service.hkey = NULL;
+
+    /* delete the key */
+    RegDeleteKeyW(hsvc->u.service.sc_manager->u.manager.hkey_scm_db,
+                  hsvc->u.service.name);
 
     return TRUE;
 }
@@ -741,6 +849,7 @@
                                                 'c','e','S','t','a','r','t',0};
     static const WCHAR  _ImagePathW[]  = {'I','m','a','g','e','P','a','t','h',0};
                                                 
+    struct sc_handle *hsvc = hService;
     WCHAR path[MAX_PATH],str[MAX_PATH];
     DWORD type,size;
     long r;
@@ -751,7 +860,7 @@
           lpServiceArgVectors);
 
     size = sizeof(str);
-    r = RegQueryValueExW(hService, _ImagePathW, NULL, &type, (LPVOID)str, &size);
+    r = RegQueryValueExW(hsvc->u.service.hkey, _ImagePathW, NULL, &type, (LPVOID)str, &size);
     if (r!=ERROR_SUCCESS)
         return FALSE;
     ExpandEnvironmentStringsW(str,path,sizeof(path));
@@ -831,6 +940,7 @@
 BOOL WINAPI
 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
 {
+    struct sc_handle *hsvc = hService;
     LONG r;
     DWORD type, val, size;
 
@@ -838,7 +948,7 @@
 
     /* read the service type from the registry */
     size = sizeof(val);
-    r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
+    r = RegQueryValueExA(hsvc->u.service.hkey, "Type", NULL, &type, (LPBYTE)&val, &size);
     if(type!=REG_DWORD)
     {
         ERR("invalid Type\n");
@@ -913,6 +1023,7 @@
     static const WCHAR szGroup[] = {'G','r','o','u','p',0};
     static const WCHAR szDependencies[] = {
         'D','e','p','e','n','d','e','n','c','i','e','s',0};
+    HKEY hKey = ((struct sc_handle*) hService)->u.service.hkey;
     LONG r;
     DWORD type, val, sz, total, n;
     LPBYTE p;
@@ -924,27 +1035,27 @@
     total = sizeof (QUERY_SERVICE_CONFIGW);
 
     sz = 0;
-    r = RegQueryValueExW( hService, szImagePath, 0, &type, NULL, &sz );
+    r = RegQueryValueExW( hKey, szImagePath, 0, &type, NULL, &sz );
     if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
         total += sz;
 
     sz = 0;
-    r = RegQueryValueExW( hService, szGroup, 0, &type, NULL, &sz );
+    r = RegQueryValueExW( hKey, szGroup, 0, &type, NULL, &sz );
     if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
         total += sz;
 
     sz = 0;
-    r = RegQueryValueExW( hService, szDependencies, 0, &type, NULL, &sz );
+    r = RegQueryValueExW( hKey, szDependencies, 0, &type, NULL, &sz );
     if( ( r == ERROR_SUCCESS ) && ( type == REG_MULTI_SZ ) )
         total += sz;
 
     sz = 0;
-    r = RegQueryValueExW( hService, szStart, 0, &type, NULL, &sz );
+    r = RegQueryValueExW( hKey, szStart, 0, &type, NULL, &sz );
     if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
         total += sz;
 
     sz = 0;
-    r = RegQueryValueExW( hService, szDisplayName, 0, &type, NULL, &sz );
+    r = RegQueryValueExW( hKey, szDisplayName, 0, &type, NULL, &sz );
     if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
         total += sz;
 
@@ -960,17 +1071,17 @@
     ZeroMemory( lpServiceConfig, total );
 
     sz = sizeof val;
-    r = RegQueryValueExW( hService, szType, 0, &type, (LPBYTE)&val, &sz );
+    r = RegQueryValueExW( hKey, szType, 0, &type, (LPBYTE)&val, &sz );
     if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
         lpServiceConfig->dwServiceType = val;
 
     sz = sizeof val;
-    r = RegQueryValueExW( hService, szStart, 0, &type, (LPBYTE)&val, &sz );
+    r = RegQueryValueExW( hKey, szStart, 0, &type, (LPBYTE)&val, &sz );
     if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
         lpServiceConfig->dwStartType = val;
 
     sz = sizeof val;
-    r = RegQueryValueExW( hService, szError, 0, &type, (LPBYTE)&val, &sz );
+    r = RegQueryValueExW( hKey, szError, 0, &type, (LPBYTE)&val, &sz );
     if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
         lpServiceConfig->dwErrorControl = val;
 
@@ -979,7 +1090,7 @@
     n = total - sizeof (QUERY_SERVICE_CONFIGW);
 
     sz = n;
-    r = RegQueryValueExW( hService, szImagePath, 0, &type, p, &sz );
+    r = RegQueryValueExW( hKey, szImagePath, 0, &type, p, &sz );
     if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
     {
         lpServiceConfig->lpBinaryPathName = (LPWSTR) p;
@@ -988,7 +1099,7 @@
     }
 
     sz = n;
-    r = RegQueryValueExW( hService, szGroup, 0, &type, p, &sz );
+    r = RegQueryValueExW( hKey, szGroup, 0, &type, p, &sz );
     if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
     {
         lpServiceConfig->lpLoadOrderGroup = (LPWSTR) p;
@@ -997,7 +1108,7 @@
     }
 
     sz = n;
-    r = RegQueryValueExW( hService, szDependencies, 0, &type, p, &sz );
+    r = RegQueryValueExW( hKey, szDependencies, 0, &type, p, &sz );
     if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
     {
         lpServiceConfig->lpDependencies = (LPWSTR) p;
@@ -1062,6 +1173,8 @@
 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel, 
     LPVOID lpInfo)
 {
+    HKEY hKey = ((struct sc_handle*) hService)->u.service.hkey;
+
     if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
     {
         static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
@@ -1070,9 +1183,9 @@
         {
             TRACE("Setting Description to %s\n",debugstr_w(sd->lpDescription));
             if (sd->lpDescription[0] == 0)
-                RegDeleteValueW(hService,szDescription);
+                RegDeleteValueW(hKey,szDescription);
             else
-                RegSetValueExW(hService, szDescription, 0, REG_SZ,
+                RegSetValueExW(hKey, szDescription, 0, REG_SZ,
                                         (LPVOID)sd->lpDescription,
                                  sizeof(WCHAR)*(strlenW(sd->lpDescription)+1));
         }




More information about the wine-patches mailing list