Make it possible to specify a custom Java download URL + added an explicit Manifest file.

This commit is contained in:
LoRd_MuldeR 2020-09-29 21:21:59 +02:00
parent 6858ffe791
commit 1139c65df2
8 changed files with 145 additions and 74 deletions

View File

@ -36,22 +36,22 @@ resources: init
windres -o obj/registry.$(CPU_ARCH).o res/registry.rc windres -o obj/registry.$(CPU_ARCH).o res/registry.rc
build: init resources 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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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) -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=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: build
strip bin/launch5j_$(CPU_ARCH).exe strip bin/launch5j_$(CPU_ARCH).exe

View File

@ -77,42 +77,50 @@ Some options can be configured via the launcher executable's [STRINGTABLE](https
* **`ID_STR_CMDARGS` (#3)** * **`ID_STR_CMDARGS` (#3)**
Specifies *additional* fixed command-line parameters to be passed to the Java application. 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`). 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. 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. 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! *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`). 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. 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. 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! *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). 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)** * **`ID_STR_JAVAURL` (#9)**
Specifies the required ***bitness*** of the JRE. This can be either **`32`** (x86, aka i586) or **`64`** (x86-64). The Java download URL that will ne suggested, if **no** suitable JRE could be detected on the machine.
If not specified, 32-Bit *and* 64-Bit JREs are accepted, with a preference to 64-Bit. If not specified, wes suggest downloading OpenJDK as provided by the [AdoptOpenJDK](https://adoptopenjdk.net/) project.
(This option only applies to the `registry` variant of Launch5j) (This option only applies to the “registry” variant of Launch5j)
* **`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.
*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! *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 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 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. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
[∎](https://www.youtube.com/watch?v=EfbbjY9MlQs)

View File

@ -40,7 +40,8 @@ public class MakefileGenerator {
for(int registry = 0; registry < 2; ++registry) { for(int registry = 0; registry < 2; ++registry) {
for(int stayAlive = 1; stayAlive > -1; --stayAlive) { for(int stayAlive = 1; stayAlive > -1; --stayAlive) {
for(int enableSplash = 1; enableSplash > -1; --enableSplash) { 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(); out.println();
} }
private static String generateCommand(final List<String> filenNames, final int wrapped, final int registry, final int stayAlive, final int enableSplash) private static String generateCommand(final List<String> filenNames,
final int wrapped, final int registry, final int stayAlive, final int enableSplash)
{ {
final String fileName = String.format("bin/launch5j_$(CPU_ARCH)%s.exe", final String fileName = String.format("bin/launch5j_$(CPU_ARCH)%s.exe",
generateNameSuffix(wrapped, registry, stayAlive, enableSplash)); generateNameSuffix(wrapped, registry, stayAlive, enableSplash));
final StringBuilder cmdLine = new StringBuilder(String.format( final StringBuilder cmdLine = new StringBuilder(String.format(
"\t$(CC) $(CFLAGS) " "\t$(CC) $(CFLAGS) "
+ "-DJAR_FILE_WRAPPED=%d " + "-DL5J_JAR_FILE_WRAPPED=%d "
+ "-DDETECT_REGISTRY=%d " + "-DL5J_DETECT_REGISTRY=%d "
+ "-DSTAY_ALIVE=%d " + "-DL5J_STAY_ALIVE=%d "
+ "-DENABLE_SPLASH=%d " + "-DL5J_ENABLE_SPLASH=%d "
+ "-o %s " + "-o %s "
+ "src/head.c obj/common.$(CPU_ARCH).o", + "src/head.c obj/common.$(CPU_ARCH).o",
wrapped, wrapped,

31
res/assets/manifest.xml Normal file
View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="MuldeRsoft.Launch5j.ExeHead" type="win32"/>
<description>Launch5j</description>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker"/>
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!--The ID below indicates application support for Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!--The ID below indicates application support for Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!--The ID below indicates application support for Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!--The ID below indicates application support for Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!--The ID below indicates application support for Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
</dependentAssembly>
</dependency>
</assembly>

View File

@ -40,6 +40,7 @@ BEGIN
ID_STR_HEADING L"?" /*custom application title*/ ID_STR_HEADING L"?" /*custom application title*/
ID_STR_JVMARGS L"?" /*additional JVM args*/ ID_STR_JVMARGS L"?" /*additional JVM args*/
ID_STR_CMDARGS L"?" /*additional command-line 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*/ ID_STR_MUTEXID L"?" /*single instance mutex ID*/
END END
@ -81,3 +82,9 @@ BEGIN
VALUE "Translation", 0x0, 1200 VALUE "Translation", 0x0, 1200
END END
END END
/////////////////////////////////////////////////////////////////////////////
// Manifest
/////////////////////////////////////////////////////////////////////////////
1 RT_MANIFEST "assets/manifest.xml"

View File

@ -34,4 +34,5 @@ BEGIN
ID_STR_JAVAMIN L"?" /*min supported JRE version, in "w.x.y.z" format*/ 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_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_BITNESS L"?" /*required JRE "bitness", i.e. "32" or "64"*/
ID_STR_JAVAURL L"?" /*Java download URL, if no usable JRE was found*/
END END

View File

@ -29,25 +29,25 @@
#include "resource.h" #include "resource.h"
// Options // Options
#ifndef JAR_FILE_WRAPPED #ifndef L5J_JAR_FILE_WRAPPED
#define JAR_FILE_WRAPPED 0 #error L5J_JAR_FILE_WRAPPED flag is *not* defined!
#endif #endif
#ifndef DETECT_REGISTRY #ifndef L5J_DETECT_REGISTRY
#define DETECT_REGISTRY 0 #error L5J_DETECT_REGISTRY flag is *not* defined!
#endif #endif
#ifndef ENABLE_SPLASH #ifndef L5J_ENABLE_SPLASH
#define ENABLE_SPLASH 1 #error L5J_ENABLE_SPLASH flag is *not* defined!
#endif #endif
#ifndef STAY_ALIVE #ifndef L5J_STAY_ALIVE
#define STAY_ALIVE 1 #error L5J_STAY_ALIVE flag is *not* defined!
#endif #endif
#ifndef WAIT_FOR_WINDOW #ifndef L5J_WAIT_FOR_WINDOW
#define WAIT_FOR_WINDOW 1 #define L5J_WAIT_FOR_WINDOW 1
#endif #endif
// Const // Const
static const wchar_t *const JRE_RELATIVE_PATH = L"runtime\\bin\\javaw.exe"; static const wchar_t *const JRE_DOWNLOAD_LINK_DEFAULT = L"https://adoptopenjdk.net/";
static const wchar_t *const JRE_DOWNLOAD_LINK = 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 size_t MIN_MUTEXID_LENGTH = 5U;
static const DWORD SPLASH_SCREEN_TIMEOUT = 30000U; 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) 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*/ return wcsdup(executable_path); /*JAR file is wrapped*/
#else #else
const wchar_t *jarfile_path = NULL; 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(); const DWORD ticks_start = GetTickCount();
for (;;) 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); const HWND child_hwnd = find_window_by_process_id(process_id);
if (child_hwnd) if (child_hwnd)
@ -888,12 +888,13 @@ static int show_message_format(HWND hwnd, const DWORD flags, const wchar_t *cons
return result; 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[] = const DWORD req_version_comp[] =
{ {
(required_ver >> 48) & 0xFFFF, (required_ver >> 32) & 0xFFFF, (required_ver >> 16) & 0xFFFF, required_ver & 0xFFFF (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) 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]) ? 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) : ((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])); : awprintf(L"%u.%u", req_version_comp[0U], req_version_comp[1U]));
if(version_str) 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) const int result = (required_bitness == 0U)
? show_message_format(hwnd, MB_ICONWARNING | MB_OKCANCEL | MB_TOPMOST, title, ? 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"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", 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, : 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"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"Only the %u-Bit (%ls) version of the JRE is supported!\n\n",
L"We recommend downloading the OpenJDK runtime:\n%ls", 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) 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 WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{ {
int result = -1; 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; HANDLE mutex_handle = NULL;
DWORD java_required_bitness = 0U; DWORD java_required_bitness = 0U;
ULONGLONG java_required_ver_min = 0ULL, java_required_ver_max = 0ULL; ULONGLONG java_required_ver_min = 0ULL, java_required_ver_max = 0ULL;
HGDIOBJ splash_image = NULL; HGDIOBJ splash_image = NULL;
BOOL have_screen_created = FALSE;
PROCESS_INFORMATION process_info; PROCESS_INFORMATION process_info;
STARTUPINFOW startup_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); 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 // Single instance
#if L5J_STAY_ALIVE
mutex_name = load_string(hInstance, ID_STR_MUTEXID); mutex_name = load_string(hInstance, ID_STR_MUTEXID);
if (AVAILABLE(mutex_name) && (wcslen(mutex_name) >= MIN_MUTEXID_LENGTH + ((mutex_name[0U] == L'@') ? 0U : 1U))) 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; goto cleanup;
} }
} }
#endif
// Show the splash screen // 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 (splash_image = LoadImage(hInstance, MAKEINTRESOURCE(ID_BITMAP_SPLASH), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE))
{ {
if (create_splash_screen(hwnd, splash_image)) if (create_splash_screen(hwnd, splash_image))
{ {
have_screen_created = TRUE;
process_window_messages(hwnd); process_window_messages(hwnd);
} }
} }
@ -1073,7 +1081,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine
} }
// Does the JAR file exist? // Does the JAR file exist?
#if !JAR_FILE_WRAPPED #if !L5J_JAR_FILE_WRAPPED
if (!file_exists(jarfile_path)) 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); 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 #endif
// Find the Java runtime executable path (possibly from the registry) // 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_min = load_java_version(hInstance, ID_STR_JAVAMIN, (8ull << 48));
java_required_ver_max = load_java_version(hInstance, ID_STR_JAVAMAX, MAXULONGLONG); java_required_ver_max = load_java_version(hInstance, ID_STR_JAVAMAX, MAXULONGLONG);
java_required_bitness = load_java_bitness(hInstance, ID_STR_BITNESS); 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))) 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_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; goto cleanup;
} }
#else #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!"); show_message(hwnd, MB_ICONERROR | MB_TOPMOST, APP_HEADING, L"The path of the Java runtime could not be determined!");
goto cleanup; goto cleanup;
@ -1124,7 +1133,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine
} }
// Process pending window messages // Process pending window messages
#if ENABLE_SPLASH #if L5J_ENABLE_SPLASH
process_window_messages(hwnd); process_window_messages(hwnd);
#endif #endif
@ -1145,16 +1154,23 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine
} }
// Process pending window messages // Process pending window messages
#if ENABLE_SPLASH #if L5J_ENABLE_SPLASH
process_window_messages(hwnd); 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); wait_for_process_ready(hwnd, process_info.hProcess, process_info.dwProcessId);
#endif #endif
destroy_window(&hwnd);
#endif #endif
// Hide the splash screen now
if (have_screen_created)
{
ShowWindow(hwnd, SW_HIDE);
}
// Wait for process to exit, then get the exit code // 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))) if (signaled_or_failed(WaitForSingleObject(process_info.hProcess, INFINITE)))
{ {
DWORD exit_code = 0U; DWORD exit_code = 0U;
@ -1181,6 +1197,7 @@ cleanup:
free((void*)command_line); free((void*)command_line);
free((void*)java_runtime_path); free((void*)java_runtime_path);
free((void*)jarfile_path); free((void*)jarfile_path);
free((void*)jre_relative_path);
free((void*)executable_directory); free((void*)executable_directory);
free((void*)executable_path); free((void*)executable_path);
free((void*)mutex_name); free((void*)mutex_name);

View File

@ -21,7 +21,9 @@
#define ID_STR_HEADING 1 #define ID_STR_HEADING 1
#define ID_STR_JVMARGS 2 #define ID_STR_JVMARGS 2
#define ID_STR_CMDARGS 3 #define ID_STR_CMDARGS 3
#define ID_STR_JAVAMIN 4 #define ID_STR_JREPATH 4
#define ID_STR_JAVAMAX 5 #define ID_STR_MUTEXID 5
#define ID_STR_BITNESS 6 #define ID_STR_JAVAMIN 6
#define ID_STR_MUTEXID 7 #define ID_STR_JAVAMAX 7
#define ID_STR_BITNESS 8
#define ID_STR_JAVAURL 9