Stefan Leichter : advapi32: Partly implemented QueryServiceConfig2A/W.

Alexandre Julliard julliard at winehq.org
Wed Mar 26 09:16:13 CDT 2008


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

Author: Stefan Leichter <Stefan.Leichter at camline.com>
Date:   Fri Mar 21 09:49:57 2008 +0100

advapi32: Partly implemented QueryServiceConfig2A/W.

---

 dlls/advapi32/advapi32.spec   |    4 +-
 dlls/advapi32/service.c       |  115 +++++++++++++++++++++++++++++++++++++++++
 dlls/advapi32/tests/service.c |    7 +++
 include/winsvc.h              |   13 ++++-
 4 files changed, 135 insertions(+), 4 deletions(-)

diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec
index d066f5c..e9a3ccc 100644
--- a/dlls/advapi32/advapi32.spec
+++ b/dlls/advapi32/advapi32.spec
@@ -448,8 +448,8 @@
 # @ stub QueryAllTracesA
 # @ stub QueryAllTracesW
 # @ stub QueryRecoveryAgentsOnEncryptedFile
-# @ stub QueryServiceConfig2A
-# @ stub QueryServiceConfig2W
+@ stdcall QueryServiceConfig2A(long long ptr long ptr)
+@ stdcall QueryServiceConfig2W(long long ptr long ptr)
 @ stdcall QueryServiceConfigA(long ptr long ptr)
 @ stdcall QueryServiceConfigW(long ptr long ptr)
 @ stdcall QueryServiceLockStatusA(long ptr long ptr)
diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c
index ae565ab..007d2b0 100644
--- a/dlls/advapi32/service.c
+++ b/dlls/advapi32/service.c
@@ -2053,6 +2053,121 @@ QueryServiceConfigW( SC_HANDLE hService,
 }
 
 /******************************************************************************
+ * QueryServiceConfig2A [ADVAPI32.@]
+ *
+ * Note
+ *   observed unter win2k:
+ *   The functions QueryServiceConfig2A and QueryServiceConfig2W return the same
+ *   required buffer size (in byte) at least for dwLevel SERVICE_CONFIG_DESCRIPTION
+ */
+BOOL WINAPI QueryServiceConfig2A(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
+                                 DWORD size, LPDWORD needed)
+{
+    BOOL ret;
+    LPBYTE bufferW = NULL;
+
+    if(buffer && size)
+        bufferW = HeapAlloc( GetProcessHeap(), 0, size);
+
+    ret = QueryServiceConfig2W(hService, dwLevel, bufferW, size, needed);
+    if(!ret) goto cleanup;
+
+    switch(dwLevel) {
+        case SERVICE_CONFIG_DESCRIPTION:
+            {   LPSERVICE_DESCRIPTIONA configA = (LPSERVICE_DESCRIPTIONA) buffer;
+                LPSERVICE_DESCRIPTIONW configW = (LPSERVICE_DESCRIPTIONW) bufferW;
+                if (configW->lpDescription) {
+                    DWORD sz;
+                    configA->lpDescription = (LPSTR)(configA + 1);
+                    sz = WideCharToMultiByte( CP_ACP, 0, configW->lpDescription, -1,
+                             configA->lpDescription, size - sizeof(SERVICE_DESCRIPTIONA), NULL, NULL );
+                    if (!sz) {
+                        FIXME("WideCharToMultiByte failed for configW->lpDescription\n");
+                        ret = FALSE;
+                        configA->lpDescription = NULL;
+                    }
+                }
+                else configA->lpDescription = NULL;
+            }
+        break;
+        default:
+            FIXME("conversation W->A not implemented for level %d\n", dwLevel);
+            ret = FALSE;
+    }
+
+cleanup:
+    HeapFree( GetProcessHeap(), 0, bufferW);
+    return ret;
+}
+
+/******************************************************************************
+ * QueryServiceConfig2W [ADVAPI32.@]
+ */
+BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
+                                 DWORD size, LPDWORD needed)
+{
+    DWORD sz, type;
+    HKEY hKey;
+    LONG r;
+    struct sc_service *hsvc;
+
+    if(dwLevel != SERVICE_CONFIG_DESCRIPTION) {
+        if((dwLevel == SERVICE_CONFIG_DELAYED_AUTO_START_INFO) ||
+           (dwLevel == SERVICE_CONFIG_FAILURE_ACTIONS) ||
+           (dwLevel == SERVICE_CONFIG_FAILURE_ACTIONS_FLAG) ||
+           (dwLevel == SERVICE_CONFIG_PRESHUTDOWN_INFO) ||
+           (dwLevel == SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO) ||
+           (dwLevel == SERVICE_CONFIG_SERVICE_SID_INFO))
+            FIXME("Level %d not implemented\n", dwLevel);
+        SetLastError(ERROR_INVALID_LEVEL);
+        return FALSE;
+    }
+    if(!needed || (!buffer && size)) {
+        SetLastError(ERROR_INVALID_ADDRESS);
+        return FALSE;
+    }
+
+    TRACE("%p 0x%d %p 0x%d %p\n", hService, dwLevel, buffer, size, needed);
+
+    hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
+    if (!hsvc)
+    {
+        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;
+            }
+        }
+        break;
+    }
+    if(*needed > size)
+        SetLastError(ERROR_INSUFFICIENT_BUFFER);
+
+    return (*needed <= size);
+}
+
+/******************************************************************************
  * EnumServicesStatusA [ADVAPI32.@]
  */
 BOOL WINAPI
diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c
index 8c71715..9b4eb72 100644
--- a/dlls/advapi32/tests/service.c
+++ b/dlls/advapi32/tests/service.c
@@ -947,6 +947,13 @@ static void test_queryconfig2(void)
     ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %d\n", GetLastError());
 
     needed = 0;
+    SetLastError(0xdeadbeef);
+    ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA)-1,&needed);
+    ok(!ret, "expected QueryServiceConfig2A to fail\n");
+    ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+    ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %d\n", needed);
+
+    needed = 0;
     pConfig->lpDescription = (LPSTR)0xdeadbeef;
     ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
     ok(ret, "expected QueryServiceConfig2A to succeed\n");
diff --git a/include/winsvc.h b/include/winsvc.h
index fb77789..1031f0c 100644
--- a/include/winsvc.h
+++ b/include/winsvc.h
@@ -243,8 +243,14 @@ typedef struct _QUERY_SERVICE_CONFIGW {
 } QUERY_SERVICE_CONFIGW, *LPQUERY_SERVICE_CONFIGW;
 
 /* defines and structures for ChangeServiceConfig2 */
-#define SERVICE_CONFIG_DESCRIPTION     1
-#define SERVICE_CONFIG_FAILURE_ACTIONS 2
+#define SERVICE_CONFIG_DESCRIPTION              1
+#define SERVICE_CONFIG_FAILURE_ACTIONS          2
+#define SERVICE_CONFIG_DELAYED_AUTO_START_INFO  3
+#define SERVICE_CONFIG_FAILURE_ACTIONS_FLAG     4
+#define SERVICE_CONFIG_SERVICE_SID_INFO         5
+#define SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO 6
+#define SERVICE_CONFIG_PRESHUTDOWN_INFO         7
+
 
 typedef struct _SERVICE_DESCRIPTIONA {
    LPSTR lpDescription;
@@ -351,6 +357,9 @@ WINADVAPI BOOL        WINAPI QueryServiceStatusEx(SC_HANDLE,SC_STATUS_TYPE,LPBYT
 WINADVAPI BOOL        WINAPI QueryServiceConfigA(SC_HANDLE,LPQUERY_SERVICE_CONFIGA,DWORD,LPDWORD);
 WINADVAPI BOOL        WINAPI QueryServiceConfigW(SC_HANDLE,LPQUERY_SERVICE_CONFIGW,DWORD,LPDWORD);
 #define                      QueryServiceConfig WINELIB_NAME_AW(QueryServiceConfig)
+WINADVAPI BOOL        WINAPI QueryServiceConfig2A(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD);
+WINADVAPI BOOL        WINAPI QueryServiceConfig2W(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD);
+#define                      QueryServiceConfig2 WINELIB_NAME_AW(QueryServiceConfig2)
 WINADVAPI BOOL        WINAPI QueryServiceLockStatusA(SC_HANDLE,LPQUERY_SERVICE_LOCK_STATUSA,DWORD,LPDWORD);
 WINADVAPI BOOL        WINAPI QueryServiceLockStatusW(SC_HANDLE,LPQUERY_SERVICE_LOCK_STATUSW,DWORD,LPDWORD);
 #define                      QueryServiceLockStatus WINELIB_NAME_AW(QueryServiceLockStatus)




More information about the wine-cvs mailing list