Alexandre Julliard : advapi32: Reimplemented QueryServiceConfig2W in services.exe.

Alexandre Julliard julliard at winehq.org
Tue Jan 20 08:27:25 CST 2009


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Jan 19 20:18:24 2009 +0100

advapi32: Reimplemented QueryServiceConfig2W in services.exe.

---

 dlls/advapi32/service.c |   60 +++++++++++++++++++++++-----------------------
 include/wine/svcctl.idl |   10 ++++++-
 programs/services/rpc.c |   49 ++++++++++++++++++++++++++++++++-----
 3 files changed, 80 insertions(+), 39 deletions(-)

diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c
index cf58e2c..dd056b2 100644
--- a/dlls/advapi32/service.c
+++ b/dlls/advapi32/service.c
@@ -292,6 +292,7 @@ static DWORD map_exception_code(DWORD exception_code)
     switch (exception_code)
     {
     case RPC_X_NULL_REF_POINTER:
+        return ERROR_INVALID_ADDRESS;
     case RPC_X_ENUM_VALUE_OUT_OF_RANGE:
     case RPC_X_BYTE_COUNT_TOO_SMALL:
         return ERROR_INVALID_PARAMETER;
@@ -1654,9 +1655,7 @@ cleanup:
 BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
                                  DWORD size, LPDWORD needed)
 {
-    DWORD sz, type;
-    HKEY hKey;
-    LONG r;
+    DWORD err;
     struct sc_service *hsvc;
 
     if(dwLevel != SERVICE_CONFIG_DESCRIPTION) {
@@ -1670,7 +1669,8 @@ BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffe
         SetLastError(ERROR_INVALID_LEVEL);
         return FALSE;
     }
-    if(!needed || (!buffer && size)) {
+
+    if(!buffer && size) {
         SetLastError(ERROR_INVALID_ADDRESS);
         return FALSE;
     }
@@ -1683,36 +1683,36 @@ BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffe
         SetLastError(ERROR_INVALID_HANDLE);
         return FALSE;
     }
-    hKey = hsvc->hkey;
 
-    switch(dwLevel) {
-        case SERVICE_CONFIG_DESCRIPTION: {
-            static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
-            LPSERVICE_DESCRIPTIONW config = (LPSERVICE_DESCRIPTIONW) buffer;
-            LPBYTE strbuf = NULL;
-            *needed = sizeof (SERVICE_DESCRIPTIONW);
-            sz = size - *needed;
-            if(config && (*needed <= size))
-                strbuf = (LPBYTE) (config + 1);
-            r = RegQueryValueExW( hKey, szDescription, 0, &type, strbuf, &sz );
-            if((r == ERROR_SUCCESS) && ( type != REG_SZ)) {
-                FIXME("SERVICE_CONFIG_DESCRIPTION: don't know how to handle type %d\n", type);
-                return FALSE;
-            }
-            *needed += sz;
-            if(config) {
-                if(r == ERROR_SUCCESS)
-                    config->lpDescription = (LPWSTR) (config + 1);
-                else
-                    config->lpDescription = NULL;
-            }
+    __TRY
+    {
+        err = svcctl_QueryServiceConfig2W(hsvc->hdr.server_handle, dwLevel, buffer, size, needed);
+    }
+    __EXCEPT(rpc_filter)
+    {
+        err = map_exception_code(GetExceptionCode());
+    }
+    __ENDTRY
+
+    if (err != ERROR_SUCCESS)
+    {
+        SetLastError( err );
+        return FALSE;
+    }
+
+    switch (dwLevel)
+    {
+    case SERVICE_CONFIG_DESCRIPTION:
+        if (buffer)
+        {
+            SERVICE_DESCRIPTIONW *descr = (SERVICE_DESCRIPTIONW *)buffer;
+            if (descr->lpDescription)  /* make it an absolute pointer */
+                descr->lpDescription = (WCHAR *)(buffer + (ULONG_PTR)descr->lpDescription);
+            break;
         }
-        break;
     }
-    if(*needed > size)
-        SetLastError(ERROR_INSUFFICIENT_BUFFER);
 
-    return (*needed <= size);
+    return TRUE;
 }
 
 /******************************************************************************
diff --git a/include/wine/svcctl.idl b/include/wine/svcctl.idl
index 66abd30..d04da08 100644
--- a/include/wine/svcctl.idl
+++ b/include/wine/svcctl.idl
@@ -296,8 +296,14 @@ typedef [switch_type(DWORD)] union
     /* Not compatible with Windows function 0x26 */
     DWORD svcctl_QueryServiceConfig2A(/* FIXME */);
 
-    /* Not compatible with Windows function 0x27 */
-    DWORD svcctl_QueryServiceConfig2W(/* FIXME */);
+    /* Untested with Windows function 0x27 */
+    DWORD svcctl_QueryServiceConfig2W(
+        [in] SC_RPC_HANDLE hService,
+        [in] DWORD InfoLevel,
+        [out,size_is(cbBufSize)] BYTE lpBuffer[],
+        [in] DWORD cbBufSize,
+        [out] LPDWORD pcbBytesNeeded
+    );
 
     /* Untested with Windows function 0x28 */
     DWORD svcctl_QueryServiceStatusEx(
diff --git a/programs/services/rpc.c b/programs/services/rpc.c
index 830ed9c..b6014aa 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -646,6 +646,48 @@ DWORD svcctl_ChangeServiceConfig2W( SC_RPC_HANDLE hService, DWORD level, SERVICE
     return err;
 }
 
+DWORD svcctl_QueryServiceConfig2W( SC_RPC_HANDLE hService, DWORD level,
+                                   BYTE *buffer, DWORD size, LPDWORD needed )
+{
+    struct sc_service_handle *service;
+    DWORD err;
+
+    if ((err = validate_service_handle(hService, SERVICE_QUERY_STATUS, &service)) != 0)
+        return err;
+
+    switch (level)
+    {
+    case SERVICE_CONFIG_DESCRIPTION:
+        {
+            SERVICE_DESCRIPTIONW *descr = (SERVICE_DESCRIPTIONW *)buffer;
+
+            service_lock_shared(service->service_entry);
+            *needed = sizeof(*descr);
+            if (service->service_entry->description)
+                *needed += (strlenW(service->service_entry->description) + 1) * sizeof(WCHAR);
+            if (size >= *needed)
+            {
+                if (service->service_entry->description)
+                {
+                    /* store a buffer offset instead of a pointer */
+                    descr->lpDescription = (WCHAR *)((BYTE *)(descr + 1) - buffer);
+                    strcpyW( (WCHAR *)(descr + 1), service->service_entry->description );
+                }
+                else descr->lpDescription = NULL;
+            }
+            else err = ERROR_INSUFFICIENT_BUFFER;
+            service_unlock(service->service_entry);
+        }
+        break;
+
+    default:
+        WINE_FIXME("level %u not implemented\n", level);
+        err = ERROR_INVALID_LEVEL;
+        break;
+    }
+    return err;
+}
+
 DWORD svcctl_QueryServiceStatusEx(
     SC_RPC_HANDLE hService,
     SC_STATUS_TYPE InfoLevel,
@@ -1141,13 +1183,6 @@ DWORD svcctl_QueryServiceConfig2A(
     return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
-DWORD svcctl_QueryServiceConfig2W(
-    void)
-{
-    WINE_FIXME("\n");
-    return ERROR_CALL_NOT_IMPLEMENTED;
-}
-
 
 DWORD RPC_Init(void)
 {




More information about the wine-cvs mailing list