services: Move QueryServiceConfigW from advapi32.dll to services.exe.

Mikołaj Zalewski mikolaj at zalewski.pl
Sat Mar 15 10:42:40 CDT 2008


---
 dlls/advapi32/service.c |  209 ++++++++++++-----------------------------------
 include/wine/svcctl.idl |   22 +++++
 programs/services/rpc.c |   27 ++++++
 3 files changed, 103 insertions(+), 155 deletions(-)

diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c
index a22c309..acb1e66 100644
--- a/dlls/advapi32/service.c
+++ b/dlls/advapi32/service.c
@@ -1849,6 +1849,29 @@ done:
     return ret;
 }
 
+static DWORD move_string_to_buffer(BYTE **buf, LPWSTR *string_ptr)
+{
+    DWORD cb;
+    WCHAR empty_str[] = {0};
+
+    if (!*string_ptr)
+        *string_ptr = empty_str;
+
+    cb = (strlenW(*string_ptr) + 1)*sizeof(WCHAR);
+
+    memcpy(*buf, *string_ptr, cb);
+    MIDL_user_free(*string_ptr);
+    *string_ptr = (LPWSTR)*buf;
+    *buf += cb;
+
+    return cb;
+}
+
+static DWORD size_string(LPWSTR string)
+{
+    return (string ? (strlenW(string) + 1)*sizeof(WCHAR) : sizeof(WCHAR));
+}
+
 /******************************************************************************
  * QueryServiceConfigW [ADVAPI32.@]
  */
@@ -1857,12 +1880,11 @@ QueryServiceConfigW( SC_HANDLE hService,
                      LPQUERY_SERVICE_CONFIGW lpServiceConfig,
                      DWORD cbBufSize, LPDWORD pcbBytesNeeded)
 {
-    WCHAR str_buffer[ MAX_PATH ];
-    LONG r;
-    DWORD type, val, sz, total, n;
-    LPBYTE p;
-    HKEY hKey;
+    QUERY_SERVICE_CONFIGW config;
     struct sc_service *hsvc;
+    DWORD total;
+    DWORD err;
+    BYTE *bufpos;
 
     TRACE("%p %p %d %p\n", hService, lpServiceConfig,
            cbBufSize, pcbBytesNeeded);
@@ -1873,58 +1895,23 @@ QueryServiceConfigW( SC_HANDLE hService,
         SetLastError( ERROR_INVALID_HANDLE );
         return FALSE;
     }
-    hKey = hsvc->hkey;
-
-    /* TODO: Check which members are mandatory and what the registry types
-     * should be. This should of course also be tested when a service is
-     * created.
-     */
-
-    /* calculate the size required first */
-    total = sizeof (QUERY_SERVICE_CONFIGW);
 
-    sz = sizeof(str_buffer);
-    r = RegQueryValueExW( hKey, szImagePath, 0, &type, (LPBYTE) str_buffer, &sz );
-    if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ || type == REG_EXPAND_SZ ) )
-    {
-        sz = ExpandEnvironmentStringsW(str_buffer,NULL,0);
-        if( 0 == sz ) return FALSE;
+    memset(&config, 0, sizeof(config));
 
-        total += sizeof(WCHAR) * sz;
-    }
-    else
+    if ((err = svcctl_QueryServiceConfigW(hsvc->hdr.server_handle, &config)) != 0)
     {
-       /* FIXME: set last error */
-       return FALSE;
+        TRACE("services.exe: error %u\n", err);
+        SetLastError(err);
+        return FALSE;
     }
 
-    sz = 0;
-    r = RegQueryValueExW( hKey, szGroup, 0, &type, NULL, &sz );
-    if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
-        total += sz;
-    else
-	total += sizeof(WCHAR);
-
-    sz = 0;
-    r = RegQueryValueExW( hKey, szDependencies, 0, &type, NULL, &sz );
-    if( ( r == ERROR_SUCCESS ) && ( type == REG_MULTI_SZ ) )
-        total += sz;
-    else
-	total += sizeof(WCHAR);
-
-    sz = 0;
-    r = RegQueryValueExW( hKey, szObjectName, 0, &type, NULL, &sz );
-    if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
-        total += sz;
-    else
-	total += sizeof(WCHAR);
-
-    sz = 0;
-    r = RegQueryValueExW( hKey, szDisplayName, 0, &type, NULL, &sz );
-    if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
-        total += sz;
-    else
-	total += sizeof(WCHAR);
+    /* calculate the size required first */
+    total = sizeof (QUERY_SERVICE_CONFIGW);
+    total += size_string(config.lpBinaryPathName);
+    total += size_string(config.lpLoadOrderGroup);
+    total += size_string(config.lpDependencies);
+    total += size_string(config.lpServiceStartName);
+    total += size_string(config.lpDisplayName);
 
     *pcbBytesNeeded = total;
 
@@ -1932,112 +1919,24 @@ QueryServiceConfigW( SC_HANDLE hService,
     if( total > cbBufSize )
     {
         SetLastError( ERROR_INSUFFICIENT_BUFFER );
+        MIDL_user_free(config.lpBinaryPathName);
+        MIDL_user_free(config.lpLoadOrderGroup);
+        MIDL_user_free(config.lpDependencies);
+        MIDL_user_free(config.lpServiceStartName);
+        MIDL_user_free(config.lpDisplayName);
         return FALSE;
     }
 
-    ZeroMemory( lpServiceConfig, total );
-
-    sz = sizeof val;
-    r = RegQueryValueExW( hKey, szType, 0, &type, (LPBYTE)&val, &sz );
-    if( ( r == ERROR_SUCCESS ) && ( type == REG_DWORD ) )
-        lpServiceConfig->dwServiceType = val;
-
-    sz = sizeof val;
-    r = RegQueryValueExW( hKey, szStart, 0, &type, (LPBYTE)&val, &sz );
-    if( ( r == ERROR_SUCCESS ) && ( type == REG_DWORD ) )
-        lpServiceConfig->dwStartType = val;
-
-    sz = sizeof val;
-    r = RegQueryValueExW( hKey, szError, 0, &type, (LPBYTE)&val, &sz );
-    if( ( r == ERROR_SUCCESS ) && ( type == REG_DWORD ) )
-        lpServiceConfig->dwErrorControl = val;
-
-    sz = sizeof val;
-    r = RegQueryValueExW( hKey, szTag, 0, &type, (LPBYTE)&val, &sz );
-    if( ( r == ERROR_SUCCESS ) && ( type == REG_DWORD ) )
-        lpServiceConfig->dwTagId = val;
-
-    /* now do the strings */
-    p = (LPBYTE) &lpServiceConfig[1];
-    n = total - sizeof (QUERY_SERVICE_CONFIGW);
-
-    sz = sizeof(str_buffer);
-    r = RegQueryValueExW( hKey, szImagePath, 0, &type, (LPBYTE) str_buffer, &sz );
-    if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ || type == REG_EXPAND_SZ ) )
-    {
-        sz = ExpandEnvironmentStringsW(str_buffer, (LPWSTR) p, n);
-        sz *= sizeof(WCHAR);
-        if( 0 == sz || sz > n ) return FALSE;
-
-        lpServiceConfig->lpBinaryPathName = (LPWSTR) p;
-        p += sz;
-        n -= sz;
-    }
-    else
-    {
-       /* FIXME: set last error */
-       return FALSE;
-    }
-
-    sz = n;
-    r = RegQueryValueExW( hKey, szGroup, 0, &type, p, &sz );
-    lpServiceConfig->lpLoadOrderGroup = (LPWSTR) p;
-    if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
-    {
-        p += sz;
-        n -= sz;
-    }
-    else
-    {
-	*(WCHAR *) p = 0;
-	p += sizeof(WCHAR);
-	n -= sizeof(WCHAR);
-    }
-
-    sz = n;
-    r = RegQueryValueExW( hKey, szDependencies, 0, &type, p, &sz );
-    lpServiceConfig->lpDependencies = (LPWSTR) p;
-    if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
-    {
-        p += sz;
-        n -= sz;
-    }
-    else
-    {
-	*(WCHAR *) p = 0;
-	p += sizeof(WCHAR);
-	n -= sizeof(WCHAR);
-    }
-
-    sz = n;
-    r = RegQueryValueExW( hKey, szObjectName, 0, &type, p, &sz );
-    lpServiceConfig->lpServiceStartName = (LPWSTR) p;
-    if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
-    {
-        p += sz;
-        n -= sz;
-    }
-    else
-    {
-        *(WCHAR *) p = 0;
-        p += sizeof(WCHAR);
-        n -= sizeof(WCHAR);
-    }
-
-    sz = n;
-    r = RegQueryValueExW( hKey, szDisplayName, 0, &type, p, &sz );
-    lpServiceConfig->lpDisplayName = (LPWSTR) p;
-    if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
-    {
-        p += sz;
-        n -= sz;
-    }
-    else
-    {
-        *(WCHAR *) p = 0;
-        p += sizeof(WCHAR);
-        n -= sizeof(WCHAR);
-    }
+    *lpServiceConfig = config;
+    bufpos = ((BYTE *)lpServiceConfig) + sizeof(QUERY_SERVICE_CONFIGW);
+    move_string_to_buffer(&bufpos, &lpServiceConfig->lpBinaryPathName);
+    move_string_to_buffer(&bufpos, &lpServiceConfig->lpLoadOrderGroup);
+    move_string_to_buffer(&bufpos, &lpServiceConfig->lpDependencies);
+    move_string_to_buffer(&bufpos, &lpServiceConfig->lpServiceStartName);
+    move_string_to_buffer(&bufpos, &lpServiceConfig->lpDisplayName);
+  
+    if (bufpos - (LPBYTE)lpServiceConfig > cbBufSize)
+        ERR("Buffer overflow!\n");
 
     TRACE("Image path           = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
     TRACE("Group                = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
diff --git a/include/wine/svcctl.idl b/include/wine/svcctl.idl
index d4e7081..ab189c3 100644
--- a/include/wine/svcctl.idl
+++ b/include/wine/svcctl.idl
@@ -24,6 +24,7 @@ import "wtypes.idl";
 /* 
  * some defined for the C code
  */
+cpp_quote("#include \"winsvc.h\"")
 cpp_quote("#define SVCCTL_TRANSPORT {'n','c','a','c','n','_','n','p',0}")
 cpp_quote("#define SVCCTL_ENDPOINT {'\\\\','p','i','p','e','\\\\','s','v','c','c','t','l',0}")
 
@@ -43,6 +44,21 @@ interface svcctl
     typedef [handle] LPCWSTR MACHINE_HANDLEW;
     typedef [context_handle] void *SC_RPC_HANDLE;
 
+cpp_quote("#if 0 /* already defined in winsvc.h */")
+typedef struct _QUERY_SERVICE_CONFIGW {
+    DWORD   dwServiceType;
+    DWORD   dwStartType;
+    DWORD   dwErrorControl;
+    [unique] LPWSTR  lpBinaryPathName;
+    [unique] LPWSTR  lpLoadOrderGroup;
+    DWORD   dwTagId;
+    [unique] LPWSTR  lpDependencies;
+    [unique] LPWSTR  lpServiceStartName;
+    [unique] LPWSTR  lpDisplayName;
+} QUERY_SERVICE_CONFIGW, *LPQUERY_SERVICE_CONFIGW;
+cpp_quote("#endif")
+
+
     /* Compatible with Windows function 0x00 */
     DWORD svcctl_CloseServiceHandle(
         [in,out] SC_RPC_HANDLE *handle
@@ -88,4 +104,10 @@ interface svcctl
         [in] DWORD dwDesiredAccess,
         [out] SC_RPC_HANDLE *phService
     );
+
+    /* Windows function 0x11 must be using a different prototype - not compatible */
+    DWORD svcctl_QueryServiceConfigW(
+        [in] SC_RPC_HANDLE hService,
+        [out] QUERY_SERVICE_CONFIGW *config);
+
 }
diff --git a/programs/services/rpc.c b/programs/services/rpc.c
index 8ef1e92..ca56a34 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -343,6 +343,33 @@ DWORD svcctl_DeleteService(
     return err;
 }
 
+DWORD svcctl_QueryServiceConfigW(
+        SC_RPC_HANDLE hService,
+        QUERY_SERVICE_CONFIGW *config)
+{
+    struct sc_service *service;
+    DWORD err;
+
+    WINE_TRACE("(%p)\n", config);
+
+    if ((err = validate_service_handle(hService, SERVICE_QUERY_CONFIG, &service)) != 0)
+        return err;
+
+    lock_services();
+    config->dwServiceType = service->service_entry->config.dwServiceType;
+    config->dwStartType = service->service_entry->config.dwStartType;
+    config->dwErrorControl = service->service_entry->config.dwErrorControl;
+    config->lpBinaryPathName = strdupW(service->service_entry->config.lpBinaryPathName);
+    config->lpLoadOrderGroup = strdupW(service->service_entry->config.lpLoadOrderGroup);
+    config->dwTagId = service->service_entry->config.dwTagId;
+    config->lpDependencies = NULL; /* TODO */
+    config->lpServiceStartName = strdupW(service->service_entry->config.lpServiceStartName);
+    config->lpDisplayName = strdupW(service->service_entry->config.lpDisplayName);
+    unlock_services();
+
+    return ERROR_SUCCESS;
+}
+
 DWORD svcctl_CloseServiceHandle(
     SC_RPC_HANDLE *handle)
 {
-- 
1.5.3.GIT



--------------020702060306030905040607--



More information about the wine-patches mailing list