advapi32: Partly implemented QueryServiceConfig2A/W.
authorStefan Leichter <Stefan.Leichter@camline.com>
Fri, 21 Mar 2008 08:49:57 +0000 (09:49 +0100)
committerAlexandre Julliard <julliard@winehq.org>
Wed, 26 Mar 2008 13:13:07 +0000 (14:13 +0100)
dlls/advapi32/advapi32.spec
dlls/advapi32/service.c
dlls/advapi32/tests/service.c
include/winsvc.h

index d066f5c99bd9489f2a0294d118dbe807fe97b7cb..e9a3ccc551654709c2a80f9a51ca493d655cfc9d 100644 (file)
 # @ 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)
index ae565ab20957d9c2fa78e8d1bbddde55a42e71ce..007d2b028bd1576806f00b6fda5cb0ebab29a062 100644 (file)
@@ -2052,6 +2052,121 @@ QueryServiceConfigW( SC_HANDLE hService,
     return TRUE;
 }
 
+/******************************************************************************
+ * 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.@]
  */
index 8c717157a7933cd33fa97e91bbf2837fdafccfb9..9b4eb728fb812ed440f02edb0c7da3f94c4d9749 100644 (file)
@@ -946,6 +946,13 @@ static void test_queryconfig2(void)
     ok(!ret, "expected QueryServiceConfig2A to fail\n");
     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);
index fb77789d747db9d5f2b3d89cf99d54a0045278a4..1031f0cf75416347ee2cd68758b6374d7249a92c 100644 (file)
@@ -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)