Author: jgardou
Date: Thu Oct 2 22:03:58 2014
New Revision: 64475
URL:
http://svn.reactos.org/svn/reactos?rev=64475&view=rev
Log:
[ADVAPI32]
- Reimplement RegEnumValueA on top of RegEnumValueW
CORE-8582
Modified:
trunk/reactos/dll/win32/advapi32/reg/reg.c
Modified: trunk/reactos/dll/win32/advapi32/reg/reg.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/advapi32/reg/reg…
==============================================================================
--- trunk/reactos/dll/win32/advapi32/reg/reg.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/advapi32/reg/reg.c [iso-8859-1] Thu Oct 2 22:03:58 2014
@@ -2697,120 +2697,139 @@
* @implemented
*/
LONG WINAPI
-RegEnumValueA(HKEY hKey,
- DWORD index,
- LPSTR value,
- LPDWORD val_count,
- LPDWORD reserved,
- LPDWORD type,
- LPBYTE data,
- LPDWORD count)
-{
- HANDLE KeyHandle;
- NTSTATUS status;
- ULONG total_size;
- char buffer[256], *buf_ptr = buffer;
- KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
- static const int info_size = FIELD_OFFSET( KEY_VALUE_FULL_INFORMATION, Name );
-
- //TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
- // hkey, index, value, val_count, reserved, type, data, count );
-
- /* NT only checks count, not val_count */
- if ((data && !count) || reserved)
+RegEnumValueA(
+ _In_ HKEY hKey,
+ _In_ DWORD dwIndex,
+ _Out_ LPSTR lpName,
+ _Inout_ LPDWORD lpcbName,
+ _Reserved_ LPDWORD lpdwReserved,
+ _Out_opt_ LPDWORD lpdwType,
+ _Out_opt_ LPBYTE lpData,
+ _Out_opt_ LPDWORD lpcbData)
+{
+ WCHAR* NameBuffer;
+ DWORD NameBufferSize, NameLength;
+ LONG ErrorCode;
+ DWORD LocalType = REG_NONE;
+ BOOL NameOverflow = FALSE;
+
+ /* Do parameter checks now, once and for all. */
+ if ((lpData && !lpcbData) || lpdwReserved)
return ERROR_INVALID_PARAMETER;
- status = MapDefaultKey(&KeyHandle, hKey);
- if (!NT_SUCCESS(status))
- {
- return RtlNtStatusToDosError(status);
- }
-
- total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
- if (data) total_size += *count;
- total_size = min( sizeof(buffer), total_size );
-
- status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
- buffer, total_size, &total_size );
- if (status && (status != STATUS_BUFFER_OVERFLOW) && (status !=
STATUS_BUFFER_TOO_SMALL)) goto done;
-
- /* 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 (value || data || is_string(info->Type))
- {
- /* retry with a dynamically allocated buffer */
- while ((status == STATUS_BUFFER_OVERFLOW) || (status ==
STATUS_BUFFER_TOO_SMALL))
- {
- if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
- if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
- {
- status = STATUS_INSUFFICIENT_RESOURCES;
- goto done;
- }
- info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
- status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
- buf_ptr, total_size, &total_size );
- }
-
- if (status) goto done;
-
- if (is_string(info->Type))
- {
- ULONG len;
- RtlUnicodeToMultiByteSize( &len, (WCHAR *)(buf_ptr +
info->DataOffset),
- info->DataLength );
- if (data && len)
- {
- if (len > *count) status = STATUS_BUFFER_OVERFLOW;
- else
- {
- RtlUnicodeToMultiByteN( (PCHAR)data, len, NULL, (WCHAR *)(buf_ptr +
info->DataOffset),
- info->DataLength );
- /* 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 < *count && data[len-1]) data[len] = 0;
- }
- }
- info->DataLength = len;
- }
- else if (data)
- {
- if (info->DataLength > *count) status = STATUS_BUFFER_OVERFLOW;
- else memcpy( data, buf_ptr + info->DataOffset, info->DataLength );
- }
-
- if (value && !status)
- {
- ULONG len;
-
- RtlUnicodeToMultiByteSize( &len, info->Name, info->NameLength );
- if (len >= *val_count)
- {
- status = STATUS_BUFFER_OVERFLOW;
- if (*val_count)
- {
- len = *val_count - 1;
- RtlUnicodeToMultiByteN( value, len, NULL, info->Name,
info->NameLength );
- value[len] = 0;
- }
- }
- else
- {
- RtlUnicodeToMultiByteN( value, len, NULL, info->Name,
info->NameLength );
- value[len] = 0;
- *val_count = len;
- }
- }
- }
- else status = STATUS_SUCCESS;
-
- if (type) *type = info->Type;
- if (count) *count = info->DataLength;
-
- done:
- if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
- ClosePredefKey(KeyHandle);
- return RtlNtStatusToDosError(status);
+ /* Get the size of the buffer we must use for the first call ro RegEnumValueW */
+ ErrorCode = RegQueryInfoKeyW(
+ hKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &NameBufferSize, NULL, NULL,
NULL);
+ if (ErrorCode != ERROR_SUCCESS)
+ return ErrorCode;
+
+ /* Allocate the buffer for the unicode name */
+ NameBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, NameBufferSize *
sizeof(WCHAR));
+ if (NameBuffer == NULL)
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ /*
+ * This code calls RegEnumValueW twice, because we need to know the type of the
enumerated value.
+ * So for the first call, we check if we overflow on the name, as we have no way of
knowing if this
+ * is an overflow on the data or on the name during the the second call. So the first
time, we make the
+ * call with the supplied value. This is merdique, but this is how it is.
+ */
+ NameLength = *lpcbName;
+ ErrorCode = RegEnumValueW(
+ hKey,
+ dwIndex,
+ NameBuffer,
+ &NameLength,
+ NULL,
+ &LocalType,
+ NULL,
+ NULL);
+ if (ErrorCode != ERROR_SUCCESS)
+ {
+ if (ErrorCode == ERROR_MORE_DATA)
+ NameOverflow = TRUE;
+ else
+ goto Exit;
+ }
+
+ if (is_string(LocalType) && lpcbData)
+ {
+ /* We must allocate a buffer to get the unicode data */
+ DWORD DataBufferSize = *lpcbData * sizeof(WCHAR);
+ WCHAR* DataBuffer = NULL;
+ DWORD DataLength = *lpcbData;
+ LPSTR DataStr = (LPSTR)lpData;
+
+ if (lpData)
+ DataBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, *lpcbData *
sizeof(WCHAR));
+
+ /* Do the real call */
+ ErrorCode = RegEnumValueW(
+ hKey,
+ dwIndex,
+ NameBuffer,
+ &NameBufferSize,
+ lpdwReserved,
+ lpdwType,
+ (LPBYTE)DataBuffer,
+ &DataBufferSize);
+
+ *lpcbData = DataBufferSize / sizeof(WCHAR);
+
+ if (ErrorCode != ERROR_SUCCESS)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, DataBuffer);
+ goto Exit;
+ }
+
+ /* Copy the data whatever the error code is */
+ if (lpData)
+ {
+ /* Do the data conversion */
+ RtlUnicodeToMultiByteN(DataStr, DataLength, 0, DataBuffer, DataBufferSize);
+ /* NULL-terminate if there is enough room */
+ if ((DataLength > *lpcbData) && (DataStr[*lpcbData - 1] !=
'\0'))
+ DataStr[*lpcbData] = '\0';
+ }
+
+ RtlFreeHeap(RtlGetProcessHeap(), 0, DataBuffer);
+ }
+ else
+ {
+ /* No data conversion needed. Do the call with provided buffers */
+ ErrorCode = RegEnumValueW(
+ hKey,
+ dwIndex,
+ NameBuffer,
+ &NameBufferSize,
+ lpdwReserved,
+ lpdwType,
+ lpData,
+ lpcbData);
+
+ if (ErrorCode != ERROR_SUCCESS)
+ {
+ goto Exit;
+ }
+ }
+
+ if (NameOverflow)
+ {
+ ErrorCode = ERROR_MORE_DATA;
+ goto Exit;
+ }
+
+ /* Convert the name string */
+ RtlUnicodeToMultiByteN(lpName, *lpcbName, lpcbName, NameBuffer, NameBufferSize *
sizeof(WCHAR));
+ ((PSTR)lpName)[*lpcbName] = '\0';
+
+Exit:
+ if (NameBuffer)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer);
+
+ return ErrorCode;
}