Commit b608a43d authored by Alexandre Julliard's avatar Alexandre Julliard

advapi32: Reimplemented QueryServiceConfig2W in services.exe.

parent 8e16e787
......@@ -292,6 +292,7 @@ static DWORD map_exception_code(DWORD exception_code)
switch (exception_code)
{
case RPC_X_NULL_REF_POINTER:
return ERROR_INVALID_ADDRESS;
case RPC_X_ENUM_VALUE_OUT_OF_RANGE:
case RPC_X_BYTE_COUNT_TOO_SMALL:
return ERROR_INVALID_PARAMETER;
......@@ -1654,9 +1655,7 @@ cleanup:
BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
DWORD size, LPDWORD needed)
{
DWORD sz, type;
HKEY hKey;
LONG r;
DWORD err;
struct sc_service *hsvc;
if(dwLevel != SERVICE_CONFIG_DESCRIPTION) {
......@@ -1670,7 +1669,8 @@ BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffe
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
if(!needed || (!buffer && size)) {
if(!buffer && size) {
SetLastError(ERROR_INVALID_ADDRESS);
return FALSE;
}
......@@ -1683,36 +1683,36 @@ BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffe
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;
}
__TRY
{
err = svcctl_QueryServiceConfig2W(hsvc->hdr.server_handle, dwLevel, buffer, size, needed);
}
__EXCEPT(rpc_filter)
{
err = map_exception_code(GetExceptionCode());
}
__ENDTRY
if (err != ERROR_SUCCESS)
{
SetLastError( err );
return FALSE;
}
switch (dwLevel)
{
case SERVICE_CONFIG_DESCRIPTION:
if (buffer)
{
SERVICE_DESCRIPTIONW *descr = (SERVICE_DESCRIPTIONW *)buffer;
if (descr->lpDescription) /* make it an absolute pointer */
descr->lpDescription = (WCHAR *)(buffer + (ULONG_PTR)descr->lpDescription);
break;
}
break;
}
if(*needed > size)
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (*needed <= size);
return TRUE;
}
/******************************************************************************
......
......@@ -296,8 +296,14 @@ typedef [switch_type(DWORD)] union
/* Not compatible with Windows function 0x26 */
DWORD svcctl_QueryServiceConfig2A(/* FIXME */);
/* Not compatible with Windows function 0x27 */
DWORD svcctl_QueryServiceConfig2W(/* FIXME */);
/* Untested with Windows function 0x27 */
DWORD svcctl_QueryServiceConfig2W(
[in] SC_RPC_HANDLE hService,
[in] DWORD InfoLevel,
[out,size_is(cbBufSize)] BYTE lpBuffer[],
[in] DWORD cbBufSize,
[out] LPDWORD pcbBytesNeeded
);
/* Untested with Windows function 0x28 */
DWORD svcctl_QueryServiceStatusEx(
......
......@@ -646,6 +646,48 @@ DWORD svcctl_ChangeServiceConfig2W( SC_RPC_HANDLE hService, DWORD level, SERVICE
return err;
}
DWORD svcctl_QueryServiceConfig2W( SC_RPC_HANDLE hService, DWORD level,
BYTE *buffer, DWORD size, LPDWORD needed )
{
struct sc_service_handle *service;
DWORD err;
if ((err = validate_service_handle(hService, SERVICE_QUERY_STATUS, &service)) != 0)
return err;
switch (level)
{
case SERVICE_CONFIG_DESCRIPTION:
{
SERVICE_DESCRIPTIONW *descr = (SERVICE_DESCRIPTIONW *)buffer;
service_lock_shared(service->service_entry);
*needed = sizeof(*descr);
if (service->service_entry->description)
*needed += (strlenW(service->service_entry->description) + 1) * sizeof(WCHAR);
if (size >= *needed)
{
if (service->service_entry->description)
{
/* store a buffer offset instead of a pointer */
descr->lpDescription = (WCHAR *)((BYTE *)(descr + 1) - buffer);
strcpyW( (WCHAR *)(descr + 1), service->service_entry->description );
}
else descr->lpDescription = NULL;
}
else err = ERROR_INSUFFICIENT_BUFFER;
service_unlock(service->service_entry);
}
break;
default:
WINE_FIXME("level %u not implemented\n", level);
err = ERROR_INVALID_LEVEL;
break;
}
return err;
}
DWORD svcctl_QueryServiceStatusEx(
SC_RPC_HANDLE hService,
SC_STATUS_TYPE InfoLevel,
......@@ -1141,13 +1183,6 @@ DWORD svcctl_QueryServiceConfig2A(
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD svcctl_QueryServiceConfig2W(
void)
{
WINE_FIXME("\n");
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD RPC_Init(void)
{
......
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