Commit 6cb602c6 authored by Stefan Leichter's avatar Stefan Leichter Committed by Alexandre Julliard

advapi32: Partly implemented QueryServiceConfig2A/W.

parent f14eecde
...@@ -448,8 +448,8 @@ ...@@ -448,8 +448,8 @@
# @ stub QueryAllTracesA # @ stub QueryAllTracesA
# @ stub QueryAllTracesW # @ stub QueryAllTracesW
# @ stub QueryRecoveryAgentsOnEncryptedFile # @ stub QueryRecoveryAgentsOnEncryptedFile
# @ stub QueryServiceConfig2A @ stdcall QueryServiceConfig2A(long long ptr long ptr)
# @ stub QueryServiceConfig2W @ stdcall QueryServiceConfig2W(long long ptr long ptr)
@ stdcall QueryServiceConfigA(long ptr long ptr) @ stdcall QueryServiceConfigA(long ptr long ptr)
@ stdcall QueryServiceConfigW(long ptr long ptr) @ stdcall QueryServiceConfigW(long ptr long ptr)
@ stdcall QueryServiceLockStatusA(long ptr long ptr) @ stdcall QueryServiceLockStatusA(long ptr long ptr)
......
...@@ -2053,6 +2053,121 @@ QueryServiceConfigW( SC_HANDLE hService, ...@@ -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.@] * EnumServicesStatusA [ADVAPI32.@]
*/ */
BOOL WINAPI BOOL WINAPI
......
...@@ -947,6 +947,13 @@ static void test_queryconfig2(void) ...@@ -947,6 +947,13 @@ static void test_queryconfig2(void)
ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %d\n", GetLastError()); ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %d\n", GetLastError());
needed = 0; 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; pConfig->lpDescription = (LPSTR)0xdeadbeef;
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed); ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
ok(ret, "expected QueryServiceConfig2A to succeed\n"); ok(ret, "expected QueryServiceConfig2A to succeed\n");
......
...@@ -243,8 +243,14 @@ typedef struct _QUERY_SERVICE_CONFIGW { ...@@ -243,8 +243,14 @@ typedef struct _QUERY_SERVICE_CONFIGW {
} QUERY_SERVICE_CONFIGW, *LPQUERY_SERVICE_CONFIGW; } QUERY_SERVICE_CONFIGW, *LPQUERY_SERVICE_CONFIGW;
/* defines and structures for ChangeServiceConfig2 */ /* defines and structures for ChangeServiceConfig2 */
#define SERVICE_CONFIG_DESCRIPTION 1 #define SERVICE_CONFIG_DESCRIPTION 1
#define SERVICE_CONFIG_FAILURE_ACTIONS 2 #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 { typedef struct _SERVICE_DESCRIPTIONA {
LPSTR lpDescription; LPSTR lpDescription;
...@@ -351,6 +357,9 @@ WINADVAPI BOOL WINAPI QueryServiceStatusEx(SC_HANDLE,SC_STATUS_TYPE,LPBYT ...@@ -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 QueryServiceConfigA(SC_HANDLE,LPQUERY_SERVICE_CONFIGA,DWORD,LPDWORD);
WINADVAPI BOOL WINAPI QueryServiceConfigW(SC_HANDLE,LPQUERY_SERVICE_CONFIGW,DWORD,LPDWORD); WINADVAPI BOOL WINAPI QueryServiceConfigW(SC_HANDLE,LPQUERY_SERVICE_CONFIGW,DWORD,LPDWORD);
#define QueryServiceConfig WINELIB_NAME_AW(QueryServiceConfig) #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 QueryServiceLockStatusA(SC_HANDLE,LPQUERY_SERVICE_LOCK_STATUSA,DWORD,LPDWORD);
WINADVAPI BOOL WINAPI QueryServiceLockStatusW(SC_HANDLE,LPQUERY_SERVICE_LOCK_STATUSW,DWORD,LPDWORD); WINADVAPI BOOL WINAPI QueryServiceLockStatusW(SC_HANDLE,LPQUERY_SERVICE_LOCK_STATUSW,DWORD,LPDWORD);
#define QueryServiceLockStatus WINELIB_NAME_AW(QueryServiceLockStatus) #define QueryServiceLockStatus WINELIB_NAME_AW(QueryServiceLockStatus)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment