diff options
author | Sky <git@bunnies.cc> | 2013-10-06 19:54:52 +0100 |
---|---|---|
committer | Sky <git@bunnies.cc> | 2013-10-06 19:54:52 +0100 |
commit | 17c98655f86f8ea41c4528e3fc25d12388a36861 (patch) | |
tree | 38591551b6bfe792ffd287ec68831b9801e0260e | |
parent | d5e4802adef575d1d2d20a3e6e5addd4b5f4d2ca (diff) | |
download | MultiMC-17c98655f86f8ea41c4528e3fc25d12388a36861.tar MultiMC-17c98655f86f8ea41c4528e3fc25d12388a36861.tar.gz MultiMC-17c98655f86f8ea41c4528e3fc25d12388a36861.tar.lz MultiMC-17c98655f86f8ea41c4528e3fc25d12388a36861.tar.xz MultiMC-17c98655f86f8ea41c4528e3fc25d12388a36861.zip |
First draft of multiple Java installation detection on Windows
-rw-r--r-- | gui/settingsdialog.cpp | 4 | ||||
-rw-r--r-- | gui/settingsdialog.ui | 18 | ||||
-rw-r--r-- | logic/JavaUtils.cpp | 129 | ||||
-rw-r--r-- | logic/JavaUtils.h | 20 |
4 files changed, 122 insertions, 49 deletions
diff --git a/gui/settingsdialog.cpp b/gui/settingsdialog.cpp index c6fe893d..011925b7 100644 --- a/gui/settingsdialog.cpp +++ b/gui/settingsdialog.cpp @@ -185,9 +185,9 @@ void SettingsDialog::loadSettings(SettingsObject *s) void SettingsDialog::on_pushButton_clicked() { JavaUtils jut; - QStringList paths = jut.FindJavaPath(); + auto javas = jut.FindJavaPaths(); - ui->javaPathTextBox->setText(paths.at(0)); + ui->javaPathTextBox->setText(std::get<JI_PATH>(javas.at(0))); } void SettingsDialog::on_btnBrowse_clicked() diff --git a/gui/settingsdialog.ui b/gui/settingsdialog.ui index d7a134fb..8fa5e96e 100644 --- a/gui/settingsdialog.ui +++ b/gui/settingsdialog.ui @@ -374,6 +374,12 @@ <layout class="QGridLayout" name="gridLayout_3"> <item row="0" column="0"> <widget class="QLabel" name="labelJavaPath"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="text"> <string>Java path:</string> </property> @@ -381,6 +387,12 @@ </item> <item row="2" column="0"> <widget class="QLabel" name="labelJVMArgs"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="text"> <string>JVM arguments:</string> </property> @@ -402,9 +414,6 @@ <item row="0" column="1" colspan="3"> <widget class="QLineEdit" name="javaPathTextBox"/> </item> - <item row="2" column="1" colspan="3"> - <widget class="QLineEdit" name="jvmArgsTextBox"/> - </item> <item row="1" column="2"> <widget class="QPushButton" name="pushButton"> <property name="sizePolicy"> @@ -418,6 +427,9 @@ </property> </widget> </item> + <item row="2" column="1" colspan="3"> + <widget class="QLineEdit" name="jvmArgsTextBox"/> + </item> </layout> </widget> </item> 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 <QStringList> @@ -22,27 +21,33 @@ #include <QDir> #include <logger/QsLog.h> -#if WINDOWS -#include <windows.h> +JavaUtils::JavaUtils() +{ -#endif +} -JavaUtils::JavaUtils() +std::vector<java_install> JavaUtils::GetDefaultJava() { + std::vector<java_install> javas; + javas.push_back(std::make_tuple("java", "unknown", "java", false)); + return javas; } #if WINDOWS -QStringList JavaUtils::FindJavaPath() +std::vector<java_install> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString keyName) { - QStringList paths; + std::vector<java_install> 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<java_install> JavaUtils::FindJavaPaths() +{ + std::vector<java_install> JRE64s = this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment"); + std::vector<java_install> JDK64s = this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Development Kit"); + std::vector<java_install> JRE32s = this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment"); + std::vector<java_install> JDK32s = this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Development Kit"); + + std::vector<java_install> 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<JI_REC>(java)) sRec = "(Recommended)"; + QLOG_INFO() << std::get<JI_ID>(java) << std::get<JI_ARCH>(java) << " at " << std::get<JI_PATH>(java) << sRec; } - return paths; + return javas; } #elif OSX -QStringList JavaUtils::FindJavaPath() +std::vector<java_install> 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<java_install> 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<java_install> JavaUtils::FindJavaPath() { QLOG_INFO() << "Unknown operating system build - defaulting to \"java\""; - QStringList paths; - paths << "java"; - - return paths; + return this->GetDefaultPath(); } #endif diff --git a/logic/JavaUtils.h b/logic/JavaUtils.h index fef2a1bf..63daac12 100644 --- a/logic/JavaUtils.h +++ b/logic/JavaUtils.h @@ -17,10 +17,28 @@ #include <QStringList> +#include "osutils.h" + +#if WINDOWS + #include <windows.h> +#endif + +#define JI_ID 0 +#define JI_ARCH 1 +#define JI_PATH 2 +#define JI_REC 3 +typedef std::tuple<QString, QString, QString, bool> java_install; + class JavaUtils { public: JavaUtils(); - QStringList FindJavaPath(); + std::vector<java_install> FindJavaPaths(); + +private: + std::vector<java_install> GetDefaultJava(); +#if WINDOWS + std::vector<java_install> FindJavaFromRegistryKey(DWORD keyType, QString keyName); +#endif }; |