[PATCH] services.exe/advapi32: Move QueryServiceConfig 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 |   26 ++++++
 programs/services/rpc.c |   26 ++++++
 3 files changed, 105 insertions(+), 156 deletions(-)

diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c
index 52a3f1c..b9892c1 100644
--- a/dlls/advapi32/service.c
+++ b/dlls/advapi32/service.c
@@ -1862,6 +1862,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.@]
  */
@@ -1870,12 +1893,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);
@@ -1886,58 +1908,21 @@ 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 ) )
+    if ((err = svcctl_QueryServiceConfigW(hsvc->hdr.rpc_handle, &hsvc->hdr.server_handle, &config)) != 0)
     {
-        sz = ExpandEnvironmentStringsW(str_buffer,NULL,0);
-        if( 0 == sz ) return FALSE;
-
-        total += sizeof(WCHAR) * sz;
-    }
-    else
-    {
-       /* 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;
 
@@ -1945,112 +1930,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 f25d4a3..f7ce1d9 100644
--- a/include/wine/svcctl.idl
+++ b/include/wine/svcctl.idl
@@ -24,6 +24,8 @@ 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}");
 
@@ -50,6 +52,21 @@ cpp_quote("#define SVCCTL_STARTED_EVENT (const WCHAR[]){'_','_','w','i','n','e',
 	GUID uuid;
     } POLICY_HANDLE;
 
+cpp_quote("#if 0 /* already defined in winsvc.h */")
+typedef struct _QUERY_SERVICE_CONFIGW {
+    DWORD   dwServiceType;
+    DWORD   dwStartType;
+    DWORD   dwErrorControl;
+    [unique,string] LPWSTR  lpBinaryPathName;
+    [unique,string] LPWSTR  lpLoadOrderGroup;
+    DWORD   dwTagId;
+    [unique,string] LPWSTR  lpDependencies;
+    [unique,string] LPWSTR  lpServiceStartName;
+    [unique,string] LPWSTR  lpDisplayName;
+} QUERY_SERVICE_CONFIGW, *LPQUERY_SERVICE_CONFIGW;
+cpp_quote("#endif")
+
+
     /* Compatible with Windows function 0x00 */
     DWORD svcctl_CloseServiceHandle(
         [in] SvcCtlRpcHandle rpc_handle,
@@ -100,4 +117,13 @@ cpp_quote("#define SVCCTL_STARTED_EVENT (const WCHAR[]){'_','_','w','i','n','e',
         [in] DWORD dwDesiredAccess,
         [out] POLICY_HANDLE *phService
     );
+
+    /* Windows function 0x11 must be using a different prototype - not compatible */
+    /* Robert Shearman thinks there should be a byte_count attribute but (as of Sep 2007)
+     * this isn't supported by widl nor by rpcrt4 */
+    DWORD svcctl_QueryServiceConfigW(
+        SvcCtlRpcHandle rpc_handle,
+        [in] POLICY_HANDLE *handle,
+        [out] QUERY_SERVICE_CONFIGW *config);
+
 }
diff --git a/programs/services/rpc.c b/programs/services/rpc.c
index af5c346..1fe474f 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -362,6 +362,32 @@ DWORD svcctl_DeleteService(
     return err;
 }
 
+DWORD svcctl_QueryServiceConfigW(
+        SvcCtlRpcHandle rpc_handle,
+        POLICY_HANDLE *hService,
+        QUERY_SERVICE_CONFIGW *config)
+{
+    service_entry *service;
+    DWORD err;
+
+    WINE_TRACE("conn=%p (%s)\n", rpc_handle, wine_dbgstr_guid(&hService->uuid));
+    if ((err = validate_service_handle(hService, SERVICE_QUERY_CONFIG, &service)) != 0)
+        return err;
+
+    lock_services();
+    config->dwServiceType = service->config.dwServiceType;
+    config->dwStartType = service->config.dwStartType;
+    config->dwErrorControl = service->config.dwErrorControl;
+    config->lpBinaryPathName = strdupW(service->config.lpBinaryPathName);
+    config->lpLoadOrderGroup = strdupW(service->config.lpLoadOrderGroup);
+    config->dwTagId = service->config.dwTagId;
+    config->lpDependencies = NULL; /* TODO */
+    config->lpServiceStartName = strdupW(service->config.lpServiceStartName);
+    config->lpDisplayName = strdupW(service->config.lpDisplayName);
+    unlock_services();
+    return ERROR_SUCCESS;
+}
+
 DWORD svcctl_CloseServiceHandle(
     SvcCtlRpcHandle rpc_handle,
     POLICY_HANDLE *handle)
-- 
1.5.4


--------------080904080005010706000902--



More information about the wine-patches mailing list