Author: jgardou
Date: Wed Oct 1 22:51:44 2014
New Revision: 64445
URL:
http://svn.reactos.org/svn/reactos?rev=64445&view=rev
Log:
[ADVAPI32]
- Fix a stupid crash I introduced in RegQueryValueExA
- Reimplement RegEnumKeyExA as wrapper around RegEnumKeyExW
- Implement RegEnumKeyExW for HKCR subkeys
- Fix a few potential handle leaks
CORE-8582
Modified:
trunk/reactos/dll/win32/advapi32/reg/hkcr.c
trunk/reactos/dll/win32/advapi32/reg/reg.c
trunk/reactos/dll/win32/advapi32/reg/reg.h
Modified: trunk/reactos/dll/win32/advapi32/reg/hkcr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/advapi32/reg/hkc…
==============================================================================
--- trunk/reactos/dll/win32/advapi32/reg/hkcr.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/advapi32/reg/hkcr.c [iso-8859-1] Wed Oct 1 22:51:44 2014
@@ -263,7 +263,7 @@
}
/* See if the subkey already exists in HKCU. */
- ErrorCode = RegOpenKeyExW(QueriedKey, lpSubKey, 0, KEY_READ, &TestKey);
+ ErrorCode = RegOpenKeyExW(QueriedKey, lpSubKey, 0, 0, &TestKey);
if (ErrorCode != ERROR_FILE_NOT_FOUND)
{
if (ErrorCode == ERROR_SUCCESS)
@@ -585,3 +585,217 @@
return ErrorCode;
}
+
+/* HKCR version of RegEnumKeyExW */
+LONG
+WINAPI
+EnumHKCRKey(
+ _In_ HKEY hKey,
+ _In_ DWORD dwIndex,
+ _Out_ LPWSTR lpName,
+ _Inout_ LPDWORD lpcbName,
+ _Reserved_ LPDWORD lpReserved,
+ _Out_opt_ LPWSTR lpClass,
+ _Inout_opt_ LPDWORD lpcbClass,
+ _Out_opt_ PFILETIME lpftLastWriteTime)
+{
+ HKEY PreferredKey, FallbackKey;
+ DWORD NumPreferredSubKeys;
+ DWORD MaxFallbackSubKeyLen;
+ DWORD FallbackIndex;
+ WCHAR* FallbackSubKeyName = NULL;
+ LONG ErrorCode;
+
+ ASSERT(IsHKCRKey(hKey));
+
+ /* Remove the HKCR flag while we're working */
+ hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
+
+ /* Get the preferred key */
+ ErrorCode = GetPreferredHKCRKey(hKey, &PreferredKey);
+ if (ErrorCode != ERROR_SUCCESS)
+ {
+ if (ErrorCode == ERROR_FILE_NOT_FOUND)
+ {
+ /* Only the HKLM key exists */
+ return RegEnumKeyExW(
+ hKey,
+ dwIndex,
+ lpName,
+ lpcbName,
+ lpReserved,
+ lpClass,
+ lpcbClass,
+ lpftLastWriteTime);
+ }
+ return ErrorCode;
+ }
+
+ /* Get the fallback key */
+ ErrorCode = GetFallbackHKCRKey(hKey, &FallbackKey, FALSE);
+ if (ErrorCode != ERROR_SUCCESS)
+ {
+ if (PreferredKey != hKey)
+ RegCloseKey(PreferredKey);
+ if (ErrorCode == ERROR_FILE_NOT_FOUND)
+ {
+ /* Only the HKCU key exists */
+ return RegEnumKeyExW(
+ hKey,
+ dwIndex,
+ lpName,
+ lpcbName,
+ lpReserved,
+ lpClass,
+ lpcbClass,
+ lpftLastWriteTime);
+ }
+ return ErrorCode;
+ }
+
+ /* Get some info on the HKCU side */
+ ErrorCode = RegQueryInfoKeyW(
+ PreferredKey,
+ NULL,
+ NULL,
+ NULL,
+ &NumPreferredSubKeys,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (ErrorCode != ERROR_SUCCESS)
+ goto Exit;
+
+ if (dwIndex < NumPreferredSubKeys)
+ {
+ /* HKCU side takes precedence */
+ ErrorCode = RegEnumKeyExW(
+ PreferredKey,
+ dwIndex,
+ lpName,
+ lpcbName,
+ lpReserved,
+ lpClass,
+ lpcbClass,
+ lpftLastWriteTime);
+ goto Exit;
+ }
+
+ /* Here it gets tricky. We must enumerate the values from the HKLM side,
+ * without reporting those which are present on the HKCU side */
+
+ /* Squash out the indices from HKCU */
+ dwIndex -= NumPreferredSubKeys;
+
+ /* Get some info */
+ ErrorCode = RegQueryInfoKeyW(
+ FallbackKey,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &MaxFallbackSubKeyLen,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (ErrorCode != ERROR_SUCCESS)
+ {
+ ERR("Could not query info of key %p (Err: %d)\n", FallbackKey,
ErrorCode);
+ goto Exit;
+ }
+
+ ERR("Maxfallbacksubkeylen: %d\n", MaxFallbackSubKeyLen);
+
+ /* Allocate our buffer */
+ FallbackSubKeyName = RtlAllocateHeap(
+ RtlGetProcessHeap(), 0, (MaxFallbackSubKeyLen + 1) * sizeof(WCHAR));
+ if (!FallbackSubKeyName)
+ {
+ ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ goto Exit;
+ }
+
+ /* We must begin at the very first subkey of the fallback key,
+ * and then see if we meet keys that already are in the preferred key.
+ * In that case, we must bump dwIndex, as otherwise we would enumerate a key we
already
+ * saw in a previous call.
+ */
+ FallbackIndex = 0;
+ while (TRUE)
+ {
+ HKEY PreferredSubKey;
+ DWORD FallbackSubkeyLen = MaxFallbackSubKeyLen;
+
+ /* Try enumerating */
+ ErrorCode = RegEnumKeyExW(
+ FallbackKey,
+ FallbackIndex,
+ FallbackSubKeyName,
+ &FallbackSubkeyLen,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (ErrorCode != ERROR_SUCCESS)
+ {
+ /* Most likely ERROR_NO_MORE_ITEMS */
+ ERR("Returning %d.\n", ErrorCode);
+ goto Exit;
+ }
+ FallbackSubKeyName[FallbackSubkeyLen] = L'\0';
+
+ /* See if there is such a value on HKCU side */
+ ErrorCode = RegOpenKeyExW(
+ PreferredKey,
+ FallbackSubKeyName,
+ 0,
+ 0,
+ &PreferredSubKey);
+
+ if (ErrorCode == ERROR_SUCCESS)
+ {
+ RegCloseKey(PreferredSubKey);
+ /* So we already enumerated it on HKCU side. */
+ dwIndex++;
+ }
+ else if (ErrorCode != ERROR_FILE_NOT_FOUND)
+ {
+ ERR("Got error %d while querying for %s on HKCU side.\n",
ErrorCode, FallbackSubKeyName);
+ goto Exit;
+ }
+
+ /* See if we caught up */
+ if (FallbackIndex == dwIndex)
+ break;
+
+ FallbackIndex++;
+ }
+
+ /* We can finally enumerate on the fallback side */
+ ErrorCode = RegEnumKeyExW(
+ FallbackKey,
+ dwIndex,
+ lpName,
+ lpcbName,
+ lpReserved,
+ lpClass,
+ lpcbClass,
+ lpftLastWriteTime);
+
+Exit:
+ if (PreferredKey != hKey)
+ RegCloseKey(PreferredKey);
+ if (FallbackKey != hKey)
+ RegCloseKey(FallbackKey);
+ if (FallbackSubKeyName)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, FallbackSubKeyName);
+
+ return ErrorCode;
+}
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] Wed Oct 1 22:51:44 2014
@@ -1306,7 +1306,11 @@
}
if (IsHKCRKey(ParentKey))
- return DeleteHKCRKey(ParentKey, lpSubKey, samDesired, Reserved);
+ {
+ LONG ErrorCode = DeleteHKCRKey(ParentKey, lpSubKey, samDesired, Reserved);
+ ClosePredefKey(ParentKey);
+ return ErrorCode;
+ }
if (samDesired & KEY_WOW64_32KEY)
ERR("Wow64 not yet supported!\n");
@@ -2442,166 +2446,81 @@
*
* @implemented
*/
-LONG WINAPI
-RegEnumKeyExA(HKEY hKey,
- DWORD dwIndex,
- LPSTR lpName,
- LPDWORD lpcbName,
- LPDWORD lpReserved,
- LPSTR lpClass,
- LPDWORD lpcbClass,
- PFILETIME lpftLastWriteTime)
-{
- 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;
- ULONG ResultSize;
- HANDLE KeyHandle;
- NTSTATUS Status;
-
- TRACE("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))
- {
- return ERROR_INVALID_PARAMETER;
- }
-
- Status = MapDefaultKey(&KeyHandle, hKey);
- if (!NT_SUCCESS(Status))
- {
- return RtlNtStatusToDosError(Status);
- }
-
+LONG
+WINAPI
+RegEnumKeyExA(
+ _In_ HKEY hKey,
+ _In_ DWORD dwIndex,
+ _Out_ LPSTR lpName,
+ _Inout_ LPDWORD lpcbName,
+ _Reserved_ LPDWORD lpReserved,
+ _Out_opt_ LPSTR lpClass,
+ _Inout_opt_ LPDWORD lpcbClass,
+ _Out_opt_ PFILETIME lpftLastWriteTime)
+{
+ WCHAR* NameBuffer = NULL;
+ WCHAR* ClassBuffer = NULL;
+ DWORD NameLength, ClassLength;
+ LONG ErrorCode;
+
+ /* Allocate our buffers */
if (*lpcbName > 0)
{
- NameLength = min (*lpcbName - 1 , REG_MAX_NAME_SIZE) * sizeof (WCHAR);
- }
- else
- {
- NameLength = 0;
+ NameLength = *lpcbName;
+ NameBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, *lpcbName * sizeof(WCHAR));
+ if (NameBuffer == NULL)
+ {
+ ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ goto Exit;
+ }
}
if (lpClass)
{
if (*lpcbClass > 0)
{
- ClassLength = min (*lpcbClass -1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
- }
- else
- {
- ClassLength = 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;
- }
-
- KeyInfo = RtlAllocateHeap (ProcessHeap, 0, BufferSize);
- if (KeyInfo == NULL)
- {
- ErrorCode = ERROR_OUTOFMEMORY;
- goto Cleanup;
- }
-
- Status = NtEnumerateKey(KeyHandle,
- (ULONG)dwIndex,
- lpClass == NULL ? KeyBasicInformation : KeyNodeInformation,
- KeyInfo,
- BufferSize,
- &ResultSize);
- TRACE("NtEnumerateKey() returned status 0x%X\n", Status);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- }
- else
- {
- if (lpClass == NULL)
- {
- if (KeyInfo->Basic.NameLength > NameLength)
+ ClassLength = *lpcbClass;
+ ClassBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, *lpcbClass *
sizeof(WCHAR));
+ if (ClassBuffer == NULL)
{
- ErrorCode = ERROR_BUFFER_OVERFLOW;
+ ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ goto Exit;
}
- else
- {
- StringU.Buffer = KeyInfo->Basic.Name;
- StringU.Length = KeyInfo->Basic.NameLength;
- StringU.MaximumLength = KeyInfo->Basic.NameLength;
- }
- }
- else
- {
- 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;
- }
- }
- }
- }
-
- /*TRACE("Key Namea0 Length %d\n", StringU.Length);*/ /* BUGBUG could be
uninitialized */
- TRACE("Key Name1 Length %d\n", NameLength);
- TRACE("Key Name Length %d\n", *lpcbName);
- TRACE("Key Name %s\n", lpName);
-
- RtlFreeHeap(ProcessHeap,
- 0,
- KeyInfo);
-
-Cleanup:
- ClosePredefKey(KeyHandle);
+ }
+ }
+
+ /* Do the actual call */
+ ErrorCode = RegEnumKeyExW(
+ hKey,
+ dwIndex,
+ NameBuffer,
+ lpcbName,
+ lpReserved,
+ ClassBuffer,
+ lpcbClass,
+ lpftLastWriteTime);
+
+ if (ErrorCode != ERROR_SUCCESS)
+ goto Exit;
+
+ /* Convert the strings */
+ RtlUnicodeToMultiByteN(lpName, *lpcbName, 0, NameBuffer, *lpcbName * sizeof(WCHAR));
+ /* NULL terminate if we can */
+ if (NameLength > *lpcbName)
+ lpName[*lpcbName] = '\0';
+
+ if (lpClass)
+ {
+ RtlUnicodeToMultiByteN(lpClass, *lpcbClass, 0, NameBuffer, *lpcbClass *
sizeof(WCHAR));
+ if (ClassLength > *lpcbClass)
+ lpClass[*lpcbClass] = '\0';
+ }
+
+Exit:
+ if (NameBuffer)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer);
+ if (ClassBuffer)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, ClassBuffer);
return ErrorCode;
}
@@ -2612,15 +2531,17 @@
*
* @implemented
*/
-LONG WINAPI
-RegEnumKeyExW(HKEY hKey,
- DWORD dwIndex,
- LPWSTR lpName,
- LPDWORD lpcbName,
- LPDWORD lpReserved,
- LPWSTR lpClass,
- LPDWORD lpcbClass,
- PFILETIME lpftLastWriteTime)
+LONG
+WINAPI
+RegEnumKeyExW(
+ _In_ HKEY hKey,
+ _In_ DWORD dwIndex,
+ _Out_ LPWSTR lpName,
+ _Inout_ LPDWORD lpcbName,
+ _Reserved_ LPDWORD lpReserved,
+ _Out_opt_ LPWSTR lpClass,
+ _Inout_opt_ LPDWORD lpcbClass,
+ _Out_opt_ PFILETIME lpftLastWriteTime)
{
union
{
@@ -2641,6 +2562,21 @@
if (!NT_SUCCESS(Status))
{
return RtlNtStatusToDosError(Status);
+ }
+
+ if (IsHKCRKey(KeyHandle))
+ {
+ ErrorCode = EnumHKCRKey(
+ KeyHandle,
+ dwIndex,
+ lpName,
+ lpcbName,
+ lpReserved,
+ lpClass,
+ lpcbClass,
+ lpftLastWriteTime);
+ ClosePredefKey(KeyHandle);
+ return ErrorCode;
}
if (*lpcbName > 0)
@@ -3419,7 +3355,11 @@
}
if (IsHKCRKey(KeyHandle))
- return OpenHKCRKey(KeyHandle, lpSubKey, ulOptions, samDesired, phkResult);
+ {
+ ErrorCode = OpenHKCRKey(KeyHandle, lpSubKey, ulOptions, samDesired, phkResult);
+ ClosePredefKey(KeyHandle);
+ return ErrorCode;
+ }
if (ulOptions & REG_OPTION_OPEN_LINK)
Attributes |= OBJ_OPENLINK;
@@ -4035,7 +3975,7 @@
ErrorCode = RegQueryValueExW(hkeyorg, nameW.Buffer, NULL, &LocalType, NULL,
&BufferSize);
if (ErrorCode != ERROR_SUCCESS)
{
- if (!data)
+ if ((!data) && count)
*count = 0;
RtlFreeUnicodeString(&nameW);
return ErrorCode;
Modified: trunk/reactos/dll/win32/advapi32/reg/reg.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/advapi32/reg/reg…
==============================================================================
--- trunk/reactos/dll/win32/advapi32/reg/reg.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/advapi32/reg/reg.h [iso-8859-1] Wed Oct 1 22:51:44 2014
@@ -72,3 +72,15 @@
_In_ CONST BYTE* Data,
_In_ DWORD DataSize);
+LONG
+WINAPI
+EnumHKCRKey(
+ _In_ HKEY hKey,
+ _In_ DWORD dwIndex,
+ _Out_ LPWSTR lpName,
+ _Inout_ LPDWORD lpcbName,
+ _Reserved_ LPDWORD lpReserved,
+ _Out_opt_ LPWSTR lpClass,
+ _Inout_opt_ LPDWORD lpcbClass,
+ _Out_opt_ PFILETIME lpftLastWriteTime);
+