Skip to content

Commit

Permalink
Merge branch 'feature/refactor-hmclauncher' into prs
Browse files Browse the repository at this point in the history
  • Loading branch information
burningtnt committed Jul 22, 2024
2 parents 3cf721d + 4e08af3 commit b136fd5
Show file tree
Hide file tree
Showing 11 changed files with 282 additions and 40 deletions.
Binary file modified HMCL/src/main/resources/assets/HMCLauncher.exe
Binary file not shown.
3 changes: 2 additions & 1 deletion HMCLauncher/HMCL/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ if(ENABLE_MINGW_STATIC_LINK_LIBSTDCXX AND MINGW)
add_link_options(-static)
endif()
set(CMAKE_WIN32_EXECUTABLE ON)
add_executable(HMCLauncher WIN32 HMCL.rc java.cpp main.cpp os.cpp stdafx.cpp Version.cpp)
add_executable(HMCLauncher WIN32 HMCL.rc java.cpp main.cpp os.cpp install.cpp stdafx.cpp Version.cpp)
target_link_libraries(HMCLauncher Version)
target_link_libraries(HMCLauncher wininet)
install(TARGETS HMCLauncher)
2 changes: 2 additions & 0 deletions HMCLauncher/HMCL/HMCL.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="java.h" />
<ClInclude Include="install.h" />
<ClInclude Include="lang.h" />
<ClInclude Include="main.h" />
<ClInclude Include="os.h" />
Expand All @@ -170,6 +171,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="java.cpp" />
<ClCompile Include="install.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="os.cpp" />
<ClCompile Include="stdafx.cpp">
Expand Down
6 changes: 6 additions & 0 deletions HMCLauncher/HMCL/HMCL.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
<ClInclude Include="java.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="install.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="os.h">
<Filter>头文件</Filter>
</ClInclude>
Expand All @@ -53,6 +56,9 @@
<ClCompile Include="java.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="install.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="os.cpp">
<Filter>源文件</Filter>
</ClCompile>
Expand Down
190 changes: 190 additions & 0 deletions HMCLauncher/HMCL/install.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
#include "stdafx.h
#include "install.h"
int InstallHMCLJRE(const std::wstring &home, const std::wstring &domain,
const std::wstring &file) {
WIN32_FIND_DATA ffd;
std::wstring runtime, jreDownloadedFile, jreDownloadedDirectory, command;
STARTUPINFO si;
PROCESS_INFORMATION pi;
runtime = home + L"runtime";
jreDownloadedFile = home + L".hmclauncher-jre-";
jreDownloadedFile.append(std::to_wstring(rand()));
jreDownloadedDirectory = jreDownloadedFile + L"";
jreDownloadedFile.append(L".zip");
HANDLE hFind = INVALID_HANDLE_VALUE, hCleanable[8];
for (int i = 0;i < 8;i ++) {
hCleanable[i] = INVALID_HANDLE_VALUE;
}
int err = 0;
err = DownloadHMCLJRE(jreDownloadedFile, domain, file);
if (err != 0) {
goto cleanup;
}
if (!CreateDirectory(jreDownloadedDirectory.c_str(), NULL)) {
err = GetLastError();
goto cleanup;
}
command = L"tar.exe -xf \"" + jreDownloadedFile + L"\"";
si.cb = sizeof(si);
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
if (!CreateProcess(NULL, &command[0], NULL, NULL, false,
NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, NULL, jreDownloadedDirectory.c_str(), &si,
&pi)) {
err = GetLastError();
goto cleanup;
}
hCleanable[0] = si.hStdInput;
hCleanable[1] = si.hStdOutput;
hCleanable[2] = si.hStdError;
hCleanable[3] = pi.hProcess;
hCleanable[4] = pi.hThread;
while (true) {
DWORD exitCode;
if (!GetExitCodeProcess(pi.hProcess, &exitCode)) {
err = GetLastError();
goto cleanup;
}
if (exitCode != STILL_ACTIVE) {
if (exitCode != 0) {
err = exitCode;
goto cleanup;
}
break;
}
}
hFind = FindFirstFile((jreDownloadedDirectory + L"\\*").c_str(), &ffd);
if (hFind == INVALID_HANDLE_VALUE) {
err = GetLastError();
goto cleanup;
}
{
std::wstring targetFile = std::wstring();
do {
std::wstring fileName = std::wstring(ffd.cFileName);
if (fileName.size() <= 2 && fileName[0] == L'.') {
continue;
}
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if (targetFile.size() != 0) {
err = HMCL_ERR_INVALID_JRE_PACK;
goto cleanup;
}
targetFile.append(fileName);
}
} while (FindNextFile(hFind, &ffd) != 0);
err = GetLastError();
if (err != ERROR_NO_MORE_FILES) {
goto cleanup;
}
err = 0;
if (targetFile.size() == 0) {
err = HMCL_ERR_INVALID_JRE_PACK;
goto cleanup;
}
if (!MoveFile((jreDownloadedDirectory + L'\\' + targetFile).c_str(), runtime.c_str())) {
err = GetLastError();
goto cleanup;
}
}
cleanup:
if (hFind != INVALID_HANDLE_VALUE) {
CloseHandle(hFind);
}
for (int i = 0;i < 8;i ++) {
HANDLE hCH = hCleanable[i];
if (hCH != INVALID_HANDLE_VALUE) {
CloseHandle(hCH);
}
}
RemoveDirectory(jreDownloadedDirectory.c_str());
DeleteFile(jreDownloadedFile.c_str());
return err;
}
int DownloadHMCLJRE(std::wstring &jreDownloadedFile, const std::wstring &domain,
const std::wstring &file) {
int err = 0;
HINTERNET hInternet = NULL, hConnection = NULL, hRequest = NULL;
byte buffer[4096];
HANDLE fd = NULL;
{
hInternet = InternetOpen(L"HMCLauncher", INTERNET_OPEN_TYPE_PRECONFIG, NULL,
NULL, 0);
if (hInternet == NULL) {
err = GetLastError();
goto cleanup;
}
hConnection =
InternetConnect(hInternet, domain.c_str(), INTERNET_DEFAULT_HTTPS_PORT,
NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
if (hConnection == NULL) {
err = GetLastError();
goto cleanup;
}
const wchar_t *ACCEPTS[] = {L"application/zip", NULL};
hRequest = HttpOpenRequest(hConnection, L"GET", file.c_str(), NULL, NULL,
ACCEPTS, INTERNET_FLAG_SECURE, 0);
if (hRequest == NULL) {
err = GetLastError();
goto cleanup;
}
if (!HttpSendRequest(hRequest, NULL, 0, NULL, 0)) {
err = GetLastError();
goto cleanup;
}
{
DWORD receivedCount, unused;
fd = CreateFile(jreDownloadedFile.c_str(), GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (fd == INVALID_HANDLE_VALUE) {
err = GetLastError();
goto cleanup;
}
while (InternetReadFile(hRequest, buffer, 4096, &receivedCount) &&
receivedCount) {
if (!WriteFile(fd, buffer, receivedCount, &unused, NULL)) {
err = GetLastError();
goto cleanup;
}
}
}
}
cleanup:
if (hRequest != NULL) {
InternetCloseHandle(hRequest);
}
if (hConnection != NULL) {
InternetCloseHandle(hConnection);
}
if (hInternet != NULL) {
InternetCloseHandle(hInternet);
}
if (fd != NULL) {
CloseHandle(fd);
}
return err;
}
9 changes: 9 additions & 0 deletions HMCLauncher/HMCL/install.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "stdafx.h"

#define HMCL_ERR_INVALID_JRE_PACK -129

int InstallHMCLJRE(const std::wstring &home, const std::wstring &domain,
const std::wstring &file);

int DownloadHMCLJRE(std::wstring &target, const std::wstring &domain,
const std::wstring &file);
86 changes: 58 additions & 28 deletions HMCLauncher/HMCL/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "os.h"
#include "java.h"
#include "lang.h"
#include "install.h"
#include <windows.h>

Version J8(TEXT("8"));
Expand All @@ -18,13 +19,29 @@ __attribute__ ((dllexport)) DWORD AmdPowerXpressRequestHighPerformance = 0x00000
}

void LaunchHMCLDirect(const std::wstring &javaPath, const std::wstring &workdir,
const std::wstring &jarPath, const std::wstring &jvmOptions) {
if (MyCreateProcess(L"\"" + javaPath + L"\" " + jvmOptions + L" -jar \"" + jarPath + L"\"", workdir))
const std::wstring &jarPath,
const std::wstring &jvmOptions) {
HANDLE hProcess = MyCreateProcess(L"\"" + javaPath + L"\" " + jvmOptions + L" -jar \"" +
jarPath + L"\"", workdir);
if (hProcess == INVALID_HANDLE_VALUE) {
return;
}

Sleep(5000);
DWORD exitCode;
if (!GetExitCodeProcess(hProcess, &exitCode)) {
GetLastError();
CloseHandle(hProcess);
return;
}
CloseHandle(hProcess);
if (exitCode == STILL_ACTIVE || exitCode == 0) {
exit(EXIT_SUCCESS);
}
}

void LaunchHMCL(const std::wstring &javaPath, const std::wstring &workdir,
const std::wstring &jarPath, const std::wstring &jvmOptions) {
const std::wstring &jarPath, const std::wstring &jvmOptions) {
Version javaVersion(L"");
if (!MyGetFileVersionInfo(javaPath, javaVersion)) return;

Expand All @@ -34,11 +51,13 @@ void LaunchHMCL(const std::wstring &javaPath, const std::wstring &workdir,
}

void OpenHelpPage() {
ShellExecute(0, 0, L"https://docs.hmcl.net/help.html", 0, 0, SW_SHOW);
ShellExecute(0, 0, L"https://docs.hmcl.net/help.html", 0, 0, SW_SHOW);
}

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLine, int nCmdShow) {
srand(GetTickCount64());

std::wstring exeName, jvmOptions;

// Since Jar file is appended to this executable, we should first get the
Expand All @@ -52,54 +71,65 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
exeName = exeName.substr(last_slash + 1);
}

if (ERROR_SUCCESS != MyGetEnvironmentVariable(L"HMCL_JAVA_OPTS", jvmOptions)) {
jvmOptions = L"-XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=15"; // Default Options
if (ERROR_SUCCESS !=
MyGetEnvironmentVariable(L"HMCL_JAVA_OPTS", jvmOptions)) {
jvmOptions =
L"-XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=15"; // Default Options
}

bool useChinese = GetUserDefaultUILanguage() == 2052; // zh-CN
bool useChinese = GetUserDefaultUILanguage() == 2052; // zh-CN

SYSTEM_INFO systemInfo;
GetNativeSystemInfo(&systemInfo);
// TODO: check whether the bundled JRE is valid.

// First, try the Java packaged together.
bool isX64 = (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64);
bool isARM64 = (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64);
bool isX64 =
(systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64);
bool isARM64 =
(systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64);

if (isARM64) {
LaunchHMCLDirect(L"jre-arm64\\bin\\javaw.exe", workdir, exeName, jvmOptions);
LaunchHMCLDirect(L"jre-arm64\\bin\\java.exe", workdir, exeName,
jvmOptions);
}
if (isX64) {
LaunchHMCLDirect(L"jre-x64\\bin\\javaw.exe", workdir, exeName, jvmOptions);
LaunchHMCLDirect(L"jre-x64\\bin\\java.exe", workdir, exeName, jvmOptions);
}
LaunchHMCLDirect(L"jre-x86\\bin\\javaw.exe", workdir, exeName, jvmOptions);
LaunchHMCLDirect(L"jre-x86\\bin\\java.exe", workdir, exeName, jvmOptions);

// Next, try the Java installed on thi computer.
// Next, try the Java installed on this computer.
std::wstring path;
int status;

ScanJava(systemInfo, path, status);

if (status != JAVA_STATUS_NOT_FOUND) {
MyPathAppend(path, std::wstring(L"bin\\javaw.exe"));
MyPathAppend(path, std::wstring(L"bin\\java.exe"));
LaunchHMCL(path, workdir, exeName, jvmOptions);
}

// Try java in PATH
LaunchHMCLDirect(L"javaw", workdir, exeName, jvmOptions);

LPCWSTR downloadLink;

if (isARM64) {
downloadLink = L"https://docs.hmcl.net/downloads/windows/arm64.html";
} if (isX64) {
downloadLink = L"https://docs.hmcl.net/downloads/windows/x86_64.html";
} else {
downloadLink = L"https://docs.hmcl.net/downloads/windows/x86.html";
LaunchHMCLDirect(L"java", workdir, exeName, jvmOptions);

std::wstring home;
if (SUCCEEDED(MySHGetFolderPath(CSIDL_APPDATA, home)) ||
SUCCEEDED(MySHGetFolderPath(CSIDL_PROFILE, home))) {
MyPathNormalize(home);
MyPathAppend(home, L".hmcl\\");

std::wstring file = L"";
if (isARM64) {
file = L"/java/11.0.24+9/bellsoft-jre11.0.24+9-windows-aarch64-full.zip";
} else if (isX64) {
file = L"/java/11.0.24+9/bellsoft-jre11.0.24+9-windows-i586-full.zip";
} else {
file = L"/java/11.0.24+9/bellsoft-jre11.0.24+9-windows-amd64-full.zip";
}
InstallHMCLJRE(home, L"download.bell-sw.com", file);

LaunchHMCLDirect(home + L"runtime\\bin\\java.exe", workdir, exeName, jvmOptions);
}

if (IDOK == MessageBox(NULL, useChinese ? ERROR_PROMPT_ZH : ERROR_PROMPT, useChinese ? ERROR_TITLE_ZH : ERROR_TITLE, MB_ICONWARNING | MB_OKCANCEL)) {
ShellExecute(0, 0, downloadLink, 0, 0, SW_SHOW);
}
return 1;
return 0;
}
Loading

0 comments on commit b136fd5

Please sign in to comment.