diff --git a/HMCLauncher/HMCL/HMCL.cpp b/HMCLauncher/HMCL/HMCL.cpp
deleted file mode 100644
index 94c42fbbb..000000000
Binary files a/HMCLauncher/HMCL/HMCL.cpp and /dev/null differ
diff --git a/HMCLauncher/HMCL/HMCL.h b/HMCLauncher/HMCL/HMCL.h
deleted file mode 100644
index c4aafa38e..000000000
Binary files a/HMCLauncher/HMCL/HMCL.h and /dev/null differ
diff --git a/HMCLauncher/HMCL/HMCL.vcxproj b/HMCLauncher/HMCL/HMCL.vcxproj
index 9b6e9113d..03e8ac938 100644
--- a/HMCLauncher/HMCL/HMCL.vcxproj
+++ b/HMCLauncher/HMCL/HMCL.vcxproj
@@ -23,7 +23,7 @@
{672B1019-E741-4C0D-A986-627E2ACE157B}
Win32Proj
HMCL
- 8.1
+ 7.0
@@ -152,19 +152,25 @@
-
+
+
+
+
-
+
+
+
Create
Create
Create
Create
+
diff --git a/HMCLauncher/HMCL/HMCL.vcxproj.filters b/HMCLauncher/HMCL/HMCL.vcxproj.filters
index 04ebb26dd..e4fb0ec74 100644
--- a/HMCLauncher/HMCL/HMCL.vcxproj.filters
+++ b/HMCLauncher/HMCL/HMCL.vcxproj.filters
@@ -24,7 +24,16 @@
头文件
-
+
+ 头文件
+
+
+ 头文件
+
+
+ 头文件
+
+
头文件
@@ -32,7 +41,16 @@
源文件
-
+
+ 源文件
+
+
+ 源文件
+
+
+ 源文件
+
+
源文件
diff --git a/HMCLauncher/HMCL/Version.cpp b/HMCLauncher/HMCL/Version.cpp
new file mode 100644
index 000000000..a8b0279a6
--- /dev/null
+++ b/HMCLauncher/HMCL/Version.cpp
@@ -0,0 +1,15 @@
+#include "stdafx.h"
+#include "Version.h"
+
+Version::Version(const std::wstring & rawString)
+{
+ int idx = 0;
+ ver[0] = ver[1] = ver[2] = ver[3] = 0;
+ for (auto &i : rawString)
+ {
+ if (idx >= 4) break;
+ if (i == '.') ++idx;
+ else if (i == '_') ++idx;
+ else if (isdigit(i)) ver[idx] = ver[idx] * 10 + (i - L'0');
+ }
+}
diff --git a/HMCLauncher/HMCL/Version.h b/HMCLauncher/HMCL/Version.h
new file mode 100644
index 000000000..2e0784d16
--- /dev/null
+++ b/HMCLauncher/HMCL/Version.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include
+
+class Version
+{
+public:
+ int ver[4];
+
+ Version(const std::wstring &rawString);
+
+ bool operator<(const Version &other) const
+ {
+ for (int i = 0; i < 4; ++i)
+ if (ver[i] != other.ver[i])
+ return ver[i] < other.ver[i];
+ return false;
+ }
+};
+
diff --git a/HMCLauncher/HMCL/java.cpp b/HMCLauncher/HMCL/java.cpp
new file mode 100644
index 000000000..93e806e66
--- /dev/null
+++ b/HMCLauncher/HMCL/java.cpp
@@ -0,0 +1,88 @@
+#include "stdafx.h"
+#include "java.h"
+#include "os.h"
+
+const Version JAVA_8(L"1.8"), JAVA_11(L"11");
+
+const LPCWSTR JDK_OLD = L"SOFTWARE\\JavaSoft\\Java Development Kit";
+const LPCWSTR JRE_OLD = L"SOFTWARE\\JavaSoft\\Java Runtime Environment";
+const LPCWSTR JDK_NEW = L"SOFTWARE\\JavaSoft\\JDK";
+const LPCWSTR JRE_NEW = L"SOFTWARE\\JavaSoft\\JRE";
+
+bool oldJavaFound = false, newJavaFound = false;
+
+bool FindJavaByRegistryKey(HKEY rootKey, LPCWSTR subKey, std::wstring & path)
+{
+ WCHAR javaVer[MAX_KEY_LENGTH]; // buffer for subkey name, special for JavaVersion
+ DWORD cbName; // size of name string
+ DWORD cSubKeys = 0; // number of subkeys
+ DWORD cbMaxSubKey; // longest subkey size
+ DWORD cValues; // number of values for key
+ DWORD cchMaxValue; // longest value name
+ DWORD cbMaxValueData; // longest value data
+ LSTATUS result;
+
+ HKEY hKey;
+ if (ERROR_SUCCESS != (result = RegOpenKeyEx(rootKey, subKey, 0, KEY_WOW64_64KEY | KEY_READ, &hKey)))
+ return false;
+
+ RegQueryInfoKey(
+ hKey, // key handle
+ NULL, // buffer for class name
+ NULL, // size of class string
+ NULL, // reserved
+ &cSubKeys, // number of subkeys
+ &cbMaxSubKey, // longest subkey size
+ NULL, // longest class string
+ &cValues, // number of values for this key
+ &cchMaxValue, // longest value name
+ &cbMaxValueData, // longest value data
+ NULL, // security descriptor
+ NULL); // last write time
+
+ if (!cSubKeys)
+ return false;
+
+ bool flag = false;
+ for (DWORD i = 0; i < cSubKeys; ++i)
+ {
+ cbName = MAX_KEY_LENGTH;
+ if (ERROR_SUCCESS != (result = RegEnumKeyEx(hKey, i, javaVer, &cbName, NULL, NULL, NULL, NULL)))
+ continue;
+
+ HKEY javaKey;
+ if (ERROR_SUCCESS != RegOpenKeyEx(hKey, javaVer, 0, KEY_READ, &javaKey))
+ continue;
+
+ if (ERROR_SUCCESS == MyRegQueryValue(javaKey, L"JavaHome", REG_SZ, path))
+ {
+ if (Version(javaVer) < JAVA_8)
+ oldJavaFound = true;
+ else if (!(Version(javaVer) < JAVA_11))
+ newJavaFound = true;
+ else
+ flag = true;
+ }
+
+ if (flag)
+ break;
+ }
+
+ RegCloseKey(hKey);
+
+ return flag;
+}
+
+bool FindJavaInRegistry(std::wstring & path)
+{
+ return FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JDK_OLD, path) ||
+ FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JRE_OLD, path) ||
+ FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JDK_NEW, path) ||
+ FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JRE_NEW, path);
+}
+
+bool FindJava(std::wstring & path)
+{
+ return FindJavaInRegistry(path) ||
+ ERROR_SUCCESS == MyGetEnvironmentVariable(L"JAVA_HOME", path);
+}
diff --git a/HMCLauncher/HMCL/java.h b/HMCLauncher/HMCL/java.h
new file mode 100644
index 000000000..86e96ecd3
--- /dev/null
+++ b/HMCLauncher/HMCL/java.h
@@ -0,0 +1,10 @@
+#pragma once
+#include
+#include
+#include "Version.h"
+
+// Find Java installation in system registry
+bool FindJavaInRegistry(std::wstring &path);
+
+// Find Java Installation in registry and environment variable
+bool FindJava(std::wstring &path);
diff --git a/HMCLauncher/HMCL/main.cpp b/HMCLauncher/HMCL/main.cpp
new file mode 100644
index 000000000..61fd58e7a
--- /dev/null
+++ b/HMCLauncher/HMCL/main.cpp
@@ -0,0 +1,79 @@
+#include "stdafx.h"
+#include "main.h"
+#include "os.h"
+#include "java.h"
+
+using namespace std;
+
+
+void LaunchJVM(const wstring &javaPath, const wstring &jarPath)
+{
+ if (MyCreateProcess(L"\"" + javaPath + L"\" -XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=15 -jar \"" + jarPath + L"\""))
+ exit(EXIT_SUCCESS);
+}
+
+int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
+{
+ wstring path, exeName;
+
+ // Since Jar file is appended to this executable, we should first get the location of JAR file.
+ if (ERROR_SUCCESS != MyGetModuleFileName(NULL, exeName))
+ return 1;
+
+
+ // First try the Java packaged together.
+ bool is64Bit = false;
+ GetArch(is64Bit); // if failed to determine architecture of operating system, consider 32-bit.
+
+ if (is64Bit)
+ {
+ LaunchJVM(L"jre-x64\\bin\\javaw.exe", exeName);
+ }
+ else
+ {
+ LaunchJVM(L"jre-x86\\bin\\javaw.exe", exeName);
+ }
+
+ if (FindJava(path))
+ LaunchJVM(path + L"\\bin\\javaw.exe", exeName);
+
+ // Try java in PATH
+ LaunchJVM(L"javaw", exeName);
+
+ // Or we try to search Java in C:\Program Files.
+ {
+ WIN32_FIND_DATA data;
+ HANDLE hFind = FindFirstFile(L"C:\\Program Files\\Java\\*", &data); // Search all subdirectory
+
+ if (hFind != INVALID_HANDLE_VALUE) {
+ do {
+ wstring javaw = wstring(L"C:\\Program Files\\Java\\") + data.cFileName + wstring(L"\\bin\\javaw.exe");
+ if (FindFirstFileExists(javaw.c_str(), 0)) {
+ LaunchJVM(javaw, exeName);
+ }
+ } while (FindNextFile(hFind, &data));
+ FindClose(hFind);
+ }
+ }
+
+ // Consider C:\Program Files (x86)\Java
+ {
+ WIN32_FIND_DATA data;
+ HANDLE hFind = FindFirstFile(L"C:\\Program Files (x86)\\Java\\*", &data); // Search all subdirectory
+
+ if (hFind != INVALID_HANDLE_VALUE) {
+ do {
+ wstring javaw = wstring(L"C:\\Program Files (x86)\\Java\\") + data.cFileName + L"\\bin\\javaw.exe";
+ if (FindFirstFileExists(javaw.c_str(), 0)) {
+ LaunchJVM(javaw, exeName);
+ }
+ } while (FindNextFile(hFind, &data));
+ FindClose(hFind);
+ }
+ }
+
+ MessageBox(NULL, L"Java installation cannot be found in this computer, please download it from https://java.com \n"
+ L"未能在这台电脑上找到Java 8~Java 10,请从 https://java.com 下载安装Java", L"Error", MB_ICONERROR | MB_OK);
+ ShellExecute(0, 0, L"https://java.com/", 0, 0, SW_SHOW);
+ return 1;
+}
diff --git a/HMCLauncher/HMCL/main.h b/HMCLauncher/HMCL/main.h
new file mode 100644
index 000000000..e60f2eb7e
--- /dev/null
+++ b/HMCLauncher/HMCL/main.h
@@ -0,0 +1,3 @@
+#pragma once
+
+#include "resource.h"
diff --git a/HMCLauncher/HMCL/os.cpp b/HMCLauncher/HMCL/os.cpp
new file mode 100644
index 000000000..820e53819
--- /dev/null
+++ b/HMCLauncher/HMCL/os.cpp
@@ -0,0 +1,108 @@
+#include "stdafx.h"
+#include "os.h"
+
+using namespace std;
+
+LSTATUS MyRegQueryValue(HKEY hKey, LPCWSTR subKey, DWORD dwType, wstring &out)
+{
+ DWORD dwSize = 0;
+ LSTATUS ret = RegQueryValueEx(hKey, subKey, 0, &dwType, NULL, &dwSize);
+ if (ret != ERROR_SUCCESS) return ret;
+ WCHAR *buffer = new WCHAR[dwSize];
+ ret = RegQueryValueEx(hKey, subKey, 0, &dwType, (LPBYTE)buffer, &dwSize);
+ if (ret != ERROR_SUCCESS) return ret;
+ out = buffer;
+ delete[] buffer;
+ return ERROR_SUCCESS;
+}
+
+LSTATUS MyGetModuleFileName(HMODULE hModule, std::wstring &out)
+{
+ DWORD res, size = MAX_PATH;
+ out = wstring();
+ out.resize(size);
+ while ((res = GetModuleFileName(hModule, &out[0], size)) == size)
+ {
+ out.resize(size += MAX_PATH);
+ }
+ if (res == 0)
+ return GetLastError();
+ else
+ {
+ out.resize(size - MAX_PATH + res);
+ return ERROR_SUCCESS;
+ }
+}
+
+LSTATUS MyGetEnvironmentVariable(LPCWSTR name, std::wstring & out)
+{
+ DWORD res, size = MAX_PATH;
+ out = wstring();
+ out.resize(size);
+ while ((res = GetEnvironmentVariable(name, &out[0], size)) == size)
+ {
+ out.resize(size += MAX_PATH);
+ }
+ if (res == 0)
+ return GetLastError();
+ else
+ {
+ out.resize(size - MAX_PATH + res);
+ return ERROR_SUCCESS;
+ }
+}
+
+bool MyCreateProcess(const std::wstring &command)
+{
+ wstring writable_command = command;
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ si.cb = sizeof(si);
+ ZeroMemory(&si, sizeof(si));
+ ZeroMemory(&pi, sizeof(pi));
+
+ return (CreateProcess(NULL, &writable_command[0], NULL, NULL, false, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi));
+}
+
+bool FindFirstFileExists(LPCWSTR lpPath, DWORD dwFilter)
+{
+ WIN32_FIND_DATA fd;
+ HANDLE hFind = FindFirstFile(lpPath, &fd);
+ bool bFilter = (false == dwFilter) ? true : fd.dwFileAttributes & dwFilter;
+ bool ret = ((hFind != INVALID_HANDLE_VALUE) && bFilter) ? true : false;
+ FindClose(hFind);
+ return ret;
+}
+
+bool GetArch(bool & is64Bit)
+{
+#if _WIN64
+ isWindows64bit = true;
+ return true;
+#elif _WIN32
+ typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
+
+ BOOL isWow64 = FALSE;
+
+ // IsWow64Process is not available on all supported versions of Windows.
+ // Use GetModuleHandle to get a handle to the DLL that contains the function
+ // and GetProcAddress to get a pointer to the function if available.
+
+ LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)
+ GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
+
+ if (fnIsWow64Process)
+ {
+ if (!fnIsWow64Process(GetCurrentProcess(), &isWow64))
+ return false;
+
+ is64Bit = isWow64;
+ return true;
+ }
+ else // IsWow64Process is not supported, fail to detect.
+ return false;
+
+#else
+#error _WIN64 and _WIN32 are both undefined.
+#endif
+}
diff --git a/HMCLauncher/HMCL/os.h b/HMCLauncher/HMCL/os.h
new file mode 100644
index 000000000..406e661b4
--- /dev/null
+++ b/HMCLauncher/HMCL/os.h
@@ -0,0 +1,23 @@
+#pragma once
+#include
+#include
+
+const int MAX_KEY_LENGTH = 255;
+const int MAX_VALUE_NAME = 16383;
+
+// Query registry value of class root hKey, key path subKey, stores result in parameter out.
+LSTATUS MyRegQueryValue(HKEY hKey, LPCWSTR subKey, DWORD dwType, std::wstring &out);
+
+// Get module file name, stores result in parameter out.
+LSTATUS MyGetModuleFileName(HMODULE hModule, std::wstring &out);
+
+// Get environment variable by name, C++ style, stores the value in parameter out.
+LSTATUS MyGetEnvironmentVariable(LPCWSTR name, std::wstring &out);
+
+// Create process by invoking CreateProcess, only pass command.
+bool MyCreateProcess(const std::wstring &command);
+
+// Check if file lpPath exists.
+bool FindFirstFileExists(LPCWSTR lpPath, DWORD dwFilter);
+
+bool GetArch(bool &is64Bit);
\ No newline at end of file