void FDesktopPlatformWindows::EnumerateEngineInstallations(TMap<FString, FString> &OutInstallations)
{
	// Enumerate the binary installations
	EnumerateLauncherEngineInstallations(OutInstallations);

	// Enumerate the per-user installations
	HKEY hKey;
	if (RegOpenKeyEx(HKEY_CURRENT_USER, InstallationsSubKey, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
	{
		// Get a list of all the directories
		TArray<FString> UniqueDirectories;
		OutInstallations.GenerateValueArray(UniqueDirectories);

		// Enumerate all the installations
		TArray<FString> InvalidKeys;
		for (::DWORD Index = 0;; Index++)
		{
			TCHAR ValueName[256];
			TCHAR ValueData[MAX_PATH];
			::DWORD ValueType = 0;
			::DWORD ValueNameLength = sizeof(ValueName) / sizeof(ValueName[0]);
			::DWORD ValueDataSize = sizeof(ValueData);

			LRESULT Result = RegEnumValue(hKey, Index, ValueName, &ValueNameLength, NULL, &ValueType, (BYTE*)&ValueData[0], &ValueDataSize);
			if(Result == ERROR_SUCCESS)
			{
				int32 ValueDataLength = ValueDataSize / sizeof(TCHAR);
				if(ValueDataLength > 0 && ValueData[ValueDataLength - 1] == 0) ValueDataLength--;

				FString NormalizedInstalledDirectory(ValueDataLength, ValueData);
				FPaths::NormalizeDirectoryName(NormalizedInstalledDirectory);
				FPaths::CollapseRelativeDirectories(NormalizedInstalledDirectory);

				if(IsValidRootDirectory(NormalizedInstalledDirectory) && !UniqueDirectories.Contains(NormalizedInstalledDirectory))
				{
					OutInstallations.Add(ValueName, NormalizedInstalledDirectory);
					UniqueDirectories.Add(NormalizedInstalledDirectory);
				}
				else
				{
					InvalidKeys.Add(ValueName);
				}
			}
			else if(Result == ERROR_NO_MORE_ITEMS)
			{
				break;
			}
		}

		// Remove all the keys which weren't valid
		for(const FString InvalidKey: InvalidKeys)
		{
			RegDeleteValue(hKey, *InvalidKey);
		}

		RegCloseKey(hKey);
	}
}
void FDesktopPlatformWindows::EnumerateEngineInstallations(TMap<FString, FString> &OutInstallations)
{
	// Enumerate the binary installations
	EnumerateLauncherEngineInstallations(OutInstallations);

	// Enumerate the per-user installations
	HKEY hKey;
	if (RegOpenKeyEx(HKEY_CURRENT_USER, InstallationsSubKey, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
	{
		// Enumerate all the installations
		for (::DWORD Index = 0;; Index++)
		{
			TCHAR ValueName[256];
			TCHAR ValueData[MAX_PATH];
			::DWORD ValueType = 0;
			::DWORD ValueNameLength = sizeof(ValueName) / sizeof(ValueName[0]);
			::DWORD ValueDataSize = sizeof(ValueData);

			LRESULT Result = RegEnumValue(hKey, Index, ValueName, &ValueNameLength, NULL, &ValueType, (BYTE*)&ValueData[0], &ValueDataSize);
			if(Result == ERROR_SUCCESS)
			{
				int32 ValueDataLength = ValueDataSize / sizeof(TCHAR);
				if(ValueDataLength > 0 && ValueData[ValueDataLength - 1] == 0) ValueDataLength--;

				FString NormalizedInstalledDirectory(ValueDataLength, ValueData);
				FPaths::NormalizeDirectoryName(NormalizedInstalledDirectory);
				OutInstallations.Add(ValueName, NormalizedInstalledDirectory);
			}
			else if(Result == ERROR_NO_MORE_ITEMS)
			{
				break;
			}
		}

		// Trim the list to everything that's valid
		for(TMap<FString, FString>::TIterator Iter(OutInstallations); Iter; ++Iter)
		{
			if (!IsValidRootDirectory(Iter.Value()))
			{
				RegDeleteValue(hKey, *Iter.Key());
				Iter.RemoveCurrent();
			}
		}

		RegCloseKey(hKey);
	}
}