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