From 17c98655f86f8ea41c4528e3fc25d12388a36861 Mon Sep 17 00:00:00 2001 From: Sky Date: Sun, 6 Oct 2013 19:54:52 +0100 Subject: First draft of multiple Java installation detection on Windows --- logic/JavaUtils.cpp | 129 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 86 insertions(+), 43 deletions(-) (limited to 'logic/JavaUtils.cpp') diff --git a/logic/JavaUtils.cpp b/logic/JavaUtils.cpp index 1cfd0a77..91fa271c 100644 --- a/logic/JavaUtils.cpp +++ b/logic/JavaUtils.cpp @@ -14,7 +14,6 @@ */ #include "JavaUtils.h" -#include "osutils.h" #include "pathutils.h" #include @@ -22,27 +21,33 @@ #include #include -#if WINDOWS -#include +JavaUtils::JavaUtils() +{ -#endif +} -JavaUtils::JavaUtils() +std::vector JavaUtils::GetDefaultJava() { + std::vector javas; + javas.push_back(std::make_tuple("java", "unknown", "java", false)); + return javas; } #if WINDOWS -QStringList JavaUtils::FindJavaPath() +std::vector JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString keyName) { - QStringList paths; + std::vector javas; + + QString archType = "unknown"; + if(keyType == KEY_WOW64_64KEY) archType = "64"; + else if(keyType == KEY_WOW64_32KEY) archType = "32"; HKEY jreKey; - QString jreKeyName = "SOFTWARE\\JavaSoft\\Java Runtime Environment"; - if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, jreKeyName.toStdString().c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &jreKey) == ERROR_SUCCESS) + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyName.toStdString().c_str(), 0, KEY_READ | keyType | KEY_ENUMERATE_SUB_KEYS, &jreKey) == ERROR_SUCCESS) { - // Read the current JRE version from the registry. - // This will be used to find the key that contains the JavaHome value. + // Read the current type version from the registry. + // This will be used to find any key that contains the JavaHome value. char *value = new char[0]; DWORD valueSz = 0; if (RegQueryValueExA(jreKey, "CurrentVersion", NULL, NULL, (BYTE*)value, &valueSz) == ERROR_MORE_DATA) @@ -51,64 +56,102 @@ QStringList JavaUtils::FindJavaPath() RegQueryValueExA(jreKey, "CurrentVersion", NULL, NULL, (BYTE*)value, &valueSz); } - RegCloseKey(jreKey); + QString recommended = value; + + TCHAR subKeyName[255]; + DWORD subKeyNameSize, numSubKeys, retCode; + + // Get the number of subkeys + RegQueryInfoKey(jreKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - // Now open the registry key for the JRE version that we just got. - jreKeyName.append("\\").append(value); - if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, jreKeyName.toStdString().c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &jreKey) == ERROR_SUCCESS) + // Iterate until RegEnumKeyEx fails + if(numSubKeys > 0) { - // Read the JavaHome value to find where Java is installed. - value = new char[0]; - valueSz = 0; - if (RegQueryValueExA(jreKey, "JavaHome", NULL, NULL, (BYTE*)value, &valueSz) == ERROR_MORE_DATA) + for(int i = 0; i < numSubKeys; i++) { - value = new char[valueSz]; - RegQueryValueExA(jreKey, "JavaHome", NULL, NULL, (BYTE*)value, &valueSz); - - paths << QDir(PathCombine(value, "bin")).absoluteFilePath("java.exe"); + subKeyNameSize = 255; + retCode = RegEnumKeyEx(jreKey, i, subKeyName, &subKeyNameSize, NULL, NULL, NULL, NULL); + if(retCode == ERROR_SUCCESS) + { + // Now open the registry key for the version that we just got. + QString newKeyName = keyName + "\\" + subKeyName; + + HKEY newKey; + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, newKeyName.toStdString().c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &newKey) == ERROR_SUCCESS) + { + // Read the JavaHome value to find where Java is installed. + value = new char[0]; + valueSz = 0; + if (RegQueryValueEx(newKey, "JavaHome", NULL, NULL, (BYTE*)value, &valueSz) == ERROR_MORE_DATA) + { + value = new char[valueSz]; + RegQueryValueEx(newKey, "JavaHome", NULL, NULL, (BYTE*)value, &valueSz); + + javas.push_back(std::make_tuple(subKeyName, archType, QDir(PathCombine(value, "bin")).absoluteFilePath("java.exe"), (recommended == subKeyName))); + } + + RegCloseKey(newKey); + } + } } - - RegCloseKey(jreKey); } + + RegCloseKey(jreKey); } - if(paths.length() <= 0) + return javas; +} + +std::vector JavaUtils::FindJavaPaths() +{ + std::vector JRE64s = this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment"); + std::vector JDK64s = this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Development Kit"); + std::vector JRE32s = this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment"); + std::vector JDK32s = this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Development Kit"); + + std::vector javas; + javas.insert(javas.end(), JRE64s.begin(), JRE64s.end()); + javas.insert(javas.end(), JDK64s.begin(), JDK64s.end()); + javas.insert(javas.end(), JRE32s.begin(), JRE32s.end()); + javas.insert(javas.end(), JDK32s.begin(), JDK32s.end()); + + if(javas.size() <= 0) { QLOG_WARN() << "Failed to find Java in the Windows registry - defaulting to \"java\""; - paths << "java"; + return this->GetDefaultJava(); + } + + QLOG_INFO() << "Found the following Java installations (64 -> 32, JRE -> JDK): "; + + for(auto &java : javas) + { + QString sRec; + if(std::get(java)) sRec = "(Recommended)"; + QLOG_INFO() << std::get(java) << std::get(java) << " at " << std::get(java) << sRec; } - return paths; + return javas; } #elif OSX -QStringList JavaUtils::FindJavaPath() +std::vector JavaUtils::FindJavaPath() { QLOG_INFO() << "OS X Java detection incomplete - defaulting to \"java\""; - QStringList paths; - paths << "java"; - - return paths; + return this->GetDefaultPath(); } #elif LINUX -QStringList JavaUtils::FindJavaPath() +std::vector JavaUtils::FindJavaPath() { QLOG_INFO() << "Linux Java detection incomplete - defaulting to \"java\""; - QStringList paths; - paths << "java"; - - return paths; + return this->GetDefaultPath(); } #else -QStringList JavaUtils::FindJavaPath() +std::vector JavaUtils::FindJavaPath() { QLOG_INFO() << "Unknown operating system build - defaulting to \"java\""; - QStringList paths; - paths << "java"; - - return paths; + return this->GetDefaultPath(); } #endif -- cgit v1.2.3