Fixed RegEnumValueA/W behaviour when output buffers are too small. This
fixes 20+ tests from "advapi32_test registry" (now it has only 2
failures - but that's a reduced tests set!).
I beg my pardon for reformatting these two funcs and fixing bugs in one
commit, I will do it in different commits in the future.
Modified: trunk/reactos/lib/advapi32/reg/reg.c
_____
Modified: trunk/reactos/lib/advapi32/reg/reg.c
--- trunk/reactos/lib/advapi32/reg/reg.c 2005-04-30 21:07:32 UTC
(rev 14890)
+++ trunk/reactos/lib/advapi32/reg/reg.c 2005-04-30 21:11:34 UTC
(rev 14891)
@@ -850,166 +850,163 @@
LPDWORD lpcbClass,
PFILETIME lpftLastWriteTime)
{
- union
- {
- KEY_NODE_INFORMATION Node;
- KEY_BASIC_INFORMATION Basic;
- } *KeyInfo;
+ union
+ {
+ KEY_NODE_INFORMATION Node;
+ KEY_BASIC_INFORMATION Basic;
+ } *KeyInfo;
- UNICODE_STRING StringU;
- ANSI_STRING StringA;
- LONG ErrorCode = ERROR_SUCCESS;
- DWORD NameLength;
- DWORD ClassLength = 0;
- DWORD BufferSize;
- DWORD ResultSize;
- HANDLE KeyHandle;
- NTSTATUS Status;
+ UNICODE_STRING StringU;
+ ANSI_STRING StringA;
+ LONG ErrorCode = ERROR_SUCCESS;
+ DWORD NameLength;
+ DWORD ClassLength = 0;
+ DWORD BufferSize;
+ DWORD ResultSize;
+ HANDLE KeyHandle;
+ NTSTATUS Status;
- DPRINT("RegEnumKeyExA(hKey 0x%x, dwIndex %d, lpName 0x%x, *lpcbName
%d, lpClass 0x%x, lpcbClass %d)\n",
- hKey, dwIndex, lpName, *lpcbName, lpClass, lpcbClass ?
*lpcbClass : 0);
+ DPRINT("RegEnumKeyExA(hKey 0x%x, dwIndex %d, lpName 0x%x,
*lpcbName %d, lpClass 0x%x, lpcbClass %d)\n",
+ hKey, dwIndex, lpName, *lpcbName, lpClass, lpcbClass ?
*lpcbClass : 0);
- if ((lpClass) && (!lpcbClass))
- {
- SetLastError (ERROR_INVALID_PARAMETER);
- return ERROR_INVALID_PARAMETER;
- }
+ if ((lpClass) && (!lpcbClass))
+ {
+ SetLastError (ERROR_INVALID_PARAMETER);
+ return ERROR_INVALID_PARAMETER;
+ }
- Status = MapDefaultKey(&KeyHandle,
- hKey);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
- }
+ Status = MapDefaultKey(&KeyHandle, hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ ErrorCode = RtlNtStatusToDosError (Status);
+ SetLastError (ErrorCode);
+ return ErrorCode;
+ }
- if (*lpcbName > 0)
- {
- NameLength = min (*lpcbName - 1 , REG_MAX_NAME_SIZE) * sizeof
(WCHAR);
- }
- else
- {
- NameLength = 0;
- }
-
- if (lpClass)
- {
- if (*lpcbClass > 0)
+ if (*lpcbName > 0)
{
- ClassLength = min (*lpcbClass -1, REG_MAX_NAME_SIZE) *
sizeof(WCHAR);
+ NameLength = min (*lpcbName - 1 , REG_MAX_NAME_SIZE) *
sizeof (WCHAR);
}
- else
+ else
{
- ClassLength = 0;
+ NameLength = 0;
}
- /* The class name should start at a dword boundary */
- BufferSize = ((sizeof(KEY_NODE_INFORMATION) + NameLength + 3) &
~3) + ClassLength;
- }
- else
- {
- BufferSize = sizeof(KEY_BASIC_INFORMATION) + NameLength;
- }
+ if (lpClass)
+ {
+ if (*lpcbClass > 0)
+ {
+ ClassLength = min (*lpcbClass -1,
REG_MAX_NAME_SIZE) * sizeof(WCHAR);
+ }
+ else
+ {
+ ClassLength = 0;
+ }
- KeyInfo = RtlAllocateHeap (ProcessHeap,
- 0,
- BufferSize);
- if (KeyInfo == NULL)
- {
- SetLastError (ERROR_OUTOFMEMORY);
- return ERROR_OUTOFMEMORY;
- }
-
- Status = NtEnumerateKey (KeyHandle,
- (ULONG)dwIndex,
- lpClass == NULL ? KeyBasicInformation :
KeyNodeInformation,
- KeyInfo,
- BufferSize,
- &ResultSize);
- DPRINT("NtEnumerateKey() returned status 0x%X\n", Status);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- }
- else
- {
- if (lpClass == NULL)
+ /* The class name should start at a dword boundary */
+ BufferSize = ((sizeof(KEY_NODE_INFORMATION) + NameLength
+ 3) & ~3) + ClassLength;
+ }
+ else
{
- if (KeyInfo->Basic.NameLength > NameLength)
- {
- ErrorCode = ERROR_BUFFER_OVERFLOW;
- }
- else
- {
- StringU.Buffer = KeyInfo->Basic.Name;
- StringU.Length = KeyInfo->Basic.NameLength;
- StringU.MaximumLength = KeyInfo->Basic.NameLength;
- }
+ BufferSize = sizeof(KEY_BASIC_INFORMATION) + NameLength;
}
- else
+
+ KeyInfo = RtlAllocateHeap (ProcessHeap, 0, BufferSize);
+ if (KeyInfo == NULL)
{
- if (KeyInfo->Node.NameLength > NameLength ||
- KeyInfo->Node.ClassLength > ClassLength)
- {
- ErrorCode = ERROR_BUFFER_OVERFLOW;
- }
- else
- {
- StringA.Buffer = lpClass;
- StringA.Length = 0;
- StringA.MaximumLength = *lpcbClass;
- StringU.Buffer = (PWCHAR)((ULONG_PTR)KeyInfo->Node.Name +
KeyInfo->Node.ClassOffset);
- StringU.Length = KeyInfo->Node.ClassLength;
- StringU.MaximumLength = KeyInfo->Node.ClassLength;
- RtlUnicodeStringToAnsiString (&StringA, &StringU, FALSE);
- lpClass[StringA.Length] = 0;
- *lpcbClass = StringA.Length;
- StringU.Buffer = KeyInfo->Node.Name;
- StringU.Length = KeyInfo->Node.NameLength;
- StringU.MaximumLength = KeyInfo->Node.NameLength;
- }
+ SetLastError (ERROR_OUTOFMEMORY);
+ return ERROR_OUTOFMEMORY;
}
- if (ErrorCode == ERROR_SUCCESS)
+ Status = NtEnumerateKey (KeyHandle,
+
(ULONG)dwIndex,
+ lpClass
== NULL ? KeyBasicInformation : KeyNodeInformation,
+ KeyInfo,
+
BufferSize,
+
&ResultSize);
+ DPRINT("NtEnumerateKey() returned status 0x%X\n", Status);
+ if (!NT_SUCCESS(Status))
{
- StringA.Buffer = lpName;
- StringA.Length = 0;
- StringA.MaximumLength = *lpcbName;
- RtlUnicodeStringToAnsiString (&StringA, &StringU, FALSE);
- lpName[StringA.Length] = 0;
- *lpcbName = StringA.Length;
- if (lpftLastWriteTime != NULL)
- {
- if (lpClass == NULL)
+ ErrorCode = RtlNtStatusToDosError (Status);
+ }
+ else
+ {
+ if (lpClass == NULL)
{
- lpftLastWriteTime->dwLowDateTime =
KeyInfo->Basic.LastWriteTime.u.LowPart;
- lpftLastWriteTime->dwHighDateTime =
KeyInfo->Basic.LastWriteTime.u.HighPart;
+ if (KeyInfo->Basic.NameLength > NameLength)
+ {
+ ErrorCode = ERROR_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ StringU.Buffer = KeyInfo->Basic.Name;
+ StringU.Length =
KeyInfo->Basic.NameLength;
+ StringU.MaximumLength =
KeyInfo->Basic.NameLength;
+ }
}
- else
+ else
{
- lpftLastWriteTime->dwLowDateTime =
KeyInfo->Node.LastWriteTime.u.LowPart;
- lpftLastWriteTime->dwHighDateTime =
KeyInfo->Node.LastWriteTime.u.HighPart;
+ if (KeyInfo->Node.NameLength > NameLength ||
+ KeyInfo->Node.ClassLength > ClassLength)
+ {
+ ErrorCode = ERROR_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ StringA.Buffer = lpClass;
+ StringA.Length = 0;
+ StringA.MaximumLength = *lpcbClass;
+ StringU.Buffer =
(PWCHAR)((ULONG_PTR)KeyInfo->Node.Name + KeyInfo->Node.ClassOffset);
+ StringU.Length =
KeyInfo->Node.ClassLength;
+ StringU.MaximumLength =
KeyInfo->Node.ClassLength;
+ RtlUnicodeStringToAnsiString (&StringA,
&StringU, FALSE);
+ lpClass[StringA.Length] = 0;
+ *lpcbClass = StringA.Length;
+ StringU.Buffer = KeyInfo->Node.Name;
+ StringU.Length =
KeyInfo->Node.NameLength;
+ StringU.MaximumLength =
KeyInfo->Node.NameLength;
+ }
}
- }
+
+ if (ErrorCode == ERROR_SUCCESS)
+ {
+ StringA.Buffer = lpName;
+ StringA.Length = 0;
+ StringA.MaximumLength = *lpcbName;
+ RtlUnicodeStringToAnsiString (&StringA,
&StringU, FALSE);
+ lpName[StringA.Length] = 0;
+ *lpcbName = StringA.Length;
+ if (lpftLastWriteTime != NULL)
+ {
+ if (lpClass == NULL)
+ {
+ lpftLastWriteTime->dwLowDateTime
= KeyInfo->Basic.LastWriteTime.u.LowPart;
+
lpftLastWriteTime->dwHighDateTime =
KeyInfo->Basic.LastWriteTime.u.HighPart;
+ }
+ else
+ {
+ lpftLastWriteTime->dwLowDateTime
= KeyInfo->Node.LastWriteTime.u.LowPart;
+
lpftLastWriteTime->dwHighDateTime =
KeyInfo->Node.LastWriteTime.u.HighPart;
+ }
+ }
+ }
}
- }
- DPRINT("Key Namea0 Length %d\n", StringU.Length);
- DPRINT("Key Namea1 Length %d\n", NameLength);
- DPRINT("Key Namea Length %d\n", *lpcbName);
- DPRINT("Key Namea %s\n", lpName);
+ DPRINT("Key Namea0 Length %d\n", StringU.Length);
+ DPRINT("Key Namea1 Length %d\n", NameLength);
+ DPRINT("Key Namea Length %d\n", *lpcbName);
+ DPRINT("Key Namea %s\n", lpName);
- RtlFreeHeap (ProcessHeap,
- 0,
- KeyInfo);
+ RtlFreeHeap (ProcessHeap,
+ 0,
+ KeyInfo);
- if (ErrorCode != ERROR_SUCCESS)
- {
- SetLastError(ErrorCode);
- }
+ if (ErrorCode != ERROR_SUCCESS)
+ {
+ SetLastError(ErrorCode);
+ }
- return ErrorCode;
+ return ErrorCode;
}
@@ -1174,161 +1171,222 @@
RegEnumValueA (HKEY hKey,
DWORD dwIndex,
LPSTR lpValueName,
- LPDWORD lpcbValueName,
+ LPDWORD lpcbValueName, // lpValueName buffer len
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
- LPDWORD lpcbData)
+ LPDWORD lpcbData) // lpData buffer len
{
- union
- {
- KEY_VALUE_FULL_INFORMATION Full;
- KEY_VALUE_BASIC_INFORMATION Basic;
- } *ValueInfo;
+ union
+ {
+ KEY_VALUE_FULL_INFORMATION Full;
+ KEY_VALUE_BASIC_INFORMATION Basic;
+ } *ValueInfo;
- ULONG NameLength;
- ULONG BufferSize;
- ULONG DataLength = 0;
- ULONG ResultSize;
- HANDLE KeyHandle;
- LONG ErrorCode;
- NTSTATUS Status;
- UNICODE_STRING StringU;
- ANSI_STRING StringA;
- BOOL IsStringType;
+ ULONG NameLength;
+ ULONG BufferSize;
+ ULONG DataLength = 0;
+ ULONG ResultSize;
+ HANDLE KeyHandle;
+ LONG ErrorCode;
+ NTSTATUS Status;
+ UNICODE_STRING StringU;
+ ANSI_STRING StringA;
+ BOOL IsStringType;
- ErrorCode = ERROR_SUCCESS;
+ ErrorCode = ERROR_SUCCESS;
- Status = MapDefaultKey (&KeyHandle,
- hKey);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
- }
+ Status = MapDefaultKey (&KeyHandle, hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ ErrorCode = RtlNtStatusToDosError (Status);
+ SetLastError (ErrorCode);
+ return ErrorCode;
+ }
- if (*lpcbValueName > 0)
- {
- NameLength = min (*lpcbValueName - 1, REG_MAX_NAME_SIZE) *
sizeof(WCHAR);
- }
- else
- {
- NameLength = 0;
- }
+ if (*lpcbValueName > 0)
+ NameLength = min (*lpcbValueName - 1, REG_MAX_NAME_SIZE)
* sizeof(WCHAR);
+ else
+ NameLength = 0;
- if (lpData)
- {
- DataLength = min (*lpcbData * sizeof(WCHAR), REG_MAX_DATA_SIZE);
- BufferSize = ((sizeof(KEY_VALUE_FULL_INFORMATION) + NameLength +
3) & ~3) + DataLength;
- }
- else
- {
- BufferSize = sizeof(KEY_VALUE_BASIC_INFORMATION) + NameLength;
- }
+ if (lpData)
+ {
+ DataLength = min (*lpcbData * sizeof(WCHAR),
REG_MAX_DATA_SIZE);
+ BufferSize = ((sizeof(KEY_VALUE_FULL_INFORMATION) +
NameLength + 3) & ~3) + DataLength;
+ }
+ else
+ {
+ BufferSize = sizeof(KEY_VALUE_BASIC_INFORMATION) +
NameLength;
+ }
- ValueInfo = RtlAllocateHeap (ProcessHeap,
- 0,
- BufferSize);
- if (ValueInfo == NULL)
- {
- SetLastError(ERROR_OUTOFMEMORY);
- return ERROR_OUTOFMEMORY;
- }
+ ValueInfo = RtlAllocateHeap (ProcessHeap, 0, BufferSize);
+ if (ValueInfo == NULL)
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return ERROR_OUTOFMEMORY;
+ }
- Status = NtEnumerateValueKey (KeyHandle,
- (ULONG)dwIndex,
- lpData ? KeyValueFullInformation :
KeyValueBasicInformation,
- ValueInfo,
- BufferSize,
- &ResultSize);
+ Status = NtEnumerateValueKey (KeyHandle,
+ (ULONG)dwIndex,
+ lpData ? KeyValueFullInformation :
KeyValueBasicInformation,
+ ValueInfo,
+ BufferSize,
+ &ResultSize);
- DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- }
- else
- {
- if (lpData)
- {
- IsStringType = (ValueInfo->Full.Type == REG_SZ) ||
- (ValueInfo->Full.Type == REG_MULTI_SZ) ||
- (ValueInfo->Full.Type == REG_EXPAND_SZ);
- if (ValueInfo->Full.NameLength > NameLength ||
- (!IsStringType && ValueInfo->Full.DataLength > *lpcbData)
||
- ValueInfo->Full.DataLength > DataLength)
- {
- ErrorCode = ERROR_BUFFER_OVERFLOW;
- }
- else
- {
- if (IsStringType)
- {
- StringU.Buffer = (PWCHAR)((ULONG_PTR)ValueInfo +
ValueInfo->Full.DataOffset);
- StringU.Length = ValueInfo->Full.DataLength;
- StringU.MaximumLength = DataLength;
- StringA.Buffer = (PCHAR)lpData;
- StringA.Length = 0;
- StringA.MaximumLength = *lpcbData;
- RtlUnicodeStringToAnsiString (&StringA,
- &StringU,
- FALSE);
- *lpcbData = StringA.Length;
- }
- else
+ DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
+ if (!NT_SUCCESS(Status))
+ {
+ ErrorCode = RtlNtStatusToDosError (Status);
+
+ // handle case when BufferSize was too small
+ // we must let caller know the minimum accepted size
+ // and value type
+ if (Status == STATUS_BUFFER_OVERFLOW || Status ==
STATUS_BUFFER_TOO_SMALL)
{
- RtlCopyMemory (lpData,
- (PVOID)((ULONG_PTR)ValueInfo +
ValueInfo->Full.DataOffset),
- ValueInfo->Full.DataLength);
- *lpcbData = ValueInfo->Full.DataLength;
+ ErrorCode = ERROR_MORE_DATA;
+
+ // query now with the sufficient buffer size
+ RtlFreeHeap (ProcessHeap, 0, ValueInfo);
+ BufferSize = ResultSize;
+ ValueInfo = RtlAllocateHeap (ProcessHeap, 0,
BufferSize); // will be freed at the bottom, as usual
+ if (ValueInfo == NULL)
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return ERROR_OUTOFMEMORY;
+ }
+
+ Status = NtEnumerateValueKey (KeyHandle,
+
(ULONG)dwIndex,
+
lpData ? KeyValueFullInformation : KeyValueBasicInformation,
+
ValueInfo,
+
BufferSize,
+
&ResultSize);
+ if (!NT_SUCCESS(Status))
+ {
+ // ok, some other error
+ ErrorCode = RtlNtStatusToDosError
(Status);
+ }
+ else
+ {
+ // we have information now, pass it to
the caller
+ // but don't touch valueName length here
+ IsStringType = (ValueInfo->Full.Type ==
REG_SZ) ||
+
(ValueInfo->Full.Type == REG_MULTI_SZ) ||
+
(ValueInfo->Full.Type == REG_EXPAND_SZ); //FIXME: Include REG_LINK ?
+
+ if (lpData)
+ {
+ if (lpcbData)
+ {
+ if (IsStringType)
+ *lpcbData =
ValueInfo->Full.DataLength / sizeof(WCHAR);
+ else
+ *lpcbData =
ValueInfo->Full.DataLength;
+ }
+ }
+
+ // pass type also
+ if (lpType)
+ *lpType = lpData ?
ValueInfo->Full.Type : ValueInfo->Basic.Type;
+ }
}
-
- StringU.Buffer = ValueInfo->Full.Name;
- StringU.Length = ValueInfo->Full.NameLength;
- StringU.MaximumLength = NameLength;
- }
}
- else
+ else
{
- if (ValueInfo->Basic.NameLength > NameLength)
- {
- ErrorCode = ERROR_BUFFER_OVERFLOW;
- }
- else
- {
- StringU.Buffer = ValueInfo->Basic.Name;
- StringU.Length = ValueInfo->Basic.NameLength;
- StringU.MaximumLength = NameLength;
- }
- }
+ if (lpData)
+ {
+ IsStringType = (ValueInfo->Full.Type == REG_SZ)
||
+ (ValueInfo->Full.Type == REG_MULTI_SZ)
||
+ (ValueInfo->Full.Type == REG_EXPAND_SZ);
+ if (ValueInfo->Full.NameLength > NameLength
||
+ (!IsStringType &&
ValueInfo->Full.DataLength > *lpcbData) ||
+ ValueInfo->Full.DataLength > DataLength)
+ {
+ // overflow data
+ ErrorCode = ERROR_MORE_DATA;
- if (ErrorCode == ERROR_SUCCESS)
- {
- StringA.Buffer = (PCHAR)lpValueName;
- StringA.Length = 0;
- StringA.MaximumLength = *lpcbValueName;
- RtlUnicodeStringToAnsiString (&StringA,
- &StringU,
- FALSE);
- StringA.Buffer[StringA.Length] = 0;
- *lpcbValueName = StringA.Length;
- if (lpType)
- {
- *lpType = lpData ? ValueInfo->Full.Type :
ValueInfo->Basic.Type;
- }
+ // return correct information for data
length and type
+ if (lpcbData)
+ {
+ if (IsStringType)
+ *lpcbData =
ValueInfo->Full.DataLength / sizeof(WCHAR);
+ else
+ *lpcbData =
ValueInfo->Full.DataLength;
+ }
+
+ if (lpType)
+ *lpType = ValueInfo->Full.Type;
+ }
+ else
+ {
+ if (IsStringType)
+ {
+ StringU.Buffer =
(PWCHAR)((ULONG_PTR)ValueInfo + ValueInfo->Full.DataOffset);
+ StringU.Length =
ValueInfo->Full.DataLength;
+ StringU.MaximumLength =
DataLength;
+ StringA.Buffer = (PCHAR)lpData;
+ StringA.Length = 0;
+ StringA.MaximumLength =
*lpcbData;
+ RtlUnicodeStringToAnsiString
(&StringA, &StringU, FALSE);
+ *lpcbData = StringA.Length;
+ }
+ else
+ {
+ RtlCopyMemory (lpData,
+
(PVOID)((ULONG_PTR)ValueInfo + ValueInfo->Full.DataOffset),
+
ValueInfo->Full.DataLength);
+ *lpcbData =
ValueInfo->Full.DataLength;
+ }
+
+ StringU.Buffer = ValueInfo->Full.Name;
+ StringU.Length =
ValueInfo->Full.NameLength;
+ StringU.MaximumLength = NameLength;
+ }
+ }
+ else
+ {
+ if (ValueInfo->Basic.NameLength > NameLength)
+ {
+ // overflow name
+ ErrorCode = ERROR_MORE_DATA;
+
+ if (IsStringType)
+ *lpcbData =
ValueInfo->Full.DataLength / sizeof(WCHAR);
+ else
+ *lpcbData =
ValueInfo->Full.DataLength;
+
+ if (lpType)
+ *lpType = ValueInfo->Basic.Type;
+ }
+ else
+ {
+ StringU.Buffer = ValueInfo->Basic.Name;
+ StringU.Length =
ValueInfo->Basic.NameLength;
+ StringU.MaximumLength = NameLength;
+ }
+ }
+
+ if (ErrorCode == ERROR_SUCCESS)
+ {
+ StringA.Buffer = (PCHAR)lpValueName;
+ StringA.Length = 0;
+ StringA.MaximumLength = *lpcbValueName;
+ RtlUnicodeStringToAnsiString (&StringA,
&StringU, FALSE);
+ StringA.Buffer[StringA.Length] = 0;
+ *lpcbValueName = StringA.Length;
+ if (lpType)
+ {
+ *lpType = lpData ? ValueInfo->Full.Type
: ValueInfo->Basic.Type;
+ }
+ }
}
- }
- RtlFreeHeap (ProcessHeap,
- 0,
- ValueInfo);
- if (ErrorCode != ERROR_SUCCESS)
- {
- SetLastError(ErrorCode);
- }
+ RtlFreeHeap (ProcessHeap, 0, ValueInfo);
- return ErrorCode;
+ if (ErrorCode != ERROR_SUCCESS)
+ SetLastError(ErrorCode);
+
+ return ErrorCode;
}
@@ -1347,127 +1405,170 @@
LPBYTE lpData,
LPDWORD lpcbData)
{
- union
- {
- KEY_VALUE_FULL_INFORMATION Full;
- KEY_VALUE_BASIC_INFORMATION Basic;
- } *ValueInfo;
+ union
+ {
+ KEY_VALUE_FULL_INFORMATION Full;
+ KEY_VALUE_BASIC_INFORMATION Basic;
+ } *ValueInfo;
- ULONG NameLength;
- ULONG BufferSize;
- ULONG DataLength = 0;
- ULONG ResultSize;
- HANDLE KeyHandle;
- LONG ErrorCode;
- NTSTATUS Status;
+ ULONG NameLength;
+ ULONG BufferSize;
+ ULONG DataLength = 0;
+ ULONG ResultSize;
+ HANDLE KeyHandle;
+ LONG ErrorCode;
+ NTSTATUS Status;
- ErrorCode = ERROR_SUCCESS;
+ ErrorCode = ERROR_SUCCESS;
- Status = MapDefaultKey (&KeyHandle,
- hKey);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- SetLastError (ErrorCode);
- return ErrorCode;
- }
+ Status = MapDefaultKey (&KeyHandle, hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ ErrorCode = RtlNtStatusToDosError (Status);
+ SetLastError (ErrorCode);
+ return ErrorCode;
+ }
- if (*lpcbValueName > 0)
- {
- NameLength = min (*lpcbValueName - 1, REG_MAX_NAME_SIZE) *
sizeof(WCHAR);
- }
- else
- {
- NameLength = 0;
- }
+ if (*lpcbValueName > 0)
+ NameLength = min (*lpcbValueName - 1, REG_MAX_NAME_SIZE)
* sizeof(WCHAR);
+ else
+ NameLength = 0;
- if (lpData)
- {
- DataLength = min(*lpcbData, REG_MAX_DATA_SIZE);
- BufferSize = ((sizeof(KEY_VALUE_FULL_INFORMATION) + NameLength +
3) & ~3) + DataLength;
- }
- else
- {
- BufferSize = sizeof(KEY_VALUE_BASIC_INFORMATION) + NameLength;
- }
- ValueInfo = RtlAllocateHeap (ProcessHeap,
- 0,
- BufferSize);
- if (ValueInfo == NULL)
- {
- SetLastError (ERROR_OUTOFMEMORY);
- return ERROR_OUTOFMEMORY;
- }
- Status = NtEnumerateValueKey (KeyHandle,
- (ULONG)dwIndex,
- lpData ? KeyValueFullInformation :
KeyValueBasicInformation,
- ValueInfo,
- BufferSize,
- &ResultSize);
-
- DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- }
- else
- {
- if (lpData)
+ if (lpData)
{
- if (ValueInfo->Full.DataLength > DataLength ||
- ValueInfo->Full.NameLength > NameLength)
- {
- ErrorCode = ERROR_BUFFER_OVERFLOW;
- }
- else
- {
- RtlCopyMemory (lpValueName,
- ValueInfo->Full.Name,
- ValueInfo->Full.NameLength);
- *lpcbValueName = (DWORD)(ValueInfo->Full.NameLength /
sizeof(WCHAR));
- lpValueName[*lpcbValueName] = 0;
- RtlCopyMemory (lpData,
- (PVOID)((ULONG_PTR)ValueInfo +
ValueInfo->Full.DataOffset),
- ValueInfo->Full.DataLength);
- *lpcbData = (DWORD)ValueInfo->Full.DataLength;
- }
+ DataLength = min(*lpcbData, REG_MAX_DATA_SIZE);
+ BufferSize = ((sizeof(KEY_VALUE_FULL_INFORMATION) +
NameLength + 3) & ~3) + DataLength;
}
- else
+ else
{
- if (ValueInfo->Basic.NameLength > NameLength)
- {
- ErrorCode = ERROR_BUFFER_OVERFLOW;
- }
- else
- {
- RtlCopyMemory (lpValueName,
- ValueInfo->Basic.Name,
- ValueInfo->Basic.NameLength);
- *lpcbValueName = (DWORD)(ValueInfo->Basic.NameLength /
sizeof(WCHAR));
- lpValueName[*lpcbValueName] = 0;
- }
- if (NULL != lpcbData)
- {
- *lpcbData = (DWORD)ValueInfo->Full.DataLength;
- }
+ BufferSize = sizeof(KEY_VALUE_BASIC_INFORMATION) +
NameLength;
}
+ ValueInfo = RtlAllocateHeap (ProcessHeap, 0, BufferSize);
+ if (ValueInfo == NULL)
+ {
+ SetLastError (ERROR_OUTOFMEMORY);
+ return ERROR_OUTOFMEMORY;
+ }
+ Status = NtEnumerateValueKey (KeyHandle,
+ (ULONG)dwIndex,
+ lpData ? KeyValueFullInformation :
KeyValueBasicInformation,
+ ValueInfo,
+ BufferSize,
+ &ResultSize);
- if (ErrorCode == ERROR_SUCCESS && lpType != NULL)
+ DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
+ if (!NT_SUCCESS(Status))
{
- *lpType = lpData ? ValueInfo->Full.Type :
ValueInfo->Basic.Type;
+ ErrorCode = RtlNtStatusToDosError (Status);
+
+ // handle case when BufferSize was too small
+ // we must let caller know the minimum accepted size
+ // and value type
+ if (Status == STATUS_BUFFER_OVERFLOW || Status ==
STATUS_BUFFER_TOO_SMALL)
+ {
+ ErrorCode = ERROR_MORE_DATA;
+
+ // query now with the sufficient buffer size
+ RtlFreeHeap (ProcessHeap, 0, ValueInfo);
+ BufferSize = ResultSize;
+ ValueInfo = RtlAllocateHeap (ProcessHeap, 0,
BufferSize); // will be freed at the bottom, as usual
+ if (ValueInfo == NULL)
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return ERROR_OUTOFMEMORY;
+ }
+
+ Status = NtEnumerateValueKey (KeyHandle,
+
(ULONG)dwIndex,
+
lpData ? KeyValueFullInformation : KeyValueBasicInformation,
+
ValueInfo,
+
BufferSize,
+
&ResultSize);
+ if (!NT_SUCCESS(Status))
+ {
+ // ok, some other error
+ ErrorCode = RtlNtStatusToDosError
(Status);
+ }
+ else
+ {
+ // we have information now, pass it to
the caller
+ // but don't touch valueName length here
+ if (lpData && lpcbData)
+ *lpcbData =
ValueInfo->Full.DataLength;
+
+ // pass type also
+ if (lpType)
+ *lpType = lpData ?
ValueInfo->Full.Type : ValueInfo->Basic.Type;
+ }
+ }
}
- }
+ else
+ {
+ if (lpData)
+ {
+ if (ValueInfo->Full.DataLength > DataLength ||
+ ValueInfo->Full.NameLength > NameLength)
+ {
+ // overflow data
+ ErrorCode = ERROR_MORE_DATA;
- RtlFreeHeap (ProcessHeap,
- 0,
- ValueInfo);
+ // return correct information for data
length and type
+ if (lpcbData)
+ *lpcbData =
ValueInfo->Full.DataLength;
- if (ErrorCode != ERROR_SUCCESS)
- {
- SetLastError (ErrorCode);
- }
+ if (lpType)
+ *lpType = ValueInfo->Full.Type;
+ }
+ else
+ {
+ RtlCopyMemory (lpValueName,
ValueInfo->Full.Name, ValueInfo->Full.NameLength);
+ *lpcbValueName =
(DWORD)(ValueInfo->Full.NameLength / sizeof(WCHAR));
+ lpValueName[*lpcbValueName] = 0;
+ RtlCopyMemory (lpData,
+ (PVOID)((ULONG_PTR)ValueInfo +
ValueInfo->Full.DataOffset),
+ ValueInfo->Full.DataLength);
+ *lpcbData =
(DWORD)ValueInfo->Full.DataLength;
+ }
+ }
+ else
+ {
+ if (ValueInfo->Basic.NameLength > NameLength)
+ {
+ // overflow name
+ ErrorCode = ERROR_MORE_DATA;
- return ErrorCode;
+ if (lpcbData)
+ *lpcbData =
ValueInfo->Full.DataLength;
+
+ if (lpType)
+ *lpType = ValueInfo->Basic.Type;
+ }
+ else
+ {
+ RtlCopyMemory (lpValueName,
ValueInfo->Basic.Name, ValueInfo->Basic.NameLength);
+ *lpcbValueName =
(DWORD)(ValueInfo->Basic.NameLength / sizeof(WCHAR));
+ lpValueName[*lpcbValueName] = 0;
+ }
+
+ if (NULL != lpcbData)
+ {
+ *lpcbData =
(DWORD)ValueInfo->Full.DataLength;
+ DPRINT1("BUG: Using ValueInfo as FULL
when it is really BASIC\n");
+ }
+ }
+
+ if (ErrorCode == ERROR_SUCCESS && lpType != NULL)
+ {
+ *lpType = lpData ? ValueInfo->Full.Type :
ValueInfo->Basic.Type;
+ }
+ }
+
+ RtlFreeHeap (ProcessHeap, 0, ValueInfo);
+
+ if (ErrorCode != ERROR_SUCCESS)
+ SetLastError (ErrorCode);
+
+ return ErrorCode;
}
@@ -1741,7 +1842,7 @@
{
ErrorCode = RtlNtStatusToDosError (Status);
SetLastError (ErrorCode);
- return ErrorCode;
+ return Status;
}
RtlCreateUnicodeStringFromAsciiz (&SubKeyString,
@@ -1796,7 +1897,7 @@
{
ErrorCode = RtlNtStatusToDosError (Status);
SetLastError (ErrorCode);
- return ErrorCode;
+ return Status;
}
RtlInitUnicodeString (&SubKeyString,