From 1139c65df25478e90faf06bd49b0a67f2a6991c2 Mon Sep 17 00:00:00 2001 From: LoRd_MuldeR Date: Tue, 29 Sep 2020 21:21:59 +0200 Subject: [PATCH] Make it possible to specify a custom Java download URL + added an explicit Manifest file. --- Makefile | 32 ++++---- README.md | 47 ++++++----- .../src/MakefileGenerator.java | 14 ++-- res/assets/manifest.xml | 31 ++++++++ res/common.rc | 7 ++ res/registry.rc | 1 + src/head.c | 77 +++++++++++-------- src/resource.h | 10 ++- 8 files changed, 145 insertions(+), 74 deletions(-) create mode 100644 res/assets/manifest.xml diff --git a/Makefile b/Makefile index e137eb4..815c304 100644 --- a/Makefile +++ b/Makefile @@ -36,22 +36,22 @@ resources: init windres -o obj/registry.$(CPU_ARCH).o res/registry.rc build: init resources - $(CC) $(CFLAGS) -DJAR_FILE_WRAPPED=0 -DDETECT_REGISTRY=0 -DSTAY_ALIVE=1 -DENABLE_SPLASH=1 -o bin/launch5j_$(CPU_ARCH).exe src/head.c obj/common.$(CPU_ARCH).o obj/splash_screen.$(CPU_ARCH).o - $(CC) $(CFLAGS) -DJAR_FILE_WRAPPED=0 -DDETECT_REGISTRY=0 -DSTAY_ALIVE=1 -DENABLE_SPLASH=0 -o bin/launch5j_$(CPU_ARCH)_nosplash.exe src/head.c obj/common.$(CPU_ARCH).o - $(CC) $(CFLAGS) -DJAR_FILE_WRAPPED=0 -DDETECT_REGISTRY=0 -DSTAY_ALIVE=0 -DENABLE_SPLASH=1 -o bin/launch5j_$(CPU_ARCH)_nowait.exe src/head.c obj/common.$(CPU_ARCH).o obj/splash_screen.$(CPU_ARCH).o - $(CC) $(CFLAGS) -DJAR_FILE_WRAPPED=0 -DDETECT_REGISTRY=0 -DSTAY_ALIVE=0 -DENABLE_SPLASH=0 -o bin/launch5j_$(CPU_ARCH)_nowait_nosplash.exe src/head.c obj/common.$(CPU_ARCH).o - $(CC) $(CFLAGS) -DJAR_FILE_WRAPPED=0 -DDETECT_REGISTRY=1 -DSTAY_ALIVE=1 -DENABLE_SPLASH=1 -o bin/launch5j_$(CPU_ARCH)_registry.exe src/head.c obj/common.$(CPU_ARCH).o obj/splash_screen.$(CPU_ARCH).o obj/registry.$(CPU_ARCH).o - $(CC) $(CFLAGS) -DJAR_FILE_WRAPPED=0 -DDETECT_REGISTRY=1 -DSTAY_ALIVE=1 -DENABLE_SPLASH=0 -o bin/launch5j_$(CPU_ARCH)_registry_nosplash.exe src/head.c obj/common.$(CPU_ARCH).o obj/registry.$(CPU_ARCH).o - $(CC) $(CFLAGS) -DJAR_FILE_WRAPPED=0 -DDETECT_REGISTRY=1 -DSTAY_ALIVE=0 -DENABLE_SPLASH=1 -o bin/launch5j_$(CPU_ARCH)_registry_nowait.exe src/head.c obj/common.$(CPU_ARCH).o obj/splash_screen.$(CPU_ARCH).o obj/registry.$(CPU_ARCH).o - $(CC) $(CFLAGS) -DJAR_FILE_WRAPPED=0 -DDETECT_REGISTRY=1 -DSTAY_ALIVE=0 -DENABLE_SPLASH=0 -o bin/launch5j_$(CPU_ARCH)_registry_nowait_nosplash.exe src/head.c obj/common.$(CPU_ARCH).o obj/registry.$(CPU_ARCH).o - $(CC) $(CFLAGS) -DJAR_FILE_WRAPPED=1 -DDETECT_REGISTRY=0 -DSTAY_ALIVE=1 -DENABLE_SPLASH=1 -o bin/launch5j_$(CPU_ARCH)_wrapped.exe src/head.c obj/common.$(CPU_ARCH).o obj/splash_screen.$(CPU_ARCH).o - $(CC) $(CFLAGS) -DJAR_FILE_WRAPPED=1 -DDETECT_REGISTRY=0 -DSTAY_ALIVE=1 -DENABLE_SPLASH=0 -o bin/launch5j_$(CPU_ARCH)_wrapped_nosplash.exe src/head.c obj/common.$(CPU_ARCH).o - $(CC) $(CFLAGS) -DJAR_FILE_WRAPPED=1 -DDETECT_REGISTRY=0 -DSTAY_ALIVE=0 -DENABLE_SPLASH=1 -o bin/launch5j_$(CPU_ARCH)_wrapped_nowait.exe src/head.c obj/common.$(CPU_ARCH).o obj/splash_screen.$(CPU_ARCH).o - $(CC) $(CFLAGS) -DJAR_FILE_WRAPPED=1 -DDETECT_REGISTRY=0 -DSTAY_ALIVE=0 -DENABLE_SPLASH=0 -o bin/launch5j_$(CPU_ARCH)_wrapped_nowait_nosplash.exe src/head.c obj/common.$(CPU_ARCH).o - $(CC) $(CFLAGS) -DJAR_FILE_WRAPPED=1 -DDETECT_REGISTRY=1 -DSTAY_ALIVE=1 -DENABLE_SPLASH=1 -o bin/launch5j_$(CPU_ARCH)_wrapped_registry.exe src/head.c obj/common.$(CPU_ARCH).o obj/splash_screen.$(CPU_ARCH).o obj/registry.$(CPU_ARCH).o - $(CC) $(CFLAGS) -DJAR_FILE_WRAPPED=1 -DDETECT_REGISTRY=1 -DSTAY_ALIVE=1 -DENABLE_SPLASH=0 -o bin/launch5j_$(CPU_ARCH)_wrapped_registry_nosplash.exe src/head.c obj/common.$(CPU_ARCH).o obj/registry.$(CPU_ARCH).o - $(CC) $(CFLAGS) -DJAR_FILE_WRAPPED=1 -DDETECT_REGISTRY=1 -DSTAY_ALIVE=0 -DENABLE_SPLASH=1 -o bin/launch5j_$(CPU_ARCH)_wrapped_registry_nowait.exe src/head.c obj/common.$(CPU_ARCH).o obj/splash_screen.$(CPU_ARCH).o obj/registry.$(CPU_ARCH).o - $(CC) $(CFLAGS) -DJAR_FILE_WRAPPED=1 -DDETECT_REGISTRY=1 -DSTAY_ALIVE=0 -DENABLE_SPLASH=0 -o bin/launch5j_$(CPU_ARCH)_wrapped_registry_nowait_nosplash.exe src/head.c obj/common.$(CPU_ARCH).o obj/registry.$(CPU_ARCH).o + $(CC) $(CFLAGS) -DL5J_JAR_FILE_WRAPPED=0 -DL5J_DETECT_REGISTRY=0 -DL5J_STAY_ALIVE=1 -DL5J_ENABLE_SPLASH=1 -o bin/launch5j_$(CPU_ARCH).exe src/head.c obj/common.$(CPU_ARCH).o obj/splash_screen.$(CPU_ARCH).o + $(CC) $(CFLAGS) -DL5J_JAR_FILE_WRAPPED=0 -DL5J_DETECT_REGISTRY=0 -DL5J_STAY_ALIVE=1 -DL5J_ENABLE_SPLASH=0 -o bin/launch5j_$(CPU_ARCH)_nosplash.exe src/head.c obj/common.$(CPU_ARCH).o + $(CC) $(CFLAGS) -DL5J_JAR_FILE_WRAPPED=0 -DL5J_DETECT_REGISTRY=0 -DL5J_STAY_ALIVE=0 -DL5J_ENABLE_SPLASH=1 -o bin/launch5j_$(CPU_ARCH)_nowait.exe src/head.c obj/common.$(CPU_ARCH).o obj/splash_screen.$(CPU_ARCH).o + $(CC) $(CFLAGS) -DL5J_JAR_FILE_WRAPPED=0 -DL5J_DETECT_REGISTRY=0 -DL5J_STAY_ALIVE=0 -DL5J_ENABLE_SPLASH=0 -o bin/launch5j_$(CPU_ARCH)_nowait_nosplash.exe src/head.c obj/common.$(CPU_ARCH).o + $(CC) $(CFLAGS) -DL5J_JAR_FILE_WRAPPED=0 -DL5J_DETECT_REGISTRY=1 -DL5J_STAY_ALIVE=1 -DL5J_ENABLE_SPLASH=1 -o bin/launch5j_$(CPU_ARCH)_registry.exe src/head.c obj/common.$(CPU_ARCH).o obj/splash_screen.$(CPU_ARCH).o obj/registry.$(CPU_ARCH).o + $(CC) $(CFLAGS) -DL5J_JAR_FILE_WRAPPED=0 -DL5J_DETECT_REGISTRY=1 -DL5J_STAY_ALIVE=1 -DL5J_ENABLE_SPLASH=0 -o bin/launch5j_$(CPU_ARCH)_registry_nosplash.exe src/head.c obj/common.$(CPU_ARCH).o obj/registry.$(CPU_ARCH).o + $(CC) $(CFLAGS) -DL5J_JAR_FILE_WRAPPED=0 -DL5J_DETECT_REGISTRY=1 -DL5J_STAY_ALIVE=0 -DL5J_ENABLE_SPLASH=1 -o bin/launch5j_$(CPU_ARCH)_registry_nowait.exe src/head.c obj/common.$(CPU_ARCH).o obj/splash_screen.$(CPU_ARCH).o obj/registry.$(CPU_ARCH).o + $(CC) $(CFLAGS) -DL5J_JAR_FILE_WRAPPED=0 -DL5J_DETECT_REGISTRY=1 -DL5J_STAY_ALIVE=0 -DL5J_ENABLE_SPLASH=0 -o bin/launch5j_$(CPU_ARCH)_registry_nowait_nosplash.exe src/head.c obj/common.$(CPU_ARCH).o obj/registry.$(CPU_ARCH).o + $(CC) $(CFLAGS) -DL5J_JAR_FILE_WRAPPED=1 -DL5J_DETECT_REGISTRY=0 -DL5J_STAY_ALIVE=1 -DL5J_ENABLE_SPLASH=1 -o bin/launch5j_$(CPU_ARCH)_wrapped.exe src/head.c obj/common.$(CPU_ARCH).o obj/splash_screen.$(CPU_ARCH).o + $(CC) $(CFLAGS) -DL5J_JAR_FILE_WRAPPED=1 -DL5J_DETECT_REGISTRY=0 -DL5J_STAY_ALIVE=1 -DL5J_ENABLE_SPLASH=0 -o bin/launch5j_$(CPU_ARCH)_wrapped_nosplash.exe src/head.c obj/common.$(CPU_ARCH).o + $(CC) $(CFLAGS) -DL5J_JAR_FILE_WRAPPED=1 -DL5J_DETECT_REGISTRY=0 -DL5J_STAY_ALIVE=0 -DL5J_ENABLE_SPLASH=1 -o bin/launch5j_$(CPU_ARCH)_wrapped_nowait.exe src/head.c obj/common.$(CPU_ARCH).o obj/splash_screen.$(CPU_ARCH).o + $(CC) $(CFLAGS) -DL5J_JAR_FILE_WRAPPED=1 -DL5J_DETECT_REGISTRY=0 -DL5J_STAY_ALIVE=0 -DL5J_ENABLE_SPLASH=0 -o bin/launch5j_$(CPU_ARCH)_wrapped_nowait_nosplash.exe src/head.c obj/common.$(CPU_ARCH).o + $(CC) $(CFLAGS) -DL5J_JAR_FILE_WRAPPED=1 -DL5J_DETECT_REGISTRY=1 -DL5J_STAY_ALIVE=1 -DL5J_ENABLE_SPLASH=1 -o bin/launch5j_$(CPU_ARCH)_wrapped_registry.exe src/head.c obj/common.$(CPU_ARCH).o obj/splash_screen.$(CPU_ARCH).o obj/registry.$(CPU_ARCH).o + $(CC) $(CFLAGS) -DL5J_JAR_FILE_WRAPPED=1 -DL5J_DETECT_REGISTRY=1 -DL5J_STAY_ALIVE=1 -DL5J_ENABLE_SPLASH=0 -o bin/launch5j_$(CPU_ARCH)_wrapped_registry_nosplash.exe src/head.c obj/common.$(CPU_ARCH).o obj/registry.$(CPU_ARCH).o + $(CC) $(CFLAGS) -DL5J_JAR_FILE_WRAPPED=1 -DL5J_DETECT_REGISTRY=1 -DL5J_STAY_ALIVE=0 -DL5J_ENABLE_SPLASH=1 -o bin/launch5j_$(CPU_ARCH)_wrapped_registry_nowait.exe src/head.c obj/common.$(CPU_ARCH).o obj/splash_screen.$(CPU_ARCH).o obj/registry.$(CPU_ARCH).o + $(CC) $(CFLAGS) -DL5J_JAR_FILE_WRAPPED=1 -DL5J_DETECT_REGISTRY=1 -DL5J_STAY_ALIVE=0 -DL5J_ENABLE_SPLASH=0 -o bin/launch5j_$(CPU_ARCH)_wrapped_registry_nowait_nosplash.exe src/head.c obj/common.$(CPU_ARCH).o obj/registry.$(CPU_ARCH).o strip: build strip bin/launch5j_$(CPU_ARCH).exe diff --git a/README.md b/README.md index 85a588e..f807644 100644 --- a/README.md +++ b/README.md @@ -77,42 +77,50 @@ Some options can be configured via the launcher executable's [STRINGTABLE](https * **`ID_STR_CMDARGS` (#3)** Specifies *additional* fixed command-line parameters to be passed to the Java application. -* **`ID_STR_JAVAMIN` (#4)** +* **`ID_STR_JREPATH` (#4)** + Specifies the path to the Java runtime (`javaw.exe`) relative to the launcher executable location. + If not specified, then the *default* runtime path `runtime\\bin\\javaw.exe` is assumed. + + (This option does **not** apply to the “registry” variant of Launch5j) + +* **`ID_STR_MUTEXID` (#5)** + Specifies the application ID to be used when creating the [*single-instance*](http://www.bcbjournal.org/articles/vol3/9911/Single-instance_applications.htm) mutex. + The ID **must** be at least 5 characters in length and **should** be a *unique* string for each application! + If not specified, then **no** mutex will be created and thus *multiple* instances will be allowed. + + *Hint:* If the specified application ID *starts* with an **`@`** character, then Launch5j will **not** show a message box when the application is already running; the **`@`** character is *not* considered a part of the actual ID. + + (This option does **not** apply to the “nowait” variant of Launch5j) + +* **`ID_STR_JAVAMIN` (#6)** Specifies the ***minimum*** supported JRE version, in the **`w.x.y.z`** format (e.g. `11.0.0.0`). This values is *inclusive*, i.e. the specified JRE version or any newer JRE version will be accepted. If not specified, then the *default* minimum supported JRE version `8.0.0.0` applies. *Hint:* Old-style `1.x.y_z` Java versions are automatically translated to the new `x.y.z` format! - (This option only applies to the `registry` variant of Launch5j) + (This option only applies to the “registry” variant of Launch5j) -* **`ID_STR_JAVAMAX` (#5)** +* **`ID_STR_JAVAMAX` (#7)** Specifies the ***maximum*** supported JRE version, in the **`w.x.y.z`** format (e.g. `12.0.0.0`). This values is *exclusive*, i.e. only JRE versions *older* than the specified JRE version will be accepted. If not specified, then there is **no** upper limit on the supported JRE version. *Hint:* Old-style `1.x.y.z` Java versions are automatically translated to the `x.y.z.0` format! - (This option only applies to the `registry` variant of Launch5j) + (This option only applies to the “registry” variant of Launch5j) -* **`ID_STR_BITNESS` (#6)** +* **`ID_STR_BITNESS` (#8)** Specifies the required ***bitness*** of the JRE. This can be either **`32`** (x86, aka i586) or **`64`** (x86-64). - If not specified, 32-Bit *and* 64-Bit JREs are accepted, with a preference to 64-Bit. + If not specified, then 32-Bit *and* 64-Bit JREs are accepted, with a preference to 64-Bit. - (This option only applies to the `registry` variant of Launch5j) + (This option only applies to the “registry” variant of Launch5j) -* **`ID_STR_BITNESS` (#6)** - Specifies the required ***bitness*** of the JRE. This can be either **`32`** (x86, aka i586) or **`64`** (x86-64). - If not specified, 32-Bit *and* 64-Bit JREs are accepted, with a preference to 64-Bit. - - (This option only applies to the `registry` variant of Launch5j) +* **`ID_STR_JAVAURL` (#9)** + The Java download URL that will ne suggested, if **no** suitable JRE could be detected on the machine. + If not specified, wes suggest downloading OpenJDK as provided by the [AdoptOpenJDK](https://adoptopenjdk.net/) project. -* **`ID_STR_MUTEXID` (#7)** - Specifies the application ID to be used when creating the [*single-instance*](http://www.bcbjournal.org/articles/vol3/9911/Single-instance_applications.htm) mutex. - The ID **must** be at least 5 characters in length and **should** be a *unique* string for each application! - If not specified, then **no** mutex will be created and thus *multiple* instances will be allowed. - - *Hint:* If the specified application ID *starts* with an **`@`** character, then Launch5j will **not** show a message box when the application is already running; the **`@`** character is *not* considered a part of the actual ID. + (This option only applies to the “registry” variant of Launch5j) *Note:* We use the convention that the default resource string value `"?"` is used to represent an “undefined” value, because resource strings cannot be empty. You can replace the default value as needed! @@ -161,3 +169,6 @@ This work has been released under the MIT license: COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +[∎](https://www.youtube.com/watch?v=EfbbjY9MlQs) diff --git a/etc/utils/MakefileGenerator/src/MakefileGenerator.java b/etc/utils/MakefileGenerator/src/MakefileGenerator.java index d4ba18f..47a5028 100644 --- a/etc/utils/MakefileGenerator/src/MakefileGenerator.java +++ b/etc/utils/MakefileGenerator/src/MakefileGenerator.java @@ -40,7 +40,8 @@ public class MakefileGenerator { for(int registry = 0; registry < 2; ++registry) { for(int stayAlive = 1; stayAlive > -1; --stayAlive) { for(int enableSplash = 1; enableSplash > -1; --enableSplash) { - out.println(generateCommand(filenNames, wrapped, registry, stayAlive, enableSplash)); + out.println(generateCommand( + filenNames, wrapped, registry, stayAlive, enableSplash)); } } } @@ -83,16 +84,17 @@ public class MakefileGenerator { out.println(); } - private static String generateCommand(final List filenNames, final int wrapped, final int registry, final int stayAlive, final int enableSplash) + private static String generateCommand(final List filenNames, + final int wrapped, final int registry, final int stayAlive, final int enableSplash) { final String fileName = String.format("bin/launch5j_$(CPU_ARCH)%s.exe", generateNameSuffix(wrapped, registry, stayAlive, enableSplash)); final StringBuilder cmdLine = new StringBuilder(String.format( "\t$(CC) $(CFLAGS) " - + "-DJAR_FILE_WRAPPED=%d " - + "-DDETECT_REGISTRY=%d " - + "-DSTAY_ALIVE=%d " - + "-DENABLE_SPLASH=%d " + + "-DL5J_JAR_FILE_WRAPPED=%d " + + "-DL5J_DETECT_REGISTRY=%d " + + "-DL5J_STAY_ALIVE=%d " + + "-DL5J_ENABLE_SPLASH=%d " + "-o %s " + "src/head.c obj/common.$(CPU_ARCH).o", wrapped, diff --git a/res/assets/manifest.xml b/res/assets/manifest.xml new file mode 100644 index 0000000..fb9b0cc --- /dev/null +++ b/res/assets/manifest.xml @@ -0,0 +1,31 @@ + + + + Launch5j + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/common.rc b/res/common.rc index 7f9b9cf..0bf6cdc 100644 --- a/res/common.rc +++ b/res/common.rc @@ -40,6 +40,7 @@ BEGIN ID_STR_HEADING L"?" /*custom application title*/ ID_STR_JVMARGS L"?" /*additional JVM args*/ ID_STR_CMDARGS L"?" /*additional command-line args*/ + ID_STR_JREPATH L"?" /*relative path to JRE*/ ID_STR_MUTEXID L"?" /*single instance mutex ID*/ END @@ -81,3 +82,9 @@ BEGIN VALUE "Translation", 0x0, 1200 END END + +///////////////////////////////////////////////////////////////////////////// +// Manifest +///////////////////////////////////////////////////////////////////////////// + +1 RT_MANIFEST "assets/manifest.xml" diff --git a/res/registry.rc b/res/registry.rc index 554375b..ef218a9 100644 --- a/res/registry.rc +++ b/res/registry.rc @@ -34,4 +34,5 @@ BEGIN ID_STR_JAVAMIN L"?" /*min supported JRE version, in "w.x.y.z" format*/ ID_STR_JAVAMAX L"?" /*max supported JRE version, in "w.x.y.z" format*/ ID_STR_BITNESS L"?" /*required JRE "bitness", i.e. "32" or "64"*/ + ID_STR_JAVAURL L"?" /*Java download URL, if no usable JRE was found*/ END diff --git a/src/head.c b/src/head.c index 112982c..3dbfcc0 100644 --- a/src/head.c +++ b/src/head.c @@ -29,25 +29,25 @@ #include "resource.h" // Options -#ifndef JAR_FILE_WRAPPED -#define JAR_FILE_WRAPPED 0 +#ifndef L5J_JAR_FILE_WRAPPED +#error L5J_JAR_FILE_WRAPPED flag is *not* defined! #endif -#ifndef DETECT_REGISTRY -#define DETECT_REGISTRY 0 +#ifndef L5J_DETECT_REGISTRY +#error L5J_DETECT_REGISTRY flag is *not* defined! #endif -#ifndef ENABLE_SPLASH -#define ENABLE_SPLASH 1 +#ifndef L5J_ENABLE_SPLASH +#error L5J_ENABLE_SPLASH flag is *not* defined! #endif -#ifndef STAY_ALIVE -#define STAY_ALIVE 1 +#ifndef L5J_STAY_ALIVE +#error L5J_STAY_ALIVE flag is *not* defined! #endif -#ifndef WAIT_FOR_WINDOW -#define WAIT_FOR_WINDOW 1 +#ifndef L5J_WAIT_FOR_WINDOW +#define L5J_WAIT_FOR_WINDOW 1 #endif // Const -static const wchar_t *const JRE_RELATIVE_PATH = L"runtime\\bin\\javaw.exe"; -static const wchar_t *const JRE_DOWNLOAD_LINK = L"https://adoptopenjdk.net/"; +static const wchar_t *const JRE_DOWNLOAD_LINK_DEFAULT = L"https://adoptopenjdk.net/"; +static const wchar_t *const JRE_RELATIVE_PATH_DEFAULT = L"runtime\\bin\\javaw.exe"; static const size_t MIN_MUTEXID_LENGTH = 5U; static const DWORD SPLASH_SCREEN_TIMEOUT = 30000U; @@ -451,7 +451,7 @@ static const wchar_t *get_executable_directory(const wchar_t *const executable_p static const wchar_t *get_jarfile_path(const wchar_t *const executable_path, const wchar_t *const executable_directory) { -#if JAR_FILE_WRAPPED +#if L5J_JAR_FILE_WRAPPED return wcsdup(executable_path); /*JAR file is wrapped*/ #else const wchar_t *jarfile_path = NULL; @@ -827,7 +827,7 @@ static BOOL wait_for_process_ready(const HWND hwnd, const HANDLE process_handle, const DWORD ticks_start = GetTickCount(); for (;;) { - if (input_idle || signaled_or_failed(WaitForInputIdle(process_handle, 125U))) + if (input_idle || signaled_or_failed(WaitForInputIdle(process_handle, 25U))) { const HWND child_hwnd = find_window_by_process_id(process_id); if (child_hwnd) @@ -888,12 +888,13 @@ static int show_message_format(HWND hwnd, const DWORD flags, const wchar_t *cons return result; } -static void show_jre_download_notice(const HWND hwnd, const wchar_t *const title, const DWORD required_bitness, const ULONGLONG required_ver) +static void show_jre_download_notice(const HINSTANCE hinstance, const HWND hwnd, const wchar_t *const title, const DWORD required_bitness, const ULONGLONG required_ver) { const DWORD req_version_comp[] = { (required_ver >> 48) & 0xFFFF, (required_ver >> 32) & 0xFFFF, (required_ver >> 16) & 0xFFFF, required_ver & 0xFFFF }; + wchar_t *const jre_download_link = load_string(hinstance, ID_STR_JAVAURL); wchar_t *const version_str = (req_version_comp[3U] != 0U) ? awprintf(L"%u.%u.%u_%u", req_version_comp[0U], req_version_comp[1U], req_version_comp[2U], req_version_comp[3U]) : ((req_version_comp[2U] != 0U) @@ -901,22 +902,24 @@ static void show_jre_download_notice(const HWND hwnd, const wchar_t *const title : awprintf(L"%u.%u", req_version_comp[0U], req_version_comp[1U])); if(version_str) { + const wchar_t *const jre_download_ptr = AVAILABLE(jre_download_link) ? jre_download_link : JRE_DOWNLOAD_LINK_DEFAULT; const int result = (required_bitness == 0U) ? show_message_format(hwnd, MB_ICONWARNING | MB_OKCANCEL | MB_TOPMOST, title, L"This application requires the Java Runtime Environment, version %ls, or a compatible newer version.\n\n" L"We recommend downloading the OpenJDK runtime here:\n%ls", - version_str, JRE_DOWNLOAD_LINK) + version_str, jre_download_ptr) : show_message_format(hwnd, MB_ICONWARNING | MB_OKCANCEL | MB_TOPMOST, title, L"This application requires the Java Runtime Environment, version %ls, or a compatible newer version.\n\n" L"Only the %u-Bit (%ls) version of the JRE is supported!\n\n", L"We recommend downloading the OpenJDK runtime:\n%ls", - version_str, required_bitness, (required_bitness == 64) ? L"x64" : L"x86", JRE_DOWNLOAD_LINK); + version_str, required_bitness, (required_bitness == 64) ? L"x64" : L"x86", jre_download_ptr); if (result == IDOK) { - ShellExecuteW(hwnd, NULL, JRE_DOWNLOAD_LINK, NULL, NULL, SW_SHOW); + ShellExecuteW(hwnd, NULL, jre_download_ptr, NULL, NULL, SW_SHOW); } - free(version_str); } + free(version_str); + free(jre_download_link); } /* ======================================================================== */ @@ -1001,11 +1004,13 @@ static wchar_t *const DEFAULT_HEADING = L"Launch5j"; int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) { int result = -1; - const wchar_t *app_heading = NULL, *mutex_name = NULL, *executable_path = NULL, *executable_directory = NULL, *jarfile_path = NULL, *java_runtime_path = NULL, *jvm_extra_args = NULL, *cmd_extra_args = NULL, *command_line = NULL; + const wchar_t *app_heading = NULL, *mutex_name = NULL, *executable_path = NULL, *executable_directory = NULL, *jarfile_path = NULL, + *java_runtime_path = NULL, *jre_relative_path = NULL, *jvm_extra_args = NULL, *cmd_extra_args = NULL, *command_line = NULL; HANDLE mutex_handle = NULL; DWORD java_required_bitness = 0U; ULONGLONG java_required_ver_min = 0ULL, java_required_ver_max = 0ULL; HGDIOBJ splash_image = NULL; + BOOL have_screen_created = FALSE; PROCESS_INFORMATION process_info; STARTUPINFOW startup_info; @@ -1020,6 +1025,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine HWND hwnd = CreateWindowExW(WS_EX_TOOLWINDOW | WS_EX_TOPMOST, L"STATIC", APP_HEADING, WS_POPUP | SS_BITMAP, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); // Single instance +#if L5J_STAY_ALIVE mutex_name = load_string(hInstance, ID_STR_MUTEXID); if (AVAILABLE(mutex_name) && (wcslen(mutex_name) >= MIN_MUTEXID_LENGTH + ((mutex_name[0U] == L'@') ? 0U : 1U))) { @@ -1033,13 +1039,15 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine goto cleanup; } } +#endif // Show the splash screen -#if ENABLE_SPLASH +#if L5J_ENABLE_SPLASH if (splash_image = LoadImage(hInstance, MAKEINTRESOURCE(ID_BITMAP_SPLASH), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE)) { if (create_splash_screen(hwnd, splash_image)) { + have_screen_created = TRUE; process_window_messages(hwnd); } } @@ -1073,7 +1081,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine } // Does the JAR file exist? -#if !JAR_FILE_WRAPPED +#if !L5J_JAR_FILE_WRAPPED if (!file_exists(jarfile_path)) { show_message_format(hwnd, MB_ICONERROR | MB_TOPMOST, APP_HEADING, L"The required JAR file could not be found:\n\n%ls\n\n\nRe-installing the application may fix the problem!", jarfile_path); @@ -1082,18 +1090,19 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine #endif // Find the Java runtime executable path (possibly from the registry) -#if DETECT_REGISTRY +#if L5J_DETECT_REGISTRY java_required_ver_min = load_java_version(hInstance, ID_STR_JAVAMIN, (8ull << 48)); java_required_ver_max = load_java_version(hInstance, ID_STR_JAVAMAX, MAXULONGLONG); java_required_bitness = load_java_bitness(hInstance, ID_STR_BITNESS); if (!(java_runtime_path = detect_java_runtime(java_required_bitness, java_required_ver_min, java_required_ver_max))) { show_message(hwnd, MB_ICONERROR | MB_TOPMOST, APP_HEADING, L"Java Runtime Environment (JRE) could not be found!"); - show_jre_download_notice(hwnd, APP_HEADING, java_required_bitness, java_required_ver_min); + show_jre_download_notice(hInstance, hwnd, APP_HEADING, java_required_bitness, java_required_ver_min); goto cleanup; } #else - if (!(java_runtime_path = awprintf(L"%ls\\%ls", executable_directory, JRE_RELATIVE_PATH))) + jre_relative_path = load_string(hInstance, ID_STR_JREPATH); + if (!(java_runtime_path = awprintf(L"%ls\\%ls", executable_directory, AVAILABLE(jre_relative_path) ? jre_relative_path: JRE_RELATIVE_PATH_DEFAULT))) { show_message(hwnd, MB_ICONERROR | MB_TOPMOST, APP_HEADING, L"The path of the Java runtime could not be determined!"); goto cleanup; @@ -1124,7 +1133,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine } // Process pending window messages -#if ENABLE_SPLASH +#if L5J_ENABLE_SPLASH process_window_messages(hwnd); #endif @@ -1145,16 +1154,23 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine } // Process pending window messages -#if ENABLE_SPLASH +#if L5J_ENABLE_SPLASH process_window_messages(hwnd); -#if WAIT_FOR_WINDOW + + // Wait until child-process window is showing +#if L5J_WAIT_FOR_WINDOW wait_for_process_ready(hwnd, process_info.hProcess, process_info.dwProcessId); #endif - destroy_window(&hwnd); #endif + // Hide the splash screen now + if (have_screen_created) + { + ShowWindow(hwnd, SW_HIDE); + } + // Wait for process to exit, then get the exit code -#if STAY_ALIVE +#if L5J_STAY_ALIVE if (signaled_or_failed(WaitForSingleObject(process_info.hProcess, INFINITE))) { DWORD exit_code = 0U; @@ -1181,6 +1197,7 @@ cleanup: free((void*)command_line); free((void*)java_runtime_path); free((void*)jarfile_path); + free((void*)jre_relative_path); free((void*)executable_directory); free((void*)executable_path); free((void*)mutex_name); diff --git a/src/resource.h b/src/resource.h index 0539073..2006cc0 100644 --- a/src/resource.h +++ b/src/resource.h @@ -21,7 +21,9 @@ #define ID_STR_HEADING 1 #define ID_STR_JVMARGS 2 #define ID_STR_CMDARGS 3 -#define ID_STR_JAVAMIN 4 -#define ID_STR_JAVAMAX 5 -#define ID_STR_BITNESS 6 -#define ID_STR_MUTEXID 7 +#define ID_STR_JREPATH 4 +#define ID_STR_MUTEXID 5 +#define ID_STR_JAVAMIN 6 +#define ID_STR_JAVAMAX 7 +#define ID_STR_BITNESS 8 +#define ID_STR_JAVAURL 9