[ADVAPI32]

- Rewrite RegQueryValueExA as a wrapper arount RegQueryValueExW
CORE-8582

svn path=/trunk/; revision=64441
This commit is contained in:
Jérôme Gardou 2014-10-01 17:48:04 +00:00
parent cd4b86a398
commit 7478b71bc8

View file

@ -3942,102 +3942,86 @@ RegQueryReflectionKey(IN HKEY hBase,
*/ */
LONG LONG
WINAPI WINAPI
RegQueryValueExA(HKEY hkeyorg, RegQueryValueExA(
LPCSTR name, _In_ HKEY hkeyorg,
LPDWORD reserved, _In_ LPCSTR name,
LPDWORD type, _In_ LPDWORD reserved,
LPBYTE data, _Out_opt_ LPDWORD type,
LPDWORD count) _Out_opt_ LPBYTE data,
_Inout_opt_ LPDWORD count)
{ {
HANDLE hkey;
NTSTATUS status;
ANSI_STRING nameA;
UNICODE_STRING nameW; UNICODE_STRING nameW;
DWORD total_size, datalen = 0; DWORD DataLength;
char buffer[256], *buf_ptr = buffer; DWORD ErrorCode;
KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; DWORD BufferSize = 0;
static const int info_size = offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ); WCHAR* Buffer;
CHAR* DataStr = (CHAR*)data;
DWORD LocalType;
TRACE("(%p,%s,%p,%p,%p,%p=%d)\n", /* Validate those parameters, the rest will be done with the first RegQueryValueExW call */
hkeyorg, debugstr_a(name), reserved, type, data, count, count ? *count : 0 ); if ((data && !count) || reserved)
return ERROR_INVALID_PARAMETER;
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER; if (name)
status = MapDefaultKey(&hkey, hkeyorg); RtlCreateUnicodeStringFromAsciiz(&nameW, name);
if (!NT_SUCCESS(status)) else
RtlInitEmptyUnicodeString(&nameW, NULL, 0);
ErrorCode = RegQueryValueExW(hkeyorg, nameW.Buffer, NULL, &LocalType, NULL, &BufferSize);
if (ErrorCode != ERROR_SUCCESS)
{ {
return RtlNtStatusToDosError(status); if (!data)
*count = 0;
RtlFreeUnicodeString(&nameW);
return ErrorCode;
} }
if (count) datalen = *count; /* See if we can directly handle the call without caring for conversion */
if (!data && count) *count = 0; if (!is_string(LocalType) || !count)
RtlInitAnsiString( &nameA, name );
if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
{ {
ClosePredefKey(hkey); ErrorCode = RegQueryValueExW(hkeyorg, nameW.Buffer, reserved, type, data, count);
return RtlNtStatusToDosError(status); RtlFreeUnicodeString(&nameW);
return ErrorCode;
} }
status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, /* Allocate a unicode string to get the data */
buffer, sizeof(buffer), &total_size ); Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
if (status && status != STATUS_BUFFER_OVERFLOW) goto done; if (!Buffer)
/* we need to fetch the contents for a string type even if not requested,
* because we need to compute the length of the ASCII string. */
if (data || is_string(info->Type))
{ {
/* retry with a dynamically allocated buffer */ RtlFreeUnicodeString(&nameW);
while (status == STATUS_BUFFER_OVERFLOW) return ERROR_NOT_ENOUGH_MEMORY;
{
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
{
status = STATUS_NO_MEMORY;
goto done;
}
info = (KEY_VALUE_PARTIAL_INFORMATION *)buf_ptr;
status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
buf_ptr, total_size, &total_size );
}
if (status) goto done;
if (is_string(info->Type))
{
DWORD len;
RtlUnicodeToMultiByteSize( &len, (WCHAR *)(buf_ptr + info_size),
total_size - info_size );
if (data && len)
{
if (len > datalen) status = STATUS_BUFFER_OVERFLOW;
else
{
RtlUnicodeToMultiByteN( (char*)data, len, NULL, (WCHAR *)(buf_ptr + info_size),
total_size - info_size );
/* if the type is REG_SZ and data is not 0-terminated
* and there is enough space in the buffer NT appends a \0 */
if (len < datalen && data[len-1]) data[len] = 0;
}
}
total_size = len + info_size;
}
else if (data)
{
if (total_size - info_size > datalen) status = STATUS_BUFFER_OVERFLOW;
else memcpy( data, buf_ptr + info_size, total_size - info_size );
}
} }
else status = STATUS_SUCCESS;
if (type) *type = info->Type; ErrorCode = RegQueryValueExW(hkeyorg, nameW.Buffer, reserved, type, (LPBYTE)Buffer, &BufferSize);
if (count) *count = total_size - info_size; if (ErrorCode != ERROR_SUCCESS)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
RtlFreeUnicodeString(&nameW);
return ErrorCode;
}
done: /* We don't need this anymore */
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); RtlFreeUnicodeString(&nameW);
RtlFreeUnicodeString( &nameW );
ClosePredefKey(hkey); DataLength = *count;
return RtlNtStatusToDosError(status); RtlUnicodeToMultiByteSize(count, Buffer, BufferSize);
if ((!data) || (DataLength < *count))
{
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
return data ? ERROR_MORE_DATA : ERROR_SUCCESS;
}
/* We can finally do the conversion */
RtlUnicodeToMultiByteN(DataStr, DataLength, NULL, Buffer, BufferSize);
/* NULL-terminate if there is enough room */
if ((DataLength > *count) && (DataStr[*count - 1] != '\0'))
DataStr[*count] = '\0';
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
return ERROR_SUCCESS;
} }