advapi32: Fix QueryServiceConfig2 on Wow64.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
445996d31b
commit
251c9ccff7
|
@ -1543,6 +1543,8 @@ BOOL WINAPI QueryServiceConfig2A(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffe
|
|||
BOOL ret;
|
||||
LPBYTE bufferW = NULL;
|
||||
|
||||
TRACE("%p %u %p %u %p\n", hService, dwLevel, buffer, size, needed);
|
||||
|
||||
if(buffer && size)
|
||||
bufferW = heap_alloc(size);
|
||||
|
||||
|
@ -1591,24 +1593,42 @@ cleanup:
|
|||
BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
|
||||
DWORD size, LPDWORD needed)
|
||||
{
|
||||
BYTE *bufptr;
|
||||
DWORD err;
|
||||
|
||||
if(dwLevel!=SERVICE_CONFIG_DESCRIPTION && dwLevel!=SERVICE_CONFIG_PRESHUTDOWN_INFO) {
|
||||
TRACE("%p %u %p %u %p\n", hService, dwLevel, buffer, size, needed);
|
||||
|
||||
if (!buffer && size)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_ADDRESS);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (dwLevel)
|
||||
{
|
||||
case SERVICE_CONFIG_DESCRIPTION:
|
||||
if (!(bufptr = heap_alloc( size ))) return ERROR_OUTOFMEMORY;
|
||||
break;
|
||||
|
||||
case SERVICE_CONFIG_PRESHUTDOWN_INFO:
|
||||
bufptr = buffer;
|
||||
break;
|
||||
|
||||
default:
|
||||
FIXME("Level %d not implemented\n", dwLevel);
|
||||
SetLastError(ERROR_INVALID_LEVEL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(!buffer && size) {
|
||||
if (!needed)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_ADDRESS);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
TRACE("%p 0x%d %p 0x%d %p\n", hService, dwLevel, buffer, size, needed);
|
||||
|
||||
__TRY
|
||||
{
|
||||
err = svcctl_QueryServiceConfig2W(hService, dwLevel, buffer, size, needed);
|
||||
err = svcctl_QueryServiceConfig2W(hService, dwLevel, bufptr, size, needed);
|
||||
}
|
||||
__EXCEPT(rpc_filter)
|
||||
{
|
||||
|
@ -1616,22 +1636,53 @@ BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffe
|
|||
}
|
||||
__ENDTRY
|
||||
|
||||
if (err != ERROR_SUCCESS)
|
||||
{
|
||||
SetLastError( err );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (dwLevel)
|
||||
{
|
||||
case SERVICE_CONFIG_DESCRIPTION:
|
||||
if (buffer)
|
||||
{
|
||||
SERVICE_DESCRIPTIONW *desc = (SERVICE_DESCRIPTIONW *)buffer;
|
||||
struct service_description *s = (struct service_description *)bufptr;
|
||||
|
||||
if (err != ERROR_SUCCESS && err != ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
SERVICE_DESCRIPTIONW *descr = (SERVICE_DESCRIPTIONW *)buffer;
|
||||
if (descr->lpDescription) /* make it an absolute pointer */
|
||||
descr->lpDescription = (WCHAR *)(buffer + (ULONG_PTR)descr->lpDescription);
|
||||
break;
|
||||
heap_free( bufptr );
|
||||
SetLastError( err );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* adjust for potentially larger SERVICE_DESCRIPTIONW structure */
|
||||
if (*needed == sizeof(*s)) *needed = sizeof(*desc);
|
||||
else
|
||||
*needed = *needed - FIELD_OFFSET(struct service_description, description) + sizeof(*desc);
|
||||
|
||||
if (size < *needed)
|
||||
{
|
||||
heap_free( bufptr );
|
||||
SetLastError( ERROR_INSUFFICIENT_BUFFER );
|
||||
return FALSE;
|
||||
}
|
||||
if (desc)
|
||||
{
|
||||
if (!s->size) desc->lpDescription = NULL;
|
||||
else
|
||||
{
|
||||
desc->lpDescription = (WCHAR *)(desc + 1);
|
||||
memcpy( desc->lpDescription, s->description, s->size );
|
||||
}
|
||||
}
|
||||
heap_free( bufptr );
|
||||
break;
|
||||
}
|
||||
case SERVICE_CONFIG_PRESHUTDOWN_INFO:
|
||||
if (err != ERROR_SUCCESS)
|
||||
{
|
||||
SetLastError( err );
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
|
@ -225,6 +225,12 @@ struct enum_service_status_process
|
|||
SERVICE_STATUS_PROCESS service_status_process;
|
||||
};
|
||||
|
||||
struct service_description
|
||||
{
|
||||
USHORT size;
|
||||
WCHAR description[1];
|
||||
};
|
||||
|
||||
typedef struct _SERVICE_RPC_REQUIRED_PRIVILEGES_INFO {
|
||||
DWORD cbRequiredPrivileges;
|
||||
[size_is(cbRequiredPrivileges)] BYTE *pRequiredPrivileges;
|
||||
|
|
|
@ -879,27 +879,32 @@ DWORD __cdecl svcctl_QueryServiceConfig2W( SC_RPC_HANDLE hService, DWORD level,
|
|||
switch (level)
|
||||
{
|
||||
case SERVICE_CONFIG_DESCRIPTION:
|
||||
{
|
||||
SERVICE_DESCRIPTIONW *descr = (SERVICE_DESCRIPTIONW *)buffer;
|
||||
{
|
||||
struct service_description *desc = (struct service_description *)buffer;
|
||||
DWORD total_size = sizeof(*desc);
|
||||
|
||||
service_lock(service->service_entry);
|
||||
*needed = sizeof(*descr);
|
||||
service_lock(service->service_entry);
|
||||
if (service->service_entry->description)
|
||||
total_size += strlenW(service->service_entry->description) * sizeof(WCHAR);
|
||||
|
||||
*needed = total_size;
|
||||
if (size >= total_size)
|
||||
{
|
||||
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;
|
||||
strcpyW( desc->description, service->service_entry->description );
|
||||
desc->size = total_size - FIELD_OFFSET(struct service_description, description);
|
||||
}
|
||||
else
|
||||
{
|
||||
desc->description[0] = 0;
|
||||
desc->size = 0;
|
||||
}
|
||||
else err = ERROR_INSUFFICIENT_BUFFER;
|
||||
service_unlock(service->service_entry);
|
||||
}
|
||||
break;
|
||||
else err = ERROR_INSUFFICIENT_BUFFER;
|
||||
service_unlock(service->service_entry);
|
||||
}
|
||||
break;
|
||||
|
||||
case SERVICE_CONFIG_PRESHUTDOWN_INFO:
|
||||
service_lock(service->service_entry);
|
||||
|
|
Loading…
Reference in New Issue