From 6cb602c6db8534611da62465d2b595b9391c229e Mon Sep 17 00:00:00 2001 From: Stefan Leichter Date: Fri, 21 Mar 2008 09:49:57 +0100 Subject: [PATCH] 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 d066f5c99bd..e9a3ccc5516 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 ae565ab2095..007d2b028bd 100644 --- a/dlls/advapi32/service.c +++ b/dlls/advapi32/service.c @@ -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.@] */ diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c index 8c717157a79..9b4eb728fb8 100644 --- a/dlls/advapi32/tests/service.c +++ b/dlls/advapi32/tests/service.c @@ -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); diff --git a/include/winsvc.h b/include/winsvc.h index fb77789d747..1031f0cf754 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)