OSDN Git Service

起動時にJava環境がバンドル位置にもレジストリからも発見できなかった場合、
authorseraphy <seraphy@users.osdn.me>
Sun, 30 Dec 2018 08:43:36 +0000 (17:43 +0900)
committerseraphy <seraphy@users.osdn.me>
Sun, 30 Dec 2018 08:43:36 +0000 (17:43 +0900)
ユーザーにJAVA_HOMEの場所を問い合わせるランチャにした。

37 files changed:
pom.xml
src/Launch4JStub/head/consolehead.o [new file with mode: 0644]
src/Launch4JStub/head/guihead.o [new file with mode: 0644]
src/Launch4JStub/head/head.o [new file with mode: 0644]
src/Launch4JStub/head_src/LICENSE.txt [new file with mode: 0644]
src/Launch4JStub/head_src/consolehead/.gitignore [new file with mode: 0644]
src/Launch4JStub/head_src/consolehead/Makefile.win [new file with mode: 0644]
src/Launch4JStub/head_src/consolehead/consolehead.c [new file with mode: 0644]
src/Launch4JStub/head_src/consolehead/consolehead.dev [new file with mode: 0644]
src/Launch4JStub/head_src/guihead/.gitignore [new file with mode: 0644]
src/Launch4JStub/head_src/guihead/Makefile.win [new file with mode: 0644]
src/Launch4JStub/head_src/guihead/guihead.c [new file with mode: 0644]
src/Launch4JStub/head_src/guihead/guihead.dev [new file with mode: 0644]
src/Launch4JStub/head_src/guihead/guihead.h [new file with mode: 0644]
src/Launch4JStub/head_src/head.c [new file with mode: 0644]
src/Launch4JStub/head_src/head.h [new file with mode: 0644]
src/Launch4JStub/head_src/jniconsolehead_BETA/.gitignore [new file with mode: 0644]
src/Launch4JStub/head_src/jniconsolehead_BETA/Makefile.win [new file with mode: 0644]
src/Launch4JStub/head_src/jniconsolehead_BETA/jniconsolehead.c [new file with mode: 0644]
src/Launch4JStub/head_src/jniconsolehead_BETA/jniconsolehead.dev [new file with mode: 0644]
src/Launch4JStub/head_src/jniguihead_BETA/.gitignore [new file with mode: 0644]
src/Launch4JStub/head_src/jniguihead_BETA/Makefile.win [new file with mode: 0644]
src/Launch4JStub/head_src/jniguihead_BETA/jniguihead.c [new file with mode: 0644]
src/Launch4JStub/head_src/jniguihead_BETA/jniguihead.dev [new file with mode: 0644]
src/Launch4JStub/head_src/jniguihead_BETA/jniguihead.h [new file with mode: 0644]
src/Launch4JStub/head_src/jnihead.c [new file with mode: 0644]
src/Launch4JStub/head_src/jnihead.h [new file with mode: 0644]
src/Launch4JStub/head_src/resource.h [new file with mode: 0644]
src/Launch4JStub/w32api/crt2.o [new file with mode: 0644]
src/Launch4JStub/w32api/libadvapi32.a [new file with mode: 0644]
src/Launch4JStub/w32api/libgcc.a [new file with mode: 0644]
src/Launch4JStub/w32api/libkernel32.a [new file with mode: 0644]
src/Launch4JStub/w32api/libmingw32.a [new file with mode: 0644]
src/Launch4JStub/w32api/libmsvcrt.a [new file with mode: 0644]
src/Launch4JStub/w32api/libshell32.a [new file with mode: 0644]
src/Launch4JStub/w32api/libshfolder.a [new file with mode: 0644]
src/Launch4JStub/w32api/libuser32.a [new file with mode: 0644]

diff --git a/pom.xml b/pom.xml
index 2f2c370..7a22495 100644 (file)
--- a/pom.xml
+++ b/pom.xml
                                <plugins>
                                        <plugin>
                                                <!-- Launch4jによるjarファイルのexe化を行う. http://launch4j.sourceforge.net/docs.html
-                                                       プラグインが1.7.24の場合、使用するのはLaunch4j 3.12 である。
+                                                       プラグインが1.7.25の場合、使用するのはLaunch4j 3.12 である。
                                                        https://github.com/lukaszlenart/launch4j-maven-plugin/blob/master/pom.xml -->
                                                <groupId>com.akathist.maven.plugins.launch4j</groupId>
                                                <artifactId>launch4j-maven-plugin</artifactId>
-                                               <version>1.7.24</version>
+                                               <version>1.7.25</version>
                                                <executions>
                                                        <execution>
                                                                <id>l4j-gui</id>
                                                                        <jar>target/${project.artifactId}.jar</jar>
                                                                        <errTitle>Failed to execute the ${project.artifactId}</errTitle>
                                                                        <icon>icon.ico</icon>
+                                                                       <downloadUrl>https://adoptopenjdk.net/</downloadUrl>
+                                                                       <supportUrl>https://osdn.net/projects/charactermanaj/</supportUrl>
+                                                                       <objs>
+                                                                               <!-- 標準のLaunch4jの起動をカスタマイズして、JREがバンドル位置にも
+                                                                               レジストリにも見つからなかった場合は、ユーザーに場所の選択を問い合わせる -->
+                                                                               <obj>src/Launch4JStub/w32api/crt2.o</obj>
+                                                                               <obj>src/Launch4JStub/head/head.o</obj>
+                                                                               <obj>src/Launch4JStub/head/guihead.o</obj>
+                                                                       </objs>
+                                                                       <libs>
+                                                                               <lib>src/Launch4jStub/w32api/libmingw32.a</lib>
+                                                                               <lib>src/Launch4jStub/w32api/libgcc.a</lib>
+                                                                               <lib>src/Launch4jStub/w32api/libmsvcrt.a</lib>
+                                                                               <lib>src/Launch4jStub/w32api/libkernel32.a</lib>
+                                                                               <lib>src/Launch4jStub/w32api/libuser32.a</lib>
+                                                                               <lib>src/Launch4jStub/w32api/libadvapi32.a</lib>
+                                                                               <lib>src/Launch4jStub/w32api/libshell32.a</lib>
+                                                                               <lib>src/Launch4jStub/w32api/libshfolder.a</lib>
+                                                                       </libs>
                                                                        <jre>
                                                                                <path>jre</path>
-                                                                               <minVersion>1.5.0</minVersion>
+                                                                               <minVersion>1.6.0</minVersion>
                                                                                <initialHeapSize>64</initialHeapSize>
                                                                                <maxHeapSize>128</maxHeapSize>
                                                                        </jre>
diff --git a/src/Launch4JStub/head/consolehead.o b/src/Launch4JStub/head/consolehead.o
new file mode 100644 (file)
index 0000000..5fbc5e8
Binary files /dev/null and b/src/Launch4JStub/head/consolehead.o differ
diff --git a/src/Launch4JStub/head/guihead.o b/src/Launch4JStub/head/guihead.o
new file mode 100644 (file)
index 0000000..3cec998
Binary files /dev/null and b/src/Launch4JStub/head/guihead.o differ
diff --git a/src/Launch4JStub/head/head.o b/src/Launch4JStub/head/head.o
new file mode 100644 (file)
index 0000000..073b871
Binary files /dev/null and b/src/Launch4JStub/head/head.o differ
diff --git a/src/Launch4JStub/head_src/LICENSE.txt b/src/Launch4JStub/head_src/LICENSE.txt
new file mode 100644 (file)
index 0000000..a08f808
--- /dev/null
@@ -0,0 +1,26 @@
+Launch4j (http://launch4j.sourceforge.net/)
+Cross-platform Java application wrapper for creating Windows native executables.
+
+Copyright (c) 2004, 2015 Grzegorz Kowal
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR 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.
diff --git a/src/Launch4JStub/head_src/consolehead/.gitignore b/src/Launch4JStub/head_src/consolehead/.gitignore
new file mode 100644 (file)
index 0000000..b566d3b
--- /dev/null
@@ -0,0 +1,2 @@
+/consolehead.exe
+/consolehead.layout
diff --git a/src/Launch4JStub/head_src/consolehead/Makefile.win b/src/Launch4JStub/head_src/consolehead/Makefile.win
new file mode 100644 (file)
index 0000000..23cb75a
--- /dev/null
@@ -0,0 +1,33 @@
+# Project: consolehead
+# Makefile created by Dev-C++ 4.9.9.2
+
+CPP  = g++.exe
+CC   = gcc.exe
+WINDRES = windres.exe
+RES  = 
+OBJ  = ../../head/consolehead.o ../../head/head.o $(RES)
+LINKOBJ  = ../../head/consolehead.o ../../head/head.o $(RES)
+LIBS =  -L"C:/Dev-Cpp/lib" -n  -s 
+INCS =  -I"C:/Dev-Cpp/include" 
+CXXINCS =  -I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include"  -I"C:/Dev-Cpp/include/c++/3.4.2/backward"  -I"C:/Dev-Cpp/include/c++/3.4.2/mingw32"  -I"C:/Dev-Cpp/include/c++/3.4.2"  -I"C:/Dev-Cpp/include" 
+BIN  = consolehead.exe
+CXXFLAGS = $(CXXINCS)   -fexpensive-optimizations -O3
+CFLAGS = $(INCS)   -fexpensive-optimizations -O3
+RM = rm -f
+
+.PHONY: all all-before all-after clean clean-custom
+
+all: all-before consolehead.exe all-after
+
+
+clean: clean-custom
+       ${RM} $(OBJ) $(BIN)
+
+$(BIN): $(OBJ)
+#      $(CC) $(LINKOBJ) -o "consolehead.exe" $(LIBS)
+
+../../head/consolehead.o: consolehead.c
+       $(CC) -c consolehead.c -o ../../head/consolehead.o $(CFLAGS)
+
+../../head/head.o: ../head.c
+       $(CC) -c ../head.c -o ../../head/head.o $(CFLAGS)
diff --git a/src/Launch4JStub/head_src/consolehead/consolehead.c b/src/Launch4JStub/head_src/consolehead/consolehead.c
new file mode 100644 (file)
index 0000000..1846a56
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+       Launch4j (http://launch4j.sourceforge.net/)
+       Cross-platform Java application wrapper for creating Windows native executables.
+
+       Copyright (c) 2004, 2007 Grzegorz Kowal
+
+       Permission is hereby granted, free of charge, to any person obtaining a copy
+       of this software and associated documentation files (the "Software"), to deal
+       in the Software without restriction, including without limitation the rights
+       to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+       copies of the Software, and to permit persons to whom the Software is
+       furnished to do so, subject to the following conditions:
+
+       The above copyright notice and this permission notice shall be included in
+       all copies or substantial portions of the Software.
+
+       Except as contained in this notice, the name(s) of the above copyright holders
+       shall not be used in advertising or otherwise to promote the sale, use or other
+       dealings in this Software without prior written authorization.
+
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+       IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+       FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+       AUTHORS OR 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.
+*/
+
+#include "../resource.h"
+#include "../head.h"
+
+extern FILE* hLog;
+
+BOOL restartOnCrash = FALSE;
+
+int main(int argc, char* argv[])
+{
+    setConsoleFlag();
+       LPTSTR cmdLine = GetCommandLine();
+
+       if (*cmdLine == '"')
+       {
+               if (*(cmdLine = strchr(cmdLine + 1, '"') + 1))
+               {
+                       cmdLine++;
+               }
+       }
+       else if ((cmdLine = strchr(cmdLine, ' ')) != NULL)
+       {
+               cmdLine++;
+       }
+       else
+       {
+               cmdLine = "";
+       }
+
+       int result = prepare(cmdLine);
+
+       if (result == ERROR_ALREADY_EXISTS)
+       {
+               char errMsg[BIG_STR] = {0};
+               loadString(INSTANCE_ALREADY_EXISTS_MSG, errMsg);
+               msgBox(errMsg);
+               closeLogFile();
+               return 2;
+       }
+
+       if (result != TRUE)
+       {
+               signalError();
+               return 1;
+       }
+
+       restartOnCrash = loadBool(RESTART_ON_CRASH);
+       DWORD dwExitCode;
+
+       do
+       {
+               dwExitCode = 0;
+       
+               if (!execute(TRUE, &dwExitCode))
+               {
+                       signalError();
+                       break;
+               }
+
+               if (restartOnCrash && dwExitCode != 0)
+               {
+                       debug("Exit code:\t%d, restarting the application!\n", dwExitCode);
+               }
+       } while (restartOnCrash && dwExitCode != 0);
+
+       debug("Exit code:\t%d\n", dwExitCode);
+       closeLogFile();
+       return (int) dwExitCode;
+}
diff --git a/src/Launch4JStub/head_src/consolehead/consolehead.dev b/src/Launch4JStub/head_src/consolehead/consolehead.dev
new file mode 100644 (file)
index 0000000..94883ea
--- /dev/null
@@ -0,0 +1,108 @@
+[Project]
+FileName=consolehead.dev
+Name=consolehead
+UnitCount=4
+Type=1
+Ver=1
+ObjFiles=
+Includes=
+Libs=
+PrivateResource=
+ResourceIncludes=
+MakeIncludes=
+Compiler=
+CppCompiler=
+Linker=-n_@@_
+IsCpp=0
+Icon=
+ExeOutput=
+ObjectOutput=..\..\head
+OverrideOutput=0
+OverrideOutputName=consolehead.exe
+HostApplication=
+Folders=
+CommandLine=
+UseCustomMakefile=1
+CustomMakefile=Makefile.win
+IncludeVersionInfo=0
+SupportXPThemes=0
+CompilerSet=0
+CompilerSettings=0000000001001000000100
+
+[Unit1]
+FileName=consolehead.c
+CompileCpp=0
+Folder=consolehead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[VersionInfo]
+Major=0
+Minor=1
+Release=1
+Build=1
+LanguageID=1033
+CharsetID=1252
+CompanyName=
+FileVersion=
+FileDescription=Developed using the Dev-C++ IDE
+InternalName=
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=
+ProductName=
+ProductVersion=
+AutoIncBuildNr=0
+
+[Unit2]
+FileName=..\resource.h
+CompileCpp=0
+Folder=consolehead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit3]
+FileName=..\head.c
+CompileCpp=0
+Folder=consolehead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit4]
+FileName=..\head.h
+CompileCpp=0
+Folder=consolehead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit5]
+FileName=..\head.rc
+Folder=consolehead
+Compile=1
+Link=0
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit6]
+FileName=..\resid.h
+CompileCpp=0
+Folder=consolehead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
diff --git a/src/Launch4JStub/head_src/guihead/.gitignore b/src/Launch4JStub/head_src/guihead/.gitignore
new file mode 100644 (file)
index 0000000..5ddac15
--- /dev/null
@@ -0,0 +1,2 @@
+/guihead.exe
+/guihead.layout
diff --git a/src/Launch4JStub/head_src/guihead/Makefile.win b/src/Launch4JStub/head_src/guihead/Makefile.win
new file mode 100644 (file)
index 0000000..0109be4
--- /dev/null
@@ -0,0 +1,33 @@
+# Project: guihead
+# Makefile created by Dev-C++ 4.9.9.2
+
+CPP  = g++.exe
+CC   = gcc.exe
+WINDRES = windres.exe
+RES  = 
+OBJ  = ../../head/guihead.o ../../head/head.o $(RES)
+LINKOBJ  = ../../head/guihead.o ../../head/head.o $(RES)
+LIBS =  -L"C:/Dev-Cpp/lib" -mwindows -n  -s 
+INCS =  -I"C:/Dev-Cpp/include" 
+CXXINCS =  -I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include"  -I"C:/Dev-Cpp/include/c++/3.4.2/backward"  -I"C:/Dev-Cpp/include/c++/3.4.2/mingw32"  -I"C:/Dev-Cpp/include/c++/3.4.2"  -I"C:/Dev-Cpp/include" 
+BIN  = guihead.exe
+CXXFLAGS = $(CXXINCS)   -fexpensive-optimizations -O3
+CFLAGS = $(INCS)   -fexpensive-optimizations -O3
+RM = rm -f
+
+.PHONY: all all-before all-after clean clean-custom
+
+all: all-before guihead.exe all-after
+
+
+clean: clean-custom
+       ${RM} $(OBJ) $(BIN)
+
+$(BIN): $(OBJ)
+#      $(CC) $(LINKOBJ) -o "guihead.exe" $(LIBS)
+
+../../head/guihead.o: guihead.c
+       $(CC) -c guihead.c -o ../../head/guihead.o $(CFLAGS)
+
+../../head/head.o: ../head.c
+       $(CC) -c ../head.c -o ../../head/head.o $(CFLAGS)
diff --git a/src/Launch4JStub/head_src/guihead/guihead.c b/src/Launch4JStub/head_src/guihead/guihead.c
new file mode 100644 (file)
index 0000000..6d165a2
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+       Launch4j (http://launch4j.sourceforge.net/)
+       Cross-platform Java application wrapper for creating Windows native executables.
+
+       Copyright (c) 2004, 2015 Grzegorz Kowal
+                                                        Sylvain Mina (single instance patch)
+
+       Permission is hereby granted, free of charge, to any person obtaining a copy
+       of this software and associated documentation files (the "Software"), to deal
+       in the Software without restriction, including without limitation the rights
+       to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+       copies of the Software, and to permit persons to whom the Software is
+       furnished to do so, subject to the following conditions:
+
+       The above copyright notice and this permission notice shall be included in
+       all copies or substantial portions of the Software.
+
+       Except as contained in this notice, the name(s) of the above copyright holders
+       shall not be used in advertising or otherwise to promote the sale, use or other
+       dealings in this Software without prior written authorization.
+
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+       IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+       FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+       AUTHORS OR 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.
+*/
+
+#include "../resource.h"
+#include "../head.h"
+#include "guihead.h"
+
+extern FILE* hLog;
+extern PROCESS_INFORMATION processInformation;
+
+HWND hWnd;
+DWORD dwExitCode = 0;
+BOOL stayAlive = FALSE;
+BOOL splash = FALSE;
+BOOL splashTimeoutErr;
+BOOL waitForWindow;
+BOOL restartOnCrash = FALSE;
+int splashTimeout = DEFAULT_SPLASH_TIMEOUT;
+
+int APIENTRY WinMain(HINSTANCE hInstance,
+                     HINSTANCE hPrevInstance,
+                     LPSTR     lpCmdLine,
+                     int       nCmdShow)
+{
+       int result = prepare(lpCmdLine);
+
+       if (result == ERROR_ALREADY_EXISTS)
+       {
+               HWND handle = getInstanceWindow();
+               ShowWindow(handle, SW_SHOW);
+               SetForegroundWindow(handle);
+               closeLogFile();
+               return 2;
+       }
+
+       if (result != TRUE)
+       {
+               signalError();
+               return 1;
+       }
+
+       splash = loadBool(SHOW_SPLASH)
+                       && strstr(lpCmdLine, "--l4j-no-splash") == NULL;
+       restartOnCrash = loadBool(RESTART_ON_CRASH);
+
+       // if we should restart on crash, we must also stay alive to check for crashes
+       stayAlive = restartOnCrash ||
+                         (loadBool(GUI_HEADER_STAYS_ALIVE)
+                       && strstr(lpCmdLine, "--l4j-dont-wait") == NULL);
+                       
+       if (splash || stayAlive)
+       {
+               hWnd = CreateWindowEx(WS_EX_TOOLWINDOW, "STATIC", "",
+                               WS_POPUP | SS_BITMAP,
+                               0, 0, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
+               if (splash)
+               {
+                       char timeout[10] = {0};
+                       if (loadString(SPLASH_TIMEOUT, timeout))
+                       {
+                               splashTimeout = atoi(timeout);
+                               if (splashTimeout <= 0 || splashTimeout > MAX_SPLASH_TIMEOUT)
+                               {
+                                       splashTimeout = DEFAULT_SPLASH_TIMEOUT;
+                               }
+                       }
+                       splashTimeout = splashTimeout * 1000; // to millis
+                       splashTimeoutErr = loadBool(SPLASH_TIMEOUT_ERR)
+                                       && strstr(lpCmdLine, "--l4j-no-splash-err") == NULL;
+                       waitForWindow = loadBool(SPLASH_WAITS_FOR_WINDOW);
+                       HANDLE hImage = LoadImage(hInstance,    // handle of the instance containing the image
+                                       MAKEINTRESOURCE(SPLASH_BITMAP), // name or identifier of image
+                                       IMAGE_BITMAP,                                   // type of image
+                                       0,                                                              // desired width
+                                       0,                                                              // desired height
+                                       LR_DEFAULTSIZE);
+                       if (hImage == NULL)
+                       {
+                               signalError();
+                               return 1;
+                       }
+                       SendMessage(hWnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hImage);
+                       RECT rect;
+                       GetWindowRect(hWnd, &rect);
+                       int x = (GetSystemMetrics(SM_CXSCREEN) - (rect.right - rect.left)) / 2;
+                       int y = (GetSystemMetrics(SM_CYSCREEN) - (rect.bottom - rect.top)) / 2;
+                       SetWindowPos(hWnd, HWND_TOP, x, y, 0, 0, SWP_NOSIZE);
+                       ShowWindow(hWnd, nCmdShow);
+                       UpdateWindow (hWnd);
+               }
+       }
+
+       do
+       {
+               if (splash || stayAlive)
+               {
+                       if (!SetTimer (hWnd, ID_TIMER, TIMER_PROC_INTERVAL, TimerProc))
+                       {
+                               signalError();
+                               return 1;
+                       }
+               }
+
+               if (!execute(FALSE, &dwExitCode))
+               {
+                       signalError();
+                       return 1;
+               }
+
+               if (!(splash || stayAlive))
+               {
+                       debug("Exit code:\t0\n");
+                       closeProcessHandles();
+                       closeLogFile();
+                       return 0;
+               }
+       
+               MSG msg;
+               while (GetMessage(&msg, NULL, 0, 0))
+               {
+                       TranslateMessage(&msg);
+                       DispatchMessage(&msg);
+               }
+               
+               if (restartOnCrash && dwExitCode != 0)
+               {
+                       debug("Exit code:\t%d, restarting the application!\n", dwExitCode);
+               }
+
+               closeProcessHandles();
+       } while (restartOnCrash && dwExitCode != 0);
+
+       debug("Exit code:\t%d\n", dwExitCode);
+       closeLogFile();
+       return dwExitCode;
+}
+
+HWND getInstanceWindow()
+{
+       char windowTitle[STR];
+       char instWindowTitle[STR] = {0};
+       if (loadString(INSTANCE_WINDOW_TITLE, instWindowTitle))
+       {
+               HWND handle = FindWindowEx(NULL, NULL, NULL, NULL); 
+               while (handle != NULL)
+               {
+                       GetWindowText(handle, windowTitle, STR - 1);
+                       if (strstr(windowTitle, instWindowTitle) != NULL)
+                       {
+                               return handle;
+                       }
+                       else
+                       {
+                               handle = FindWindowEx(NULL, handle, NULL, NULL);
+                       }
+               }
+       }
+       return NULL;   
+}
+
+BOOL CALLBACK enumwndfn(HWND hwnd, LPARAM lParam)
+{
+       DWORD processId;
+       GetWindowThreadProcessId(hwnd, &processId);
+       if (processInformation.dwProcessId == processId)
+       {
+               LONG styles = GetWindowLong(hwnd, GWL_STYLE);
+               if ((styles & WS_VISIBLE) != 0)
+               {
+                       splash = FALSE;
+                       ShowWindow(hWnd, SW_HIDE);
+                       return FALSE;
+               }
+       }
+       return TRUE;
+}
+
+VOID CALLBACK TimerProc(
+       HWND hwnd,                      // handle of window for timer messages
+       UINT uMsg,                      // WM_TIMER message
+       UINT idEvent,           // timer identifier
+       DWORD dwTime)           // current system time
+{
+       if (splash)
+       {
+               if (splashTimeout == 0)
+               {
+                       splash = FALSE;
+                       ShowWindow(hWnd, SW_HIDE);
+                       if (waitForWindow && splashTimeoutErr)
+                       {
+                               KillTimer(hwnd, ID_TIMER);
+                               signalError();
+                               PostQuitMessage(0);
+                       }
+               }
+               else
+               {
+                       splashTimeout -= TIMER_PROC_INTERVAL;
+                       if (waitForWindow)
+                       {
+                               EnumWindows(enumwndfn, 0);
+                       }
+               }
+       }
+
+       GetExitCodeProcess(processInformation.hProcess, &dwExitCode);
+       if (dwExitCode != STILL_ACTIVE
+                       || !(splash || stayAlive))
+       {
+               KillTimer(hWnd, ID_TIMER);
+               PostQuitMessage(0);
+       }
+}
diff --git a/src/Launch4JStub/head_src/guihead/guihead.dev b/src/Launch4JStub/head_src/guihead/guihead.dev
new file mode 100644 (file)
index 0000000..3addd6f
--- /dev/null
@@ -0,0 +1,109 @@
+[Project]
+FileName=guihead.dev
+Name=guihead
+UnitCount=5
+Type=0
+Ver=1
+ObjFiles=
+Includes=
+Libs=
+PrivateResource=
+ResourceIncludes=
+MakeIncludes=
+Compiler=
+CppCompiler=
+Linker=-n_@@_
+IsCpp=0
+Icon=
+ExeOutput=
+ObjectOutput=..\..\head
+OverrideOutput=0
+OverrideOutputName=guihead.exe
+HostApplication=
+Folders=
+CommandLine=
+UseCustomMakefile=1
+CustomMakefile=Makefile.win
+IncludeVersionInfo=0
+SupportXPThemes=0
+CompilerSet=0
+CompilerSettings=0000000001001000000100
+
+[Unit1]
+FileName=guihead.c
+CompileCpp=0
+Folder=guihead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=$(CC) -c guihead.c -o ../../head/guihead.o $(CFLAGS)
+
+[Unit2]
+FileName=guihead.h
+CompileCpp=0
+Folder=guihead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[VersionInfo]
+Major=0
+Minor=1
+Release=1
+Build=1
+LanguageID=1033
+CharsetID=1252
+CompanyName=
+FileVersion=
+FileDescription=Developed using the Dev-C++ IDE
+InternalName=
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=
+ProductName=
+ProductVersion=
+AutoIncBuildNr=0
+
+[Unit4]
+FileName=..\head.h
+CompileCpp=0
+Folder=guihead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit6]
+FileName=..\resid.h
+CompileCpp=0
+Folder=guihead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit3]
+FileName=..\head.c
+CompileCpp=0
+Folder=guihead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit5]
+FileName=..\resource.h
+CompileCpp=0
+Folder=guihead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
diff --git a/src/Launch4JStub/head_src/guihead/guihead.h b/src/Launch4JStub/head_src/guihead/guihead.h
new file mode 100644 (file)
index 0000000..e8208d3
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+       Launch4j (http://launch4j.sourceforge.net/)
+       Cross-platform Java application wrapper for creating Windows native executables.
+
+       Copyright (c) 2004, 2007 Grzegorz Kowal
+
+       Permission is hereby granted, free of charge, to any person obtaining a copy
+       of this software and associated documentation files (the "Software"), to deal
+       in the Software without restriction, including without limitation the rights
+       to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+       copies of the Software, and to permit persons to whom the Software is
+       furnished to do so, subject to the following conditions:
+
+       The above copyright notice and this permission notice shall be included in
+       all copies or substantial portions of the Software.
+
+       Except as contained in this notice, the name(s) of the above copyright holders
+       shall not be used in advertising or otherwise to promote the sale, use or other
+       dealings in this Software without prior written authorization.
+
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+       IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+       FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+       AUTHORS OR 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.
+*/
+
+#define ID_TIMER 1
+#define DEFAULT_SPLASH_TIMEOUT 60                      /* 60 seconds */
+#define MAX_SPLASH_TIMEOUT             60 * 15         /* 15 minutes */
+#define TIMER_PROC_INTERVAL    100                     /* interval in ms between calls to EnumWindows */
+
+HWND getInstanceWindow();
+
+BOOL CALLBACK enumwndfn(HWND hwnd, LPARAM lParam);
+
+VOID CALLBACK TimerProc(
+  HWND hwnd,     // handle of window for timer messages
+  UINT uMsg,     // WM_TIMER message
+  UINT idEvent,  // timer identifier
+  DWORD dwTime   // current system time
+);
diff --git a/src/Launch4JStub/head_src/head.c b/src/Launch4JStub/head_src/head.c
new file mode 100644 (file)
index 0000000..fcca481
--- /dev/null
@@ -0,0 +1,1580 @@
+/*
+       Launch4j (http://launch4j.sourceforge.net/)
+       Cross-platform Java application wrapper for creating Windows native executables.
+
+       Copyright (c) 2004, 2015 Grzegorz Kowal,
+                                                        Ian Roberts (jdk preference patch)
+                                                        Sylvain Mina (single instance patch)
+
+       Permission is hereby granted, free of charge, to any person obtaining a copy
+       of this software and associated documentation files (the "Software"), to deal
+       in the Software without restriction, including without limitation the rights
+       to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+       copies of the Software, and to permit persons to whom the Software is
+       furnished to do so, subject to the following conditions:
+
+       The above copyright notice and this permission notice shall be included in
+       all copies or substantial portions of the Software.
+
+       Except as contained in this notice, the name(s) of the above copyright holders
+       shall not be used in advertising or otherwise to promote the sale, use or other
+       dealings in this Software without prior written authorization.
+
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+       IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+       FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+       AUTHORS OR 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.
+*/
+
+#include "resource.h"
+#include "head.h"
+
+HMODULE hModule;
+FILE* hLog;
+BOOL debugAll = FALSE;
+BOOL console = FALSE;
+BOOL wow64 = FALSE;
+char oldPwd[_MAX_PATH];
+
+PROCESS_INFORMATION processInformation;
+DWORD processPriority;
+
+struct
+{
+       char title[STR];
+       char msg[BIG_STR];
+       char url[256];
+} error;
+
+struct
+{
+       int runtimeBits;
+       int foundJava;
+       BOOL bundledJreAsFallback;
+       BOOL corruptedJreFound;
+       char originalJavaMinVer[STR];
+       char originalJavaMaxVer[STR];
+       char javaMinVer[STR];
+       char javaMaxVer[STR];
+       char foundJavaVer[STR];
+       char foundJavaKey[_MAX_PATH];
+       char foundJavaHome[_MAX_PATH];
+} search;
+
+struct
+{
+       char mainClass[_MAX_PATH];
+       char cmd[_MAX_PATH];
+       char args[MAX_ARGS];
+} launcher;
+
+BOOL initGlobals()
+{
+       hModule = GetModuleHandle(NULL);
+
+       if (hModule == NULL)
+       {
+               return FALSE;
+       }
+
+       strcpy(error.title, LAUNCH4j);
+
+       search.runtimeBits = INIT_RUNTIME_BITS;
+       search.foundJava = NO_JAVA_FOUND;
+       search.bundledJreAsFallback = FALSE;
+       search.corruptedJreFound = FALSE;
+       
+       return TRUE;
+}
+
+FILE* openLogFile(const char* exePath, const int pathLen)
+{
+       char path[_MAX_PATH] = {0};
+       strncpy(path, exePath, pathLen);
+       strcat(path, "\\launch4j.log");
+       return fopen(path, "a");
+}
+
+void closeLogFile()
+{
+       if (hLog != NULL)
+       {
+               fclose(hLog);   
+       }
+}
+
+BOOL initializeLogging(const char *lpCmdLine, const char* exePath, const int pathLen)
+{
+       char varValue[MAX_VAR_SIZE] = {0};
+       GetEnvironmentVariable(LAUNCH4j, varValue, MAX_VAR_SIZE);
+
+    if (strstr(lpCmdLine, "--l4j-debug") != NULL
+                       || strstr(varValue, "debug") != NULL)
+       {
+               hLog = openLogFile(exePath, pathLen);
+
+               if (hLog == NULL)
+               {
+                       return FALSE;
+               }
+
+               debugAll = strstr(lpCmdLine, "--l4j-debug-all") != NULL
+                               || strstr(varValue, "debug-all") != NULL;
+       }
+       
+       debug("\n\nVersion:\t%s\n", VERSION);
+       debug("CmdLine:\t%s %s\n", exePath, lpCmdLine);
+
+       return TRUE;
+}
+
+void setWow64Flag()
+{
+       LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(
+                       GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
+
+       if (fnIsWow64Process != NULL)
+       {
+               fnIsWow64Process(GetCurrentProcess(), &wow64);
+       }
+
+       debug("WOW64:\t\t%s\n", wow64 ? "yes" : "no"); 
+}
+
+void setConsoleFlag()
+{
+     console = TRUE;
+}
+
+void msgBox(const char* text)
+{
+    if (console)
+       {
+        if (*error.title)
+        {
+            printf("%s: %s\n", error.title, text);
+        }
+        else
+        {
+            printf("%s\n", text);
+        }
+    }
+       else
+       {
+       MessageBox(NULL, text, error.title, MB_OK);
+    }
+}
+
+void signalError()
+{
+       DWORD err = GetLastError();
+       debug("Error msg:\t%s\n", error.msg);
+
+       if (err)
+       {
+               LPVOID lpMsgBuf;
+               FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
+                                               | FORMAT_MESSAGE_FROM_SYSTEM
+                                               | FORMAT_MESSAGE_IGNORE_INSERTS,
+                               NULL,
+                               err,
+                               MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+                           (LPTSTR) &lpMsgBuf,
+                           0,
+                           NULL);
+               debug(ERROR_FORMAT, (LPCTSTR) lpMsgBuf);
+               strcat(error.msg, "\n\n");
+               strcat(error.msg, (LPCTSTR) lpMsgBuf);
+               LocalFree(lpMsgBuf);
+       }
+       
+       msgBox(error.msg);
+
+       if (*error.url)
+       {
+               debug("Open URL:\t%s\n", error.url);
+               ShellExecute(NULL, "open", error.url, NULL, NULL, SW_SHOWNORMAL);
+       }
+
+       closeLogFile();
+}
+
+BOOL loadString(const int resID, char* buffer)
+{
+       HRSRC hResource;
+       HGLOBAL hResourceLoaded;
+       LPBYTE lpBuffer;
+       debugAll("Resource %d:\t", resID);
+
+       hResource = FindResourceEx(hModule, RT_RCDATA, MAKEINTRESOURCE(resID),
+                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT));
+       if (NULL != hResource)
+       {
+               hResourceLoaded = LoadResource(hModule, hResource);
+               if (NULL != hResourceLoaded)
+               {
+                       lpBuffer = (LPBYTE) LockResource(hResourceLoaded);            
+                       if (NULL != lpBuffer)
+                       {     
+                               int x = 0;
+                               do
+                               {
+                                       buffer[x] = (char) lpBuffer[x];
+                               } while (buffer[x++] != 0);
+                               
+                               debugAll("%s\n", buffer);
+                               return TRUE;
+                       }
+               }    
+       }
+       else
+       {
+               SetLastError(0);
+               buffer[0] = 0;
+       }
+       
+       debugAll("<NULL>\n");
+       return FALSE;
+}
+
+BOOL loadBool(const int resID)
+{
+       char boolStr[20] = {0};
+       loadString(resID, boolStr);
+       return strcmp(boolStr, TRUE_STR) == 0;
+}
+
+int loadInt(const int resID)
+{
+       char intStr[20] = {0};
+       loadString(resID, intStr);
+       return atoi(intStr);
+}
+
+BOOL regQueryValue(const char* regPath, unsigned char* buffer,
+               unsigned long bufferLength)
+{
+       HKEY hRootKey;
+       char* key;
+       char* value;
+
+       if (strstr(regPath, HKEY_CLASSES_ROOT_STR) == regPath)
+       {
+               hRootKey = HKEY_CLASSES_ROOT;
+       }
+       else if (strstr(regPath, HKEY_CURRENT_USER_STR) == regPath)
+       {
+               hRootKey = HKEY_CURRENT_USER;
+       }
+       else if (strstr(regPath, HKEY_LOCAL_MACHINE_STR) == regPath)
+       {
+               hRootKey = HKEY_LOCAL_MACHINE;
+       }
+       else if (strstr(regPath, HKEY_USERS_STR) == regPath)
+       {
+               hRootKey = HKEY_USERS;
+       }
+       else if (strstr(regPath, HKEY_CURRENT_CONFIG_STR) == regPath)
+       {
+               hRootKey = HKEY_CURRENT_CONFIG;
+       }
+       else
+       {
+               return FALSE;
+       }
+
+       key = strchr(regPath, '\\') + 1;
+       value = strrchr(regPath, '\\') + 1;
+       *(value - 1) = 0;
+
+       HKEY hKey;
+       unsigned long datatype;
+       BOOL result = FALSE;
+       if ((wow64 && RegOpenKeyEx(hRootKey,
+                                                               key,
+                                                               0,
+                                                       KEY_READ | KEY_WOW64_64KEY,
+                                                               &hKey) == ERROR_SUCCESS)
+                       || RegOpenKeyEx(hRootKey,
+                                                               key,
+                                                               0,
+                                                       KEY_READ,
+                                                               &hKey) == ERROR_SUCCESS)
+       {
+               result = RegQueryValueEx(hKey, value, NULL, &datatype, buffer, &bufferLength)
+                               == ERROR_SUCCESS;
+               RegCloseKey(hKey);
+       }
+       *(value - 1) = '\\';
+       return result;
+}
+
+int findNextVersionPart(const char* startAt)
+{
+       if (startAt == NULL || strlen(startAt) == 0)
+    {
+               return 0;
+       }
+
+       char* firstSeparatorA = strchr(startAt, '.');
+       char* firstSeparatorB = strchr(startAt, '_');
+       char* firstSeparator;
+       if (firstSeparatorA == NULL)
+    {
+               firstSeparator = firstSeparatorB;
+       }
+    else if (firstSeparatorB == NULL)
+    {
+               firstSeparator = firstSeparatorA;
+       }
+    else
+    {
+               firstSeparator = min(firstSeparatorA, firstSeparatorB);
+       }
+
+       if (firstSeparator == NULL)
+    {
+               return strlen(startAt);
+       }
+
+       return firstSeparator - startAt;
+}
+
+/**
+ * This method will take java version from `originalVersion` string and convert/format it
+ * into `version` string that can be used for string comparison with other versions.
+ *
+ * Due to different version schemas <=8 vs. >=9 it will "normalize" versions to 1 format
+ * so we can directly compare old and new versions.
+ */
+void formatJavaVersion(char* version, const char* originalVersion)
+{
+       strcpy(version, "");
+       if (originalVersion == NULL || strlen(originalVersion) == 0)
+    {
+               return;
+       }
+
+       int partsAdded = 0;
+       int i;
+       char* pos = (char*) originalVersion;
+       int curPartLen;
+
+       while ((curPartLen = findNextVersionPart(pos)) > 0)
+    {
+               char number[curPartLen + 1];
+               memset(number, 0, curPartLen + 1);
+               strncpy(number, pos, curPartLen);
+
+               if (partsAdded == 0 && (curPartLen != 1 || number[0] != '1'))
+        {
+                       // NOTE: When it's java 9+ we'll add "1" as the first part of the version
+                       strcpy(version, "1");
+                       partsAdded++;
+               }
+
+               if (partsAdded < 3)
+        {
+                       if (partsAdded > 0)
+            {
+                               strcat(version, ".");
+                       }
+                       for (i = 0;
+                                       (partsAdded > 0)
+                                                       && (i < JRE_VER_MAX_DIGITS_PER_PART - strlen(number));
+                                       i++)
+            {
+                               strcat(version, "0");
+                       }
+                       strcat(version, number);
+               }
+        else if (partsAdded == 3)
+        {
+                       // add as an update
+                       strcat(version, "_");
+                       for (i = 0; i < JRE_VER_MAX_DIGITS_PER_PART - strlen(number); i++)
+            {
+                               strcat(version, "0");
+                       }
+                       strcat(version, number);
+               }
+        else if (partsAdded >= 4)
+        {
+                       debug("Warning:\tformatJavaVersion() too many parts added.\n");
+                       break;
+               }
+               partsAdded++;
+
+               pos += curPartLen + 1;
+               if (pos >= originalVersion + strlen(originalVersion))
+        {
+                       break;
+               }
+       }
+
+       for (i = partsAdded; i < 3; i++)
+    {
+               strcat(version, ".");
+               int j;
+               for (j = 0; j < JRE_VER_MAX_DIGITS_PER_PART; j++)
+        {
+                       strcat(version, "0");
+               }
+       }
+}
+
+void regSearch(const char* keyName, const int searchType)
+{
+       HKEY hKey;
+       const DWORD wow64KeyMask = searchType & KEY_WOW64_64KEY;
+
+       debug("%s-bit search:\t%s...\n", wow64KeyMask ? "64" : "32", keyName);
+
+       if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                       keyName,
+                       0,
+               KEY_READ | wow64KeyMask,
+                       &hKey) == ERROR_SUCCESS)
+       {
+               return;
+       }
+
+       DWORD x = 0;
+       unsigned long versionSize = _MAX_PATH;
+       FILETIME time;
+       char fullKeyName[_MAX_PATH] = {0};
+       char originalVersion[_MAX_PATH] = {0};
+       char version[_MAX_PATH] = {0};
+
+       while (RegEnumKeyEx(
+                               hKey,                   // handle to key to enumerate
+                               x++,                    // index of subkey to enumerate
+                               originalVersion,// address of buffer for subkey name
+                               &versionSize,   // address for size of subkey buffer
+                               NULL,                   // reserved
+                               NULL,                   // address of buffer for class string
+                               NULL,                   // address for size of class buffer
+                               &time) == ERROR_SUCCESS)
+       {
+               strcpy(fullKeyName, keyName);
+               appendPath(fullKeyName, originalVersion);
+               debug("Check:\t\t%s\n", fullKeyName);
+        formatJavaVersion(version, originalVersion);
+
+               if (strcmp(version, search.javaMinVer) >= 0
+                               && (!*search.javaMaxVer || strcmp(version, search.javaMaxVer) <= 0)
+                               && strcmp(version, search.foundJavaVer) > 0
+                               && isJavaHomeValid(fullKeyName, searchType))
+               {
+                       strcpy(search.foundJavaVer, version);
+                       strcpy(search.foundJavaKey, fullKeyName);
+                       search.foundJava = searchType;
+                       debug("Match:\t\t%s\n", version);
+               }
+               else
+               {
+                       debug("Ignore:\t\t%s\n", version);
+               }
+
+               versionSize = _MAX_PATH;
+       }
+
+       RegCloseKey(hKey);
+}
+
+BOOL isJavaHomeValid(const char* keyName, const int searchType)
+{
+       BOOL valid = FALSE;
+       HKEY hKey;
+       char path[_MAX_PATH] = {0};
+
+       if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                       keyName,
+                       0,
+            KEY_READ | (searchType & KEY_WOW64_64KEY),
+                       &hKey) == ERROR_SUCCESS)
+       {
+               unsigned char buffer[_MAX_PATH] = {0};
+               unsigned long bufferlength = _MAX_PATH;
+               unsigned long datatype;
+
+               if (RegQueryValueEx(hKey, "JavaHome", NULL, &datatype, buffer,
+                               &bufferlength) == ERROR_SUCCESS)
+               {
+                       int i = 0;
+                       do
+                       {
+                               path[i] = buffer[i];
+                       } while (path[i++] != 0);
+                       
+                       valid = isLauncherPathValid(path);
+               }
+               RegCloseKey(hKey);
+       }
+
+       if (valid)
+       {
+               strcpy(search.foundJavaHome, path);
+       }
+       else
+       {
+               search.corruptedJreFound = TRUE;
+       }
+
+       return valid;
+}
+
+BOOL isLauncherPathValid(const char* path)
+{
+       struct _stat statBuf;
+       char launcherPath[_MAX_PATH] = {0};
+       BOOL result = FALSE;
+
+       if (*path)
+       {
+               strcpy(launcherPath, path);
+               appendLauncher(launcherPath);
+               result = _stat(launcherPath, &statBuf) == 0;
+
+               if (!result)
+               {
+                       // Don't display additional info in the error popup.
+                       SetLastError(0);
+               }
+       }
+
+       debug("Check launcher:\t%s %s\n", launcherPath, result ? "(OK)" : "(not found)");
+       return result;
+}
+
+void regSearchWow(const char* keyName, const int searchType)
+{
+       if (search.runtimeBits == INIT_RUNTIME_BITS)
+       {
+               search.runtimeBits = loadInt(RUNTIME_BITS);
+       }
+
+       switch (search.runtimeBits)
+       {
+               case USE_64_BIT_RUNTIME:
+                       if (wow64)
+                       {
+                               regSearch(keyName, searchType | KEY_WOW64_64KEY);
+                       }
+                       break;
+
+               case USE_64_AND_32_BIT_RUNTIME:
+                       if (wow64)
+                       {
+                               regSearch(keyName, searchType | KEY_WOW64_64KEY);
+                               
+                               if ((search.foundJava & KEY_WOW64_64KEY) != NO_JAVA_FOUND)
+                               {
+                                       break;
+                               }
+                       }
+
+                       regSearch(keyName, searchType);
+                       break;
+
+               case USE_32_AND_64_BIT_RUNTIME:
+                       regSearch(keyName, searchType);
+
+                       if (search.foundJava != NO_JAVA_FOUND
+                               && (search.foundJava & KEY_WOW64_64KEY) == NO_JAVA_FOUND)
+                       {
+                               break;
+                       }
+
+                       if (wow64)
+                       {
+                               regSearch(keyName, searchType | KEY_WOW64_64KEY);
+                       }
+                       break;
+
+               case USE_32_BIT_RUNTIME:
+                       regSearch(keyName, searchType);
+                       break;
+                       
+               default:
+            debug("Runtime bits:\tFailed to load.\n");
+            break;
+       }
+}
+
+void regSearchJreSdk(const char* jreKeyName, const char* sdkKeyName,
+               const int jdkPreference)
+{
+       if (jdkPreference == JDK_ONLY || jdkPreference == PREFER_JDK)
+       {
+               regSearchWow(sdkKeyName, FOUND_SDK);
+               if (jdkPreference != JDK_ONLY)
+               {
+                       regSearchWow(jreKeyName, FOUND_JRE);
+               }
+       }
+       else
+       {
+               // jdkPreference == JRE_ONLY or PREFER_JRE
+               regSearchWow(jreKeyName, FOUND_JRE);
+               if (jdkPreference != JRE_ONLY)
+               {
+                       regSearchWow(sdkKeyName, FOUND_SDK);
+               }
+       }
+}
+
+BOOL findJavaHome(char* path, const int jdkPreference)
+{
+    debugAll("findJavaHome()\n");
+       regSearchJreSdk("SOFTWARE\\JavaSoft\\Java Runtime Environment",
+                                       "SOFTWARE\\JavaSoft\\Java Development Kit",
+                                       jdkPreference);
+
+    // Java 9 support
+       regSearchJreSdk("SOFTWARE\\JavaSoft\\JRE",
+                                       "SOFTWARE\\JavaSoft\\JDK",
+                                       jdkPreference);
+
+    // IBM Java 1.8
+       if (search.foundJava == NO_JAVA_FOUND)
+       {
+               regSearchJreSdk("SOFTWARE\\IBM\\Java Runtime Environment",
+                                               "SOFTWARE\\IBM\\Java Development Kit",
+                                               jdkPreference);
+       }
+       
+       // IBM Java 1.7 and earlier
+       if (search.foundJava == NO_JAVA_FOUND)
+       {
+               regSearchJreSdk("SOFTWARE\\IBM\\Java2 Runtime Environment",
+                                               "SOFTWARE\\IBM\\Java Development Kit",
+                                               jdkPreference);
+       }
+       
+       if (search.foundJava != NO_JAVA_FOUND)
+       {
+               strcpy(path, search.foundJavaHome);
+               debug("Runtime used:\t%s (%s-bit)\n", search.foundJavaVer,
+                               (search.foundJava & KEY_WOW64_64KEY) != NO_JAVA_FOUND ? "64" : "32");
+               return TRUE;    
+       }
+       
+       return FALSE;
+}
+
+BOOL checkJavaExe(char *path)
+{
+       char path2[MAX_PATH];
+       strcpy(path2, path);
+       strcat(path2, "\\bin\\java.exe");
+       
+       DWORD attr = GetFileAttributes(path2);
+       return attr != -1;
+}
+
+BOOL chooseJavaHome(char *path)
+{
+       // \83t\83H\83\8b\83_\91I\91ð\83_\83C\83A\83\8d\83O\82É\95\\8e¦\82·\82é\83\81\83b\83Z\81[\83W\82Í\83G\83\89\81[\83\81\83b\83Z\81[\83W\82ð\8eØ\97p\82·\82é 
+       createJreSearchError();
+
+       BROWSEINFO bInfo = { 0 };
+       bInfo.hwndOwner = NULL;
+       bInfo.pidlRoot  = NULL;
+       bInfo.pszDisplayName = path;
+       bInfo.lpszTitle = error.msg;
+       bInfo.ulFlags   = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
+
+       LPITEMIDLIST result = NULL;
+       while (!checkJavaExe(path))
+       {
+               result = SHBrowseForFolder(&bInfo);
+               if (result == NULL)
+               {
+                       return FALSE;
+               }
+
+               SHGetPathFromIDList(result, path);
+       }
+       return TRUE;
+}
+
+/*
+ * Extract the executable name, returns path length.
+ */
+int getExePath(char* exePath)
+{
+    if (GetModuleFileName(hModule, exePath, _MAX_PATH) == 0)
+       {
+        return -1;
+    }
+       return strrchr(exePath, '\\') - exePath;
+}
+
+/**
+ * exe\82Ö\82Ì\83t\83\8b\83p\83X(*.exe)\82ð\8eó\82¯\8eæ\82è\81A*.cfg\82É\82µ\82½\83p\83X\82ð\90\90¬\82·\82é 
+ */
+void getCfgPath(const char *exePath, char *cfgPath)
+{
+       strcpy(cfgPath, exePath);
+       strcpy(cfgPath + strlen(cfgPath) - 4, ".cfg");
+}
+
+void appendPath(char* basepath, const char* path)
+{
+       if (basepath[strlen(basepath) - 1] != '\\')
+       {
+               strcat(basepath, "\\");
+       }
+       strcat(basepath, path);
+}
+
+void appendLauncher(char* jrePath)
+{
+    if (console)
+       {
+           appendPath(jrePath, "bin\\java.exe");
+    }
+       else
+       {
+        appendPath(jrePath, "bin\\javaw.exe");
+    }
+}
+
+void appendAppClasspath(char* dst, const char* src)
+{
+       strcat(dst, src);
+       strcat(dst, ";");
+}
+
+/**
+ * \8ew\92è\82µ\82½\83f\83B\83\8c\83N\83g\83\8a\82ð\90e\82É\82³\82©\82Ì\82Ú\82Á\82Ä\8ew\92è\82µ\82½\83t\83@\83C\83\8b\81E\83t\83H\83\8b\83_\96¼\82É\88ê\92v\82·\82é
+ * \83p\83X\82ð\8c\9f\8dõ\82µ\82Ädst\82É\92Ç\8bL\82·\82é\81B\91\8dÝ\82µ\82È\82¢\8fê\8d\87\82Í\89½\82à\82µ\82È\82¢\81B
+ * @param dst \94­\8c©\82³\82ê\82½\83p\83X\82ð\92Ç\8bL\82·\82é\83o\83b\83t\83@
+ * @param dir \8dÅ\8f\89\82É\8ew\92è\82·\82é\82Ì\82ÍEXE\82Ö\82Ì\83t\83\8b\83p\83X(*.exe)\82ð\8ew\92è\82·\82é\81B
+ * @param name \8c\9f\8dõ\82·\82é\96¼\91
+ */
+void findAncestor(char* dst, const char *dir, const char* name)
+{
+       //      \90e\83t\83H\83\8b\83_\82ð\8c\9f\8dõ 
+       char parent[MAX_PATH];
+       strcpy(parent, dir);
+       char *p = parent;
+       while (*p++);
+       
+       while (p > parent)
+       {
+               if (*p == '\\' || *p == '/')
+               {
+                       if (*(p + 1))
+                       {
+                               // \8c»\8dÝ\82Ì\96\96\94ö\82Ì\83t\83H\83\8b\83_\8bæ\90Ø\82è\88È\8aO\82Å\82 \82ê\82Î\81A\82±\82±\82ð\96\96\94ö\82É\82·\82é 
+                               *(p + 1)  = 0;
+                               break;  
+                       }
+               }
+               p = CharPrev(parent, p);
+       }
+       if (strcmp(dir, parent) == 0)
+       {
+               // \95Ï\89»\82È\82µ\82È\82Ì\82Å\81A\82·\82Å\82É\8c\9f\8dõ\8dÏ\82Ý\82Ì\82Í\82¸ 
+           debug("Find End");
+               return;
+       }
+    
+       // \90e\83t\83H\83\8b\83_\82ð\97ñ\8b\93 
+       WIN32_FIND_DATA data = {0};
+       
+       char searchdir[MAX_PATH];
+    strcpy(searchdir, parent);
+    strcat(searchdir, "*.*");
+    debug("FindFirstFile:\t%s\n", searchdir);
+
+       HANDLE fh = FindFirstFile(searchdir, &data);
+       if (fh == INVALID_HANDLE_VALUE) {
+           debug("FindFirstFile:\tErr=%d\n", GetLastError());
+               return;
+       }
+       
+       for (;;)
+       {
+        //debug("cFileName:\t%s\n", data.cFileName);
+
+               if (strcasecmp(data.cFileName, name) == 0) // \91å\8f¬\95\8e\9a\82Í\8bæ\95Ê\82µ\82È\82¢ 
+               {
+                       strcat(dst, parent);
+                       strcat(dst, data.cFileName);
+                       return;
+               }
+               
+               if (!FindNextFile(fh, &data))
+               {
+                       // ERROR_NO_MORE_FILES \82Å\83G\83\89\81[\97L\96³\82Ì\94»\92è\82Í\81
+                       // \8c\8b\8bÇ\81A\83\8b\81[\83v\82ð\91Å\82¿\90Ø\82é\82¾\82¯\82È\82Ì\82Å\8fÈ\97ª\81
+                       break;
+               }
+       }
+       FindClose(fh);
+    debug("FindClose:\t%s\n", parent);
+
+       // \8dX\82É\81A\82±\82Ì\90e\82ð\8c\9f\8dõ\82·\82é 
+       findAncestor(dst, parent, name);
+}
+
+/* 
+ * Expand environment %variables%
+ */
+BOOL expandVars(char *dst, const char *src, const char *exePath, const int pathLen)
+{
+    char varName[STR] = {0};
+    char varValue[MAX_VAR_SIZE] = {0};
+
+    while (strlen(src) > 0)
+       {
+        char *start = strchr(src, '%');
+        if (start != NULL)
+               {
+            char *end = strchr(start + 1, '%');
+            if (end == NULL)
+                       {
+                return FALSE;
+            }
+            // Copy content up to %VAR%
+            strncat(dst, src, start - src);
+            // Insert value of %VAR%
+            *varName = 0;
+            strncat(varName, start + 1, end - start - 1);
+            // Remember value start for logging
+            char *currentVarValue = dst + strlen(dst);
+            
+            if (strstr(varName, "FIND_ANCESTOR:") == varName)
+                       {
+                               char *findName = varName + 14;
+                               findAncestor(dst, exePath, findName);
+            }
+                       else if (strcmp(varName, "EXEDIR") == 0)
+                       {
+                strncat(dst, exePath, pathLen);
+            }
+                       else if (strcmp(varName, "EXEFILE") == 0)
+                       {
+                strcat(dst, exePath);
+            }
+                       else if (strcmp(varName, "PWD") == 0)
+                       {
+                GetCurrentDirectory(_MAX_PATH, dst + strlen(dst));
+            }
+                       else if (strcmp(varName, "OLDPWD") == 0)
+                       {
+                strcat(dst, oldPwd);
+                       }
+            else if (strcmp(varName, "JREHOMEDIR") == 0)
+                       {
+                strcat(dst, search.foundJavaHome);
+                       }
+                       else if (strstr(varName, HKEY_STR) == varName)
+                       {
+                               regQueryValue(varName, dst + strlen(dst), BIG_STR);
+            }
+                       else if (strcmp(varName, "") == 0)
+                       {
+                strcat(dst, "%");
+            }
+                       else if (GetEnvironmentVariable(varName, varValue, MAX_VAR_SIZE) > 0)
+                       {
+                strcat(dst, varValue);
+            }
+
+            debug("Substitute:\t%s = %s\n", varName, currentVarValue);
+            src = end + 1;
+        }
+               else
+               {
+            // Copy remaining content
+            strcat(dst, src);
+            break;
+        }
+       }
+       return TRUE;
+}
+
+void appendHeapSizes(char *dst)
+{
+       MEMORYSTATUSEX statex;
+       statex.dwLength = sizeof(statex);
+       GlobalMemoryStatusEx(&statex);
+
+       appendHeapSize(dst, INITIAL_HEAP_SIZE, INITIAL_HEAP_PERCENT,
+                       statex.ullAvailPhys, "-Xms");
+       appendHeapSize(dst, MAX_HEAP_SIZE, MAX_HEAP_PERCENT,
+                       statex.ullAvailPhys, "-Xmx");
+}
+
+void appendHeapSize(char *dst, const int megabytesID, const int percentID,
+               const DWORDLONG availableMemory, const char *option)
+{
+       const int mb = 1048576;                 // 1 MB
+       const int mbLimit32 = 1024;     // Max heap size in MB on 32-bit JREs
+       const int megabytes = loadInt(megabytesID);
+       const int percent = loadInt(percentID);
+       const int availableMb = availableMemory * percent / (100 * mb); // 100% * 1 MB
+    int heapSizeMb = availableMb > megabytes ? availableMb : megabytes;
+
+       if (heapSizeMb > 0)
+       {
+               if (!(search.foundJava & KEY_WOW64_64KEY) && heapSizeMb > mbLimit32)
+               {
+                       debug("Heap limit:\tReduced %d MB heap size to 32-bit maximum %d MB\n",
+                                       heapSizeMb, mbLimit32);
+                       heapSizeMb = mbLimit32;
+               }
+
+               debug("Heap %s:\tRequested %d MB / %d%%, Available: %d MB, Heap size: %d MB\n",
+                               option, megabytes, percent, (int)(availableMemory / mb), heapSizeMb);
+               strcat(dst, option);
+               _itoa(heapSizeMb, dst + strlen(dst), 10);                               // 10 -- radix
+               strcat(dst, "m ");
+       }
+}
+
+void setJvmOptions(char *jvmOptions, const char *exePath)
+{
+       if (loadString(JVM_OPTIONS, jvmOptions))
+       {
+               strcat(jvmOptions, " ");
+       }
+
+       /*
+        * Load additional JVM options from .l4j.ini file
+        * Options are separated by spaces or CRLF
+        * # starts an inline comment
+        */
+       char iniFilePath[_MAX_PATH] = {0};
+
+       strncpy(iniFilePath, exePath, strlen(exePath) - 3);
+       strcat(iniFilePath, "l4j.ini");
+
+       long hFile;
+       if ((hFile = _open(iniFilePath, _O_RDONLY)) == -1)
+       {
+               // *.l4j.ini\82ª\82È\82¯\82ê\82Π*.ini \82Å\8e\8e\82· 
+               strncpy(iniFilePath, exePath, strlen(exePath) - 3);
+               strcat(iniFilePath, ".ini");
+               hFile = _open(iniFilePath, _O_RDONLY);
+       }
+
+       if (hFile != -1)
+       {
+               debug("Loading:\t%s\n", iniFilePath);
+               const int jvmOptLen = strlen(jvmOptions);
+               char* src = jvmOptions + jvmOptLen;
+               char* dst = src;
+               const int len = _read(hFile, src, MAX_ARGS - jvmOptLen - BIG_STR);
+               BOOL copy = TRUE;
+               int i;
+               for (i = 0; i < len; i++, src++)
+               {
+                       if (*src == '#')
+                       {
+                               copy = FALSE;
+                       }
+                       else if (*src == 13 || *src == 10)
+                       {
+                               copy = TRUE;
+                               if (dst > jvmOptions && *(dst - 1) != ' ')
+                               {
+                                       *dst++ = ' ';
+                               }
+                       }
+                       else if (copy)
+                       {
+                               *dst++ = *src;
+                       }
+               }
+               *dst = 0;
+               if (len > 0 && *(dst - 1) != ' ')
+               {
+                       strcat(jvmOptions, " ");
+               }
+               _close(hFile);
+       }       
+}
+
+BOOL createMutex()
+{
+       char mutexName[STR] = {0};
+
+       loadString(MUTEX_NAME, mutexName);
+
+       if (*mutexName)
+       {
+        debug("Create mutex:\t%s\n", mutexName);
+               SECURITY_ATTRIBUTES security;
+               security.nLength = sizeof(SECURITY_ATTRIBUTES);
+               security.bInheritHandle = TRUE;
+               security.lpSecurityDescriptor = NULL;
+               CreateMutexA(&security, FALSE, mutexName);
+
+               if (GetLastError() == ERROR_ALREADY_EXISTS)
+               {
+                       debug(ERROR_FORMAT, "Instance already exists.");
+                       return FALSE;
+               }
+       }
+       
+       return TRUE;
+}
+
+void setWorkingDirectory(const char *exePath, const int pathLen)
+{
+       char workingDir[_MAX_PATH] = {0};
+       char tmpPath[_MAX_PATH] = {0};
+
+       GetCurrentDirectory(_MAX_PATH, oldPwd);
+
+       if (loadString(CHDIR, tmpPath))
+       {
+               strncpy(workingDir, exePath, pathLen);
+               appendPath(workingDir, tmpPath);
+               _chdir(workingDir);
+               debug("Working dir:\t%s\n", workingDir);
+       }
+}
+
+BOOL cfgJreSearch(const char *exePath, int pathLen)
+{
+       char tmpPath[MAX_PATH] = { 0 };
+
+       char cfgPath[MAX_PATH] = { 0 };
+       getCfgPath(exePath, cfgPath);
+
+       GetPrivateProfileString("Settings", "JAVA_HOME", "", tmpPath, MAX_PATH, cfgPath);
+       if (strlen(tmpPath) > 0)
+       {
+               char jrePath[MAX_ARGS] = {0};
+               expandVars(jrePath, tmpPath, exePath, pathLen);
+               debug("Config JRE:\t%s\n", jrePath);
+
+               if (checkJavaExe(jrePath))
+               {
+                       strcpy(launcher.cmd, jrePath);
+               
+                       if (isLauncherPathValid(launcher.cmd))
+                       {
+                   search.foundJava = wow64 ? FOUND_BUNDLED | KEY_WOW64_64KEY : FOUND_BUNDLED;
+                               strcpy(search.foundJavaHome, launcher.cmd);
+                               return TRUE;
+                       }
+               }
+       }
+
+       return FALSE;
+}
+
+BOOL bundledJreSearch(const char *exePath, const int pathLen)
+{
+    debugAll("bundledJreSearch()\n");
+       char tmpPath[_MAX_PATH] = {0};
+    BOOL is64BitJre = loadBool(BUNDLED_JRE_64_BIT);
+
+    if (!wow64 && is64BitJre)
+    {
+        debug("Bundled JRE:\tCannot use 64-bit runtime on 32-bit OS.\n");
+        return FALSE;
+    }
+    
+       if (loadString(JRE_PATH, tmpPath))
+       {
+               char jrePath[MAX_ARGS] = {0};
+               expandVars(jrePath, tmpPath, exePath, pathLen);
+               debug("Bundled JRE:\t%s\n", jrePath);
+
+               if (jrePath[0] == '\\' || jrePath[1] == ':')
+               {
+                       // Absolute
+                       strcpy(launcher.cmd, jrePath);
+               }
+               else
+               {
+                       // Relative
+                       strncpy(launcher.cmd, exePath, pathLen);
+                       appendPath(launcher.cmd, jrePath);
+               }
+
+               if (isLauncherPathValid(launcher.cmd))
+               {
+            search.foundJava = is64BitJre ? FOUND_BUNDLED | KEY_WOW64_64KEY : FOUND_BUNDLED;
+                       strcpy(search.foundJavaHome, launcher.cmd);
+                       return TRUE;
+               }
+    }
+
+    return FALSE;
+}
+
+BOOL installedJreSearch()
+{
+    debugAll("installedJreSearch()\n");
+       return *search.javaMinVer && findJavaHome(launcher.cmd, loadInt(JDK_PREFERENCE));
+}
+
+void createJreSearchError()
+{
+       if (*search.javaMinVer)
+       {
+               loadString(JRE_VERSION_ERR, error.msg);
+               strcat(error.msg, " ");
+               strcat(error.msg, search.originalJavaMinVer);
+       
+               if (*search.javaMaxVer)
+               {
+                       strcat(error.msg, " - ");
+                       strcat(error.msg, search.originalJavaMaxVer);
+               }
+       
+               if (search.runtimeBits == USE_64_BIT_RUNTIME
+                               || search.runtimeBits == USE_32_BIT_RUNTIME)
+               {
+                       strcat(error.msg, " (");
+                       strcat(error.msg, search.runtimeBits == USE_64_BIT_RUNTIME ? "64" : "32");
+                       strcat(error.msg, "-bit)");
+               }                       
+               
+               if (search.corruptedJreFound)
+               {
+                       char launcherErrMsg[BIG_STR] = {0};
+       
+                       if (loadString(LAUNCHER_ERR, launcherErrMsg))
+                       {
+                               strcat(error.msg, "\n");
+                               strcat(error.msg, launcherErrMsg);
+                       }
+               }
+       
+               loadString(DOWNLOAD_URL, error.url);
+       }
+       else
+       {
+               loadString(BUNDLED_JRE_ERR, error.msg);
+       }
+}
+
+BOOL jreSearch(const char *exePath, const int pathLen)
+{
+    debugAll("jreSearch()\n");
+       BOOL result = TRUE;
+
+       // *.cfg\82É\91O\89ñ\91I\91ð\82ÌJAVA_HOME\82ª\8bL\98^\82³\82ê\82Ä\82¢\82ê\82Î\81A\82»\82ê\82ð\97D\90æ\82·\82é
+       // \8bL\98^\82³\82ê\82Ä\82¢\82È\82¢\82©\81AJAVA_HOME\82Æ\82µ\82Ä\91Ã\93\96\82Å\82È\82¯\82ê\82Î\83o\83\93\83h\83\8b\82Ü\82½\82Í\83\8c\83W\83X\83g\83\8a\82Ì\8c\9f\8dõ\82ð\8ds\82¤ 
+       if (!cfgJreSearch(exePath, pathLen))
+       {
+               search.bundledJreAsFallback = loadBool(BUNDLED_JRE_AS_FALLBACK);
+               loadString(JAVA_MIN_VER, search.originalJavaMinVer);
+               formatJavaVersion(search.javaMinVer, search.originalJavaMinVer);
+               debug("Java min ver:\t%s\n", search.javaMinVer);
+               loadString(JAVA_MAX_VER, search.originalJavaMaxVer);
+           formatJavaVersion(search.javaMaxVer, search.originalJavaMaxVer);
+           debug("Java max ver:\t%s\n", search.javaMaxVer);
+       
+               if (search.bundledJreAsFallback)
+               {
+                       if (!installedJreSearch())
+                       {
+                               result = bundledJreSearch(exePath, pathLen);
+                       }
+               }
+               else
+               {
+                       if (!bundledJreSearch(exePath, pathLen))
+                       {
+                               result = installedJreSearch();
+                       }
+               }
+               
+               if (!result)
+               {
+                       // \83o\83\93\83h\83\8b\82Ì\8c\9f\8dõ\82Æ\83\8c\83W\83X\83g\83\8a\82Ì\8c\9f\8dõ\82à\8e¸\94s\82µ\82½\8fê\8d\87
+                       // \83\86\81[\83U\81[\82ÉJAVA_HOME\82Ì\91I\91ð\82ð\8b\81\82ß\82é 
+                       char jrePath[MAX_PATH] = { 0 };
+                       if (chooseJavaHome(jrePath))
+                       {
+                               // JAVA_HOME\82ð\91I\91ð\82µ\82½\8fê\8d\87 
+                       search.foundJava = wow64 ? FOUND_BUNDLED | KEY_WOW64_64KEY : FOUND_BUNDLED;
+                               strcpy(launcher.cmd, jrePath);
+                               strcpy(search.foundJavaHome, launcher.cmd);
+                               
+                               // \90¬\8c÷\82Æ\82Ý\82È\82· 
+                               result = TRUE;
+                       }
+                       else
+                       {
+                               // \83G\83\89\81[\95\\8e¦\82Ì\8f\80\94õ 
+                               createJreSearchError();
+                       }
+               }
+       }
+
+       return result;
+}
+
+/*
+ * Append a path to the Path environment variable
+ */
+BOOL appendToPathVar(const char* path)
+{
+       char chBuf[MAX_VAR_SIZE] = {0};
+       const int pathSize = GetEnvironmentVariable("Path", chBuf, MAX_VAR_SIZE);
+
+       if (MAX_VAR_SIZE - pathSize - 1 < strlen(path))
+       {
+               return FALSE;
+       }
+
+       strcat(chBuf, ";");
+       strcat(chBuf, path);
+       return SetEnvironmentVariable("Path", chBuf);
+}
+
+BOOL appendJreBinToPathVar()
+{
+       // Append a path to the Path environment variable
+       char jreBinPath[_MAX_PATH] = {0};
+       strcpy(jreBinPath, launcher.cmd);
+       strcat(jreBinPath, "\\bin");
+
+       if (!appendToPathVar(jreBinPath))
+       {
+               debug(ERROR_FORMAT, "appendToPathVar failed.");
+               return FALSE;
+       }
+       
+       return TRUE;
+}
+
+void setEnvironmentVariables(const char *exePath, const int pathLen)
+{
+       char tmp[MAX_ARGS] = {0};
+
+       // \83\8a\83\\81[\83X\82É\96\84\82ß\8d\9e\82Ü\82ê\82Ä\82¢\82é\8aÂ\8b«\95Ï\90\94\82Ì\93W\8a
+       char envVars[MAX_VAR_SIZE] = {0};
+       loadString(ENV_VARIABLES, envVars);
+       char *var = strtok(envVars, "\t");
+
+       while (var != NULL)
+       {
+               char *varValue = strchr(var, '=');
+               *varValue++ = 0;
+               *tmp = 0;
+               expandVars(tmp, varValue, exePath, pathLen);
+               debug("Set var:\t%s = %s\n", var, tmp);
+               SetEnvironmentVariable(var, tmp);
+               var = strtok(NULL, "\t"); 
+       }
+       
+       // *.cfg\83t\83@\83C\83\8b\82©\82ç\8aÂ\8b«\95Ï\90\94\82Ì\93Ç\82Ý\8eæ\82è 
+       char cfgPath[MAX_PATH];
+       getCfgPath(exePath, cfgPath);
+       debug("cfgPath: %s\n", cfgPath);
+       
+       char envbuf[MAX_VAR_SIZE] = { 0 }; // 32kbytes
+       char envValue[MAX_ARGS] = { 0 };
+       GetPrivateProfileString("Environments", NULL, "", envbuf, sizeof(envbuf), cfgPath);
+
+       char *pEnv = envbuf;
+       while (*pEnv)
+       {
+               GetPrivateProfileString("Environments", pEnv, "", envValue, sizeof(envValue), cfgPath);
+               
+               *tmp = 0;
+               expandVars(tmp, envValue, exePath, pathLen);
+               debug("Set var:\t%s = %s\n", pEnv, tmp);
+               SetEnvironmentVariable(pEnv, tmp);
+
+               while (*pEnv++);
+       }
+}
+
+void setMainClassAndClassPath(const char *exePath, const int pathLen)
+{
+       char classPath[MAX_ARGS] = {0};
+       char expandedClassPath[MAX_ARGS] = {0};
+       char jar[_MAX_PATH] = {0};
+       char fullFileName[_MAX_PATH] = {0};
+       const BOOL wrapper = loadBool(WRAPPER);
+       loadString(JAR, jar);
+
+       if (loadString(MAIN_CLASS, launcher.mainClass))
+       {
+        debug("Main class:\t%s\n", launcher.mainClass);
+
+               if (!loadString(CLASSPATH, classPath))
+               {
+                       debug("Info:\t\tClasspath not defined.\n");
+               }
+               
+               expandVars(expandedClassPath, classPath, exePath, pathLen);
+               strcat(launcher.args, "-classpath \"");
+
+               if (wrapper)
+               {
+                       appendAppClasspath(launcher.args, exePath);
+               }
+               else if (*jar)
+               {
+                       appendAppClasspath(launcher.args, jar);
+               }
+
+               // Deal with wildcards or >> strcat(launcherArgs, exp); <<
+               char* cp = strtok(expandedClassPath, ";");
+
+               while(cp != NULL)
+               {
+                       debug("Add classpath:\t%s\n", cp);
+                       if (strpbrk(cp, "*?") != NULL)
+                       {
+                               char* lastBackslash = strrchr(cp, '\\');
+                               int pathLen = lastBackslash != NULL ? lastBackslash - cp + 1 : 0;
+                               *fullFileName = 0;
+                               strncpy(fullFileName, cp, pathLen);
+                               char* fileName = fullFileName + pathLen;
+                               *fileName = 0;
+                               struct _finddata_t c_file;
+                               long hFile;
+
+                               if ((hFile = _findfirst(cp, &c_file)) != -1L)
+                               {
+                                       do
+                                       {
+                                               strcpy(fileName, c_file.name);
+                                               appendAppClasspath(launcher.args, fullFileName);
+                                               debug("      \"      :\t%s\n", fullFileName);
+                                       } while (_findnext(hFile, &c_file) == 0);
+                               }
+
+                               _findclose(hFile);
+                       }
+                       else
+                       {
+                               appendAppClasspath(launcher.args, cp);
+                       }
+                       cp = strtok(NULL, ";");
+               }
+
+               *(launcher.args + strlen(launcher.args) - 1) = 0;
+               strcat(launcher.args, "\" ");
+               strcat(launcher.args, launcher.mainClass);
+       }
+       else if (wrapper)
+       {
+               strcat(launcher.args, "-jar \"");
+               strcat(launcher.args, exePath);
+               strcat(launcher.args, "\"");
+    }
+       else
+       {
+               strcat(launcher.args, "-jar \"");
+        strncat(launcher.args, exePath, pathLen);
+        appendPath(launcher.args, jar);
+               strcat(launcher.args, "\"");
+    }
+}
+
+void setCommandLineArgs(const char *lpCmdLine,
+               const char *exePath, const int pathLen)
+{
+       char tmp[MAX_ARGS] = {0};
+
+       // Constant command line arguments
+       if (loadString(CMD_LINE, tmp))
+       {
+               char tmp2[MAX_ARGS] = {0};
+               expandVars(tmp2, tmp, exePath, pathLen);
+               debug("constant commandline args: %s\r\n", tmp2);
+
+               strcat(launcher.args, " ");
+               strcat(launcher.args, tmp2);
+       }
+
+       // Command line arguments
+       if (*lpCmdLine)
+       {
+               strcpy(tmp, lpCmdLine);
+               char* dst;
+               while ((dst = strstr(tmp, "--l4j-")) != NULL)
+               {
+                       char* src = strchr(dst, ' ');
+                       if (src == NULL || *(src + 1) == 0)
+                       {
+                               *dst = 0;
+                       }
+                       else
+                       {
+                               strcpy(dst, src + 1);
+                       }
+               }
+               if (*tmp)
+               {
+                       strcat(launcher.args, " ");
+                       strcat(launcher.args, tmp);
+               }
+       }
+}
+
+int prepare(const char *lpCmdLine)
+{
+       if (!initGlobals())
+       {
+               return FALSE;
+       }
+
+       // Get executable path
+       char exePath[_MAX_PATH] = {0};
+       int pathLen = getExePath(exePath);
+
+       if (pathLen == -1)
+       {
+               return FALSE;
+       }
+
+       if (!initializeLogging(lpCmdLine, exePath, pathLen))
+       {
+               return FALSE;
+       }
+
+    setWow64Flag();
+
+       // Set default error message, title and optional support web site url.
+       loadString(ERR_TITLE, error.title);
+       loadString(SUPPORT_URL, error.url);
+
+       if (!loadString(STARTUP_ERR, error.msg))
+       {
+               debug(ERROR_FORMAT, "Startup error message not defined.");
+               return FALSE;                   
+       }
+
+       // Single instance
+       if (!createMutex())
+       {
+               return ERROR_ALREADY_EXISTS;
+       }
+
+       setWorkingDirectory(exePath, pathLen);
+    
+       if (!jreSearch(exePath, pathLen))
+    {
+               return FALSE;
+       }
+
+       if (!appendJreBinToPathVar())
+       {
+               return FALSE;
+       }
+
+       setEnvironmentVariables(exePath, pathLen);
+       processPriority = loadInt(PRIORITY_CLASS);
+       appendLauncher(launcher.cmd);
+       appendHeapSizes(launcher.args);
+
+       char jvmOptions[MAX_ARGS] = {0};
+       setJvmOptions(jvmOptions, exePath);
+       expandVars(launcher.args, jvmOptions, exePath, pathLen);
+       setMainClassAndClassPath(exePath, pathLen);
+       setCommandLineArgs(lpCmdLine, exePath, pathLen);
+
+       debug("Launcher:\t%s\n", launcher.cmd);
+       debug("Launcher args:\t%s\n", launcher.args);
+       debug("Args length:\t%d/32768 chars\n", strlen(launcher.args));
+       return TRUE;
+}
+
+void closeProcessHandles()
+{
+       CloseHandle(processInformation.hThread);
+       CloseHandle(processInformation.hProcess);
+}
+
+BOOL execute(const BOOL wait, DWORD *dwExitCode)
+{
+       STARTUPINFO si;
+
+    memset(&processInformation, 0, sizeof(processInformation));
+    memset(&si, 0, sizeof(si));
+    si.cb = sizeof(si);
+
+       char cmdline[MAX_ARGS] = {0};
+    strcpy(cmdline, "\"");
+       strcat(cmdline, launcher.cmd);
+       strcat(cmdline, "\" ");
+       strcat(cmdline, launcher.args);
+
+       if (CreateProcess(NULL, cmdline, NULL, NULL,
+                       TRUE, processPriority, NULL, NULL, &si, &processInformation))
+       {
+               // \83v\83\8d\83Z\83X\82ª\8bN\93®\82µ\82Ä\82·\82®\82É\83G\83\89\81[\82ª\97\8e\82¿\82é\82©\82Ç\82¤\82©\82ð\8c©\8bÉ\82ß\82é 
+               WaitForInputIdle(processInformation.hProcess, 10000); // \83\81\83b\83Z\81[\83W\83\8b\81[\83v\82Ì\83A\83C\83h\83\8b\82ð\91Ò\82 
+               WaitForSingleObject(processInformation.hProcess, 3000); // 3\95b\82Ü\82 
+               
+               // \8c»\8e\9e\93_\82Ì\8fI\97¹\83R\81[\83h\82ð\93¾\82é 
+               GetExitCodeProcess(processInformation.hProcess, dwExitCode);
+               debug("Java PreExitCode: %ld\n", *dwExitCode);
+               if (*dwExitCode == STILL_ACTIVE)
+               {
+                       // \82Ü\82¾\8fI\97¹\82µ\82Ä\82¢\82È\82¯\82ê\82Î0\82ð\89¼\90Ý\92è\82·\82é 
+                       *dwExitCode = 0;
+               }
+               
+               if (*dwExitCode == 0)
+               {
+                       // \8bN\93®\92¼\8cã\82É\83G\83\89\81[\82ª\94­\90\82µ\82Ä\82¢\82é\82Ì\82Å\82È\82¯\82ê\82Î
+                       // JAVA_HOME\82Í\90³\82µ\82©\82Á\82½\82à\82Ì\82Æ\82Ý\82È\82µ\81
+                       // \83o\83\93\83h\83\8b\82Ü\82½\82Í\83\8c\83W\83X\83g\83\8a\82©\82ç\82Ì\8c\9f\8dõ\82É\90¬\8c÷\82µ\82½JAVA_HOME\81A
+                       // \82Ü\82½\82Í\83\86\81[\83U\81[\82ª\91I\91ð\82µ\82½JAVA_HOME\82ð\81A*.cfg\82É\95Û\91\82·\82é
+                       // (\89¼\82É\8f\91\82«\8d\9e\82Ý\8bÖ\8e~\93\99\82Å\8f\91\82«\8d\9e\82ß\82È\82­\82Ä\82à\93Á\92i\96â\91è\82Í\82È\82¢) 
+                       char exePath[MAX_PATH] = { 0 };
+                       char cfgPath[MAX_PATH] = { 0 };
+                       getExePath(exePath);
+                       getCfgPath(exePath, cfgPath);
+                       int saveJavaHome = GetPrivateProfileInt("Settings", "SaveJavaHome", 1, cfgPath);
+                       if (saveJavaHome)
+                       {
+                               // JAVA_HOME\82Ì\95Û\91\83t\83\89\83O\82ª0\82Å\82È\82¯\82ê\82Î\8eg\97p\82µ\82½JAVA_HOME\82ð\8bL\98^\82·\82é 
+                               WritePrivateProfileString("Settings", "JAVA_HOME", search.foundJavaHome, cfgPath);
+                       }
+               }
+
+               if (wait)
+               {
+                       // \8fI\97¹\91Ò\82¿\82ª\8ew\92è\82³\82ê\82Ä\82¢\82ê\82Î\8eq\83v\83\8d\83Z\83X\8fI\97¹\82ð\91Ò\8b@\82·\82é 
+                       WaitForSingleObject(processInformation.hProcess, INFINITE);
+                       GetExitCodeProcess(processInformation.hProcess, dwExitCode);
+               }
+               
+               // \91Ò\8b@\82·\82é\95K\97v\82ª\82È\82­\82È\82Á\82½\82Ì\82È\82ç\83n\83\93\83h\83\8b\82Í\94j\8aü\82µ\82Ä\82¨\82­ 
+               closeProcessHandles();
+               
+               return TRUE;
+       }
+
+       *dwExitCode = -1;
+       return FALSE;
+}
+
+const char* getJavaHome()
+{
+       return search.foundJavaHome;
+}
+
+const char* getMainClass()
+{
+       return launcher.mainClass;      
+}
+
+const char* getLauncherArgs()
+{
+    return launcher.args;    
+}
+
diff --git a/src/Launch4JStub/head_src/head.h b/src/Launch4JStub/head_src/head.h
new file mode 100644 (file)
index 0000000..348477f
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+       Launch4j (http://launch4j.sourceforge.net/)
+       Cross-platform Java application wrapper for creating Windows native executables.
+
+       Copyright (c) 2004, 2015 Grzegorz Kowal,
+                                                        Ian Roberts (jdk preference patch)
+
+       Permission is hereby granted, free of charge, to any person obtaining a copy
+       of this software and associated documentation files (the "Software"), to deal
+       in the Software without restriction, including without limitation the rights
+       to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+       copies of the Software, and to permit persons to whom the Software is
+       furnished to do so, subject to the following conditions:
+
+       The above copyright notice and this permission notice shall be included in
+       all copies or substantial portions of the Software.
+
+       Except as contained in this notice, the name(s) of the above copyright holders
+       shall not be used in advertising or otherwise to promote the sale, use or other
+       dealings in this Software without prior written authorization.
+
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+       IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+       FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+       AUTHORS OR 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.
+*/
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif // _WIN32_WINNT
+
+#ifndef _LAUNCH4J_HEAD__INCLUDED_
+#define _LAUNCH4J_HEAD__INCLUDED_
+
+#define WIN32_LEAN_AND_MEAN            // VC - Exclude rarely-used stuff from Windows headers
+
+// Windows Header Files:
+#include <windows.h>
+#include <shlobj.h>
+
+// C RunTime Header Files
+#include <stdlib.h>
+#include <malloc.h>
+#include <memory.h>
+#include <tchar.h>
+#include <shellapi.h>
+#include <direct.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <io.h>
+#include <process.h>
+#include <locale.h>
+
+#define LAUNCH4j "Launch4j"
+#define VERSION "3.12"
+
+#define JRE_VER_MAX_DIGITS_PER_PART 3
+
+#define NO_JAVA_FOUND 0
+#define FOUND_JRE 1
+#define FOUND_SDK 2
+#define FOUND_BUNDLED 4
+
+#define JRE_ONLY 0
+#define PREFER_JRE 1
+#define PREFER_JDK 2
+#define JDK_ONLY 3
+
+#define USE_64_BIT_RUNTIME 1
+#define USE_64_AND_32_BIT_RUNTIME 2
+#define USE_32_AND_64_BIT_RUNTIME 3
+#define USE_32_BIT_RUNTIME 4
+#define INIT_RUNTIME_BITS 9
+
+#define KEY_WOW64_64KEY 0x0100
+
+#define HKEY_STR "HKEY"
+#define HKEY_CLASSES_ROOT_STR "HKEY_CLASSES_ROOT"
+#define HKEY_CURRENT_USER_STR "HKEY_CURRENT_USER"
+#define HKEY_LOCAL_MACHINE_STR "HKEY_LOCAL_MACHINE"
+#define HKEY_USERS_STR "HKEY_USERS"
+#define HKEY_CURRENT_CONFIG_STR "HKEY_CURRENT_CONFIG"
+
+#define STR 128
+#define BIG_STR 1024
+#define MAX_VAR_SIZE 32767
+#define MAX_ARGS 32768
+
+#define TRUE_STR "true"
+#define FALSE_STR "false"
+
+#define ERROR_FORMAT "Error:\t\t%s\n"
+#define debug(args...) if (hLog != NULL) fprintf(hLog, ## args);
+#define debugAll(args...) if (debugAll && hLog != NULL) fprintf(hLog, ## args);
+
+typedef void (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
+
+BOOL initGlobals();
+FILE* openLogFile(const char* exePath, const int pathLen);
+void closeLogFile();
+BOOL initializeLogging(const char *lpCmdLine, const char* exePath, const int pathLen);
+void msgBox(const char* text);
+void signalError();
+BOOL loadString(const int resID, char* buffer);
+BOOL loadBool(const int resID);
+int loadInt(const int resID);
+BOOL regQueryValue(const char* regPath, unsigned char* buffer,
+               unsigned long bufferLength);
+void formatJavaVersion(char* version, const char* originalVersion);
+void regSearch(const char* keyName, const int searchType);
+BOOL isJavaHomeValid(const char* keyName, const int searchType);
+BOOL isLauncherPathValid(const char* path);
+void regSearchWow(const char* keyName, const int searchType);
+void regSearchJreSdk(const char* jreKeyName, const char* sdkKeyName,
+               const int jdkPreference);
+BOOL findJavaHome(char* path, const int jdkPreference);
+int getExePath(char* exePath);
+void appendPath(char* basepath, const char* path);
+void appendLauncher(char* jrePath);
+void appendAppClasspath(char* dst, const char* src);
+BOOL expandVars(char *dst, const char *src, const char *exePath, const int pathLen);
+void appendHeapSizes(char *dst);
+void appendHeapSize(char *dst, const int megabytesID, const int percentID,
+               const DWORDLONG availableMemory, const char *option);
+void setJvmOptions(char *jvmOptions, const char *exePath);
+BOOL createMutex();
+void setWorkingDirectory(const char *exePath, const int pathLen);
+BOOL bundledJreSearch(const char *exePath, const int pathLen);
+BOOL installedJreSearch();
+void createJreSearchError();
+BOOL jreSearch(const char *exePath, const int pathLen);
+BOOL appendToPathVar(const char* path);
+BOOL appendJreBinToPathVar();
+void setEnvironmentVariables(const char *exePath, const int pathLen);
+void setMainClassAndClassPath(const char *exePath, const int pathLen);
+void setCommandLineArgs(const char *lpCmdLine, const char *exePath, const int pathLen);
+int prepare(const char *lpCmdLine);
+void closeProcessHandles();
+BOOL execute(const BOOL wait, DWORD *dwExitCode);
+const char* getJavaHome();
+const char* getMainClass();
+const char* getLauncherArgs();
+
+#endif // _LAUNCH4J_HEAD__INCLUDED_
diff --git a/src/Launch4JStub/head_src/jniconsolehead_BETA/.gitignore b/src/Launch4JStub/head_src/jniconsolehead_BETA/.gitignore
new file mode 100644 (file)
index 0000000..1c252a6
--- /dev/null
@@ -0,0 +1,2 @@
+/jniconsolehead.exe
+/jniconsolehead.layout
diff --git a/src/Launch4JStub/head_src/jniconsolehead_BETA/Makefile.win b/src/Launch4JStub/head_src/jniconsolehead_BETA/Makefile.win
new file mode 100644 (file)
index 0000000..0cc36ba
--- /dev/null
@@ -0,0 +1,34 @@
+# Project: jniconsolehead
+# Makefile created by Dev-C++ 5.7.1
+
+CPP      = g++.exe
+CC       = gcc.exe
+WINDRES  = windres.exe
+OBJ      = ../../head_jni_BETA/jniconsolehead.o ../../head_jni_BETA/head.o ../../head_jni_BETA/jnihead.o
+LINKOBJ  = ../../head_jni_BETA/jniconsolehead.o ../../head_jni_BETA/head.o ../../head_jni_BETA/jnihead.o
+LIBS     = -L"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/lib" -L"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/mingw32/lib" -static-libstdc++ -static-libgcc -n -s
+INCS     = -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/mingw32/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/lib/gcc/mingw32/4.8.1/include" -I"C:/Program Files (x86)/Java/jdk 1.4/include" -I"C:/Program Files (x86)/Java/jdk 1.4/include/win32"
+CXXINCS  = -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/mingw32/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/lib/gcc/mingw32/4.8.1/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/lib/gcc/mingw32/4.8.1/include/c++" -I"C:/Program Files (x86)/Java/jdk 1.4/include" -I"C:/Program Files (x86)/Java/jdk 1.4/include/win32"
+BIN      = jniconsolehead.exe
+CXXFLAGS = $(CXXINCS) -Os
+CFLAGS   = $(INCS) -Os
+RM       = rm.exe -f
+
+.PHONY: all all-before all-after clean clean-custom
+
+all: all-before $(BIN) all-after
+
+clean: clean-custom
+       ${RM} $(OBJ) $(BIN)
+
+$(BIN): $(OBJ)
+       $(CC) $(LINKOBJ) -o $(BIN) $(LIBS)
+
+../../head_jni_BETA/jniconsolehead.o: jniconsolehead.c
+       $(CC) -c jniconsolehead.c -o ../../head_jni_BETA/jniconsolehead.o $(CFLAGS)
+
+../../head_jni_BETA/head.o: ../head.c
+       $(CC) -c ../head.c -o ../../head_jni_BETA/head.o $(CFLAGS)
+
+../../head_jni_BETA/jnihead.o: ../jnihead.c
+       $(CC) -c ../jnihead.c -o ../../head_jni_BETA/jnihead.o $(CFLAGS)
diff --git a/src/Launch4JStub/head_src/jniconsolehead_BETA/jniconsolehead.c b/src/Launch4JStub/head_src/jniconsolehead_BETA/jniconsolehead.c
new file mode 100644 (file)
index 0000000..0ee6f1c
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+       Launch4j (http://launch4j.sourceforge.net/)
+       Cross-platform Java application wrapper for creating Windows native executables.
+
+       Copyright (c) 2004, 2007 Grzegorz Kowal
+
+       Permission is hereby granted, free of charge, to any person obtaining a copy
+       of this software and associated documentation files (the "Software"), to deal
+       in the Software without restriction, including without limitation the rights
+       to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+       copies of the Software, and to permit persons to whom the Software is
+       furnished to do so, subject to the following conditions:
+
+       The above copyright notice and this permission notice shall be included in
+       all copies or substantial portions of the Software.
+
+       Except as contained in this notice, the name(s) of the above copyright holders
+       shall not be used in advertising or otherwise to promote the sale, use or other
+       dealings in this Software without prior written authorization.
+
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+       IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+       FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+       AUTHORS OR 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.
+*/
+
+#include "../resource.h"
+#include "../head.h"
+#include "../jnihead.h"
+
+extern FILE* hLog;
+
+BOOL restartOnCrash = FALSE;
+
+int main(int argc, char* argv[])
+{
+    setConsoleFlag();
+       LPTSTR cmdLine = GetCommandLine();
+
+       if (*cmdLine == '"')
+       {
+               if (*(cmdLine = strchr(cmdLine + 1, '"') + 1))
+               {
+                       cmdLine++;
+               }
+       }
+       else if ((cmdLine = strchr(cmdLine, ' ')) != NULL)
+       {
+               cmdLine++;
+       }
+       else
+       {
+               cmdLine = "";
+       }
+
+       int result = prepare(cmdLine);
+
+       if (result == ERROR_ALREADY_EXISTS)
+       {
+               char errMsg[BIG_STR] = {0};
+               loadString(INSTANCE_ALREADY_EXISTS_MSG, errMsg);
+               msgBox(errMsg);
+               closeLogFile();
+               return 2;
+       }
+
+       if (result != TRUE)
+       {
+               signalError();
+               return 1;
+       }
+
+       restartOnCrash = loadBool(RESTART_ON_CRASH);
+       DWORD dwExitCode;
+
+       do
+       {
+               dwExitCode = 0;
+               saveJvmOptions(getJavaHome(), getMainClass(), getLauncherArgs());
+
+               if (!executeVm(&dwExitCode))
+               {
+                       signalError();
+                       break;
+               }
+
+               if (restartOnCrash && dwExitCode != 0)
+               {
+                       debug("Exit code:\t%d, restarting the application!\n", dwExitCode);
+               }
+       } while (restartOnCrash && dwExitCode != 0);
+
+       debug("Exit code:\t%d\n", dwExitCode);
+       closeLogFile();
+       return (int) dwExitCode;
+}
diff --git a/src/Launch4JStub/head_src/jniconsolehead_BETA/jniconsolehead.dev b/src/Launch4JStub/head_src/jniconsolehead_BETA/jniconsolehead.dev
new file mode 100644 (file)
index 0000000..07a00b3
--- /dev/null
@@ -0,0 +1,112 @@
+[Project]
+FileName=jniconsolehead.dev
+Name=jniconsolehead
+UnitCount=6
+Type=1
+Ver=2
+ObjFiles=
+Includes="C:\Program Files (x86)\Java\jdk 1.4\include";"C:\Program Files (x86)\Java\jdk 1.4\include\win32"
+Libs=
+PrivateResource=
+ResourceIncludes=
+MakeIncludes=
+Compiler=
+CppCompiler=
+Linker=-n_@@_
+IsCpp=0
+Icon=
+ExeOutput=
+ObjectOutput=..\..\head_jni_BETA
+OverrideOutput=0
+OverrideOutputName=jniconsolehead.exe
+HostApplication=
+Folders=
+CommandLine=
+UseCustomMakefile=0
+CustomMakefile=Makefile.win
+IncludeVersionInfo=0
+SupportXPThemes=0
+CompilerSet=0
+CompilerSettings=000000d000000000000001000
+LogOutput=
+LogOutputEnabled=0
+
+[Unit1]
+FileName=jniconsolehead.c
+CompileCpp=0
+Folder=jniconsolehead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[VersionInfo]
+Major=0
+Minor=1
+Release=1
+Build=1
+LanguageID=1033
+CharsetID=1252
+CompanyName=
+FileVersion=0.1.1.1
+FileDescription=Developed using the Dev-C++ IDE
+InternalName=
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=
+ProductName=
+ProductVersion=
+AutoIncBuildNr=0
+SyncProduct=0
+
+[Unit2]
+FileName=..\resource.h
+CompileCpp=0
+Folder=jniconsolehead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit3]
+FileName=..\head.c
+CompileCpp=0
+Folder=jniconsolehead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit4]
+FileName=..\head.h
+CompileCpp=0
+Folder=jniconsolehead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit5]
+FileName=..\jnihead.h
+Folder=jniconsolehead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+CompileCpp=0
+
+[Unit6]
+FileName=..\jnihead.c
+CompileCpp=0
+Folder=jniconsolehead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
diff --git a/src/Launch4JStub/head_src/jniguihead_BETA/.gitignore b/src/Launch4JStub/head_src/jniguihead_BETA/.gitignore
new file mode 100644 (file)
index 0000000..033e91b
--- /dev/null
@@ -0,0 +1,2 @@
+/jniguihead.exe
+/jniguihead.layout
diff --git a/src/Launch4JStub/head_src/jniguihead_BETA/Makefile.win b/src/Launch4JStub/head_src/jniguihead_BETA/Makefile.win
new file mode 100644 (file)
index 0000000..6ab81ab
--- /dev/null
@@ -0,0 +1,34 @@
+# Project: jniguihead
+# Makefile created by Dev-C++ 5.7.1
+
+CPP      = g++.exe
+CC       = gcc.exe
+WINDRES  = windres.exe
+OBJ      = ../../head_jni_BETA/jniguihead.o ../../head_jni_BETA/head.o ../../head_jni_BETA/jnihead.o
+LINKOBJ  = ../../head_jni_BETA/jniguihead.o ../../head_jni_BETA/head.o ../../head_jni_BETA/jnihead.o
+LIBS     = -L"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/lib" -L"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/mingw32/lib" -static-libstdc++ -static-libgcc -mwindows -n -s
+INCS     = -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/mingw32/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/lib/gcc/mingw32/4.8.1/include" -I"C:/Program Files (x86)/Java/jdk 1.4/include" -I"C:/Program Files (x86)/Java/jdk 1.4/include/win32"
+CXXINCS  = -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/mingw32/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/lib/gcc/mingw32/4.8.1/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/lib/gcc/mingw32/4.8.1/include/c++" -I"C:/Program Files (x86)/Java/jdk 1.4/include" -I"C:/Program Files (x86)/Java/jdk 1.4/include/win32"
+BIN      = jniguihead.exe
+CXXFLAGS = $(CXXINCS) -Os
+CFLAGS   = $(INCS) -Os
+RM       = rm.exe -f
+
+.PHONY: all all-before all-after clean clean-custom
+
+all: all-before $(BIN) all-after
+
+clean: clean-custom
+       ${RM} $(OBJ) $(BIN)
+
+$(BIN): $(OBJ)
+       $(CC) $(LINKOBJ) -o $(BIN) $(LIBS)
+
+../../head_jni_BETA/jniguihead.o: jniguihead.c
+       $(CC) -c jniguihead.c -o ../../head_jni_BETA/jniguihead.o $(CFLAGS)
+
+../../head_jni_BETA/head.o: ../head.c
+       $(CC) -c ../head.c -o ../../head_jni_BETA/head.o $(CFLAGS)
+
+../../head_jni_BETA/jnihead.o: ../jnihead.c
+       $(CC) -c ../jnihead.c -o ../../head_jni_BETA/jnihead.o $(CFLAGS)
diff --git a/src/Launch4JStub/head_src/jniguihead_BETA/jniguihead.c b/src/Launch4JStub/head_src/jniguihead_BETA/jniguihead.c
new file mode 100644 (file)
index 0000000..eda14c5
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+       Launch4j (http://launch4j.sourceforge.net/)
+       Cross-platform Java application wrapper for creating Windows native executables.
+
+       Copyright (c) 2004, 2015 Grzegorz Kowal
+                                                        Sylvain Mina (single instance patch)
+
+       Permission is hereby granted, free of charge, to any person obtaining a copy
+       of this software and associated documentation files (the "Software"), to deal
+       in the Software without restriction, including without limitation the rights
+       to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+       copies of the Software, and to permit persons to whom the Software is
+       furnished to do so, subject to the following conditions:
+
+       The above copyright notice and this permission notice shall be included in
+       all copies or substantial portions of the Software.
+
+       Except as contained in this notice, the name(s) of the above copyright holders
+       shall not be used in advertising or otherwise to promote the sale, use or other
+       dealings in this Software without prior written authorization.
+
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+       IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+       FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+       AUTHORS OR 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.
+*/
+
+#include "../resource.h"
+#include "../head.h"
+#include "../jnihead.h"
+#include "jniguihead.h"
+
+extern FILE* hLog;
+extern PROCESS_INFORMATION processInformation;
+
+HWND hWnd;
+DWORD dwExitCode = 0;
+BOOL stayAlive = FALSE;
+BOOL splash = FALSE;
+BOOL splashTimeoutErr;
+BOOL waitForWindow;
+BOOL restartOnCrash = FALSE;
+int splashTimeout = DEFAULT_SPLASH_TIMEOUT;
+
+int APIENTRY WinMain(HINSTANCE hInstance,
+                     HINSTANCE hPrevInstance,
+                     LPSTR     lpCmdLine,
+                     int       nCmdShow)
+{
+       int result = prepare(lpCmdLine);
+
+       if (result == ERROR_ALREADY_EXISTS)
+       {
+               HWND handle = getInstanceWindow();
+               ShowWindow(handle, SW_SHOW);
+               SetForegroundWindow(handle);
+               closeLogFile();
+               return 2;
+       }
+
+       if (result != TRUE)
+       {
+               signalError();
+               return 1;
+       }
+
+       splash = loadBool(SHOW_SPLASH)
+                       && strstr(lpCmdLine, "--l4j-no-splash") == NULL;
+       restartOnCrash = loadBool(RESTART_ON_CRASH);
+
+       // if we should restart on crash, we must also stay alive to check for crashes
+       stayAlive = restartOnCrash ||
+                         (loadBool(GUI_HEADER_STAYS_ALIVE)
+                       && strstr(lpCmdLine, "--l4j-dont-wait") == NULL);
+                       
+       if (splash || stayAlive)
+       {
+               hWnd = CreateWindowEx(WS_EX_TOOLWINDOW, "STATIC", "",
+                               WS_POPUP | SS_BITMAP,
+                               0, 0, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
+               if (splash)
+               {
+                       char timeout[10] = {0};
+                       if (loadString(SPLASH_TIMEOUT, timeout))
+                       {
+                               splashTimeout = atoi(timeout);
+                               if (splashTimeout <= 0 || splashTimeout > MAX_SPLASH_TIMEOUT)
+                               {
+                                       splashTimeout = DEFAULT_SPLASH_TIMEOUT;
+                               }
+                       }
+                       splashTimeoutErr = loadBool(SPLASH_TIMEOUT_ERR)
+                                       && strstr(lpCmdLine, "--l4j-no-splash-err") == NULL;
+                       waitForWindow = loadBool(SPLASH_WAITS_FOR_WINDOW);
+                       HANDLE hImage = LoadImage(hInstance,    // handle of the instance containing the image
+                                       MAKEINTRESOURCE(SPLASH_BITMAP), // name or identifier of image
+                                       IMAGE_BITMAP,                                   // type of image
+                                       0,                                                              // desired width
+                                       0,                                                              // desired height
+                                       LR_DEFAULTSIZE);
+                       if (hImage == NULL)
+                       {
+                               signalError();
+                               return 1;
+                       }
+                       SendMessage(hWnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hImage);
+                       RECT rect;
+                       GetWindowRect(hWnd, &rect);
+                       int x = (GetSystemMetrics(SM_CXSCREEN) - (rect.right - rect.left)) / 2;
+                       int y = (GetSystemMetrics(SM_CYSCREEN) - (rect.bottom - rect.top)) / 2;
+                       SetWindowPos(hWnd, HWND_TOP, x, y, 0, 0, SWP_NOSIZE);
+                       ShowWindow(hWnd, nCmdShow);
+                       UpdateWindow (hWnd);
+               }
+       }
+
+       do
+       {
+               if (splash || stayAlive)
+               {
+                       if (!SetTimer (hWnd, ID_TIMER, 1000 /* 1s */, TimerProc))
+                       {
+                               signalError();
+                               return 1;
+                       }
+               }
+
+               debug(getJavaHome());
+               saveJvmOptions(getJavaHome(), getMainClass(), getLauncherArgs());
+
+               if (!executeVm(&dwExitCode))
+               {
+                       signalError();
+                       return 1;
+               }
+
+               if (!(splash || stayAlive))
+               {
+                       debug("Exit code:\t0\n");
+                       closeProcessHandles();
+                       closeLogFile();
+                       return 0;
+               }
+       
+               MSG msg;
+               while (GetMessage(&msg, NULL, 0, 0))
+               {
+                       TranslateMessage(&msg);
+                       DispatchMessage(&msg);
+               }
+               
+               if (restartOnCrash && dwExitCode != 0)
+               {
+                       debug("Exit code:\t%d, restarting the application!\n", dwExitCode);
+               }
+
+               closeProcessHandles();
+       } while (restartOnCrash && dwExitCode != 0);
+
+       debug("Exit code:\t%d\n", dwExitCode);
+       closeLogFile();
+       return dwExitCode;
+}
+
+HWND getInstanceWindow()
+{
+       char windowTitle[STR];
+       char instWindowTitle[STR] = {0};
+       if (loadString(INSTANCE_WINDOW_TITLE, instWindowTitle))
+       {
+               HWND handle = FindWindowEx(NULL, NULL, NULL, NULL); 
+               while (handle != NULL)
+               {
+                       GetWindowText(handle, windowTitle, STR - 1);
+                       if (strstr(windowTitle, instWindowTitle) != NULL)
+                       {
+                               return handle;
+                       }
+                       else
+                       {
+                               handle = FindWindowEx(NULL, handle, NULL, NULL);
+                       }
+               }
+       }
+       return NULL;   
+}
+
+BOOL CALLBACK enumwndfn(HWND hwnd, LPARAM lParam)
+{
+       DWORD processId;
+       GetWindowThreadProcessId(hwnd, &processId);
+       if (processInformation.dwProcessId == processId)
+       {
+               LONG styles = GetWindowLong(hwnd, GWL_STYLE);
+               if ((styles & WS_VISIBLE) != 0)
+               {
+                       splash = FALSE;
+                       ShowWindow(hWnd, SW_HIDE);
+                       return FALSE;
+               }
+       }
+       return TRUE;
+}
+
+VOID CALLBACK TimerProc(
+       HWND hwnd,                      // handle of window for timer messages
+       UINT uMsg,                      // WM_TIMER message
+       UINT idEvent,           // timer identifier
+       DWORD dwTime)           // current system time
+{
+       if (splash)
+       {
+               if (splashTimeout == 0)
+               {
+                       splash = FALSE;
+                       ShowWindow(hWnd, SW_HIDE);
+                       if (waitForWindow && splashTimeoutErr)
+                       {
+                               KillTimer(hwnd, ID_TIMER);
+                               signalError();
+                               PostQuitMessage(0);
+                       }
+               }
+               else
+               {
+                       splashTimeout--;
+                       if (waitForWindow)
+                       {
+                               EnumWindows(enumwndfn, 0);
+                       }
+               }
+       }
+
+       GetExitCodeProcess(processInformation.hProcess, &dwExitCode);
+       if (dwExitCode != STILL_ACTIVE
+                       || !(splash || stayAlive))
+       {
+               KillTimer(hWnd, ID_TIMER);
+               PostQuitMessage(0);
+       }
+}
diff --git a/src/Launch4JStub/head_src/jniguihead_BETA/jniguihead.dev b/src/Launch4JStub/head_src/jniguihead_BETA/jniguihead.dev
new file mode 100644 (file)
index 0000000..1309b1f
--- /dev/null
@@ -0,0 +1,122 @@
+[Project]
+FileName=jniguihead.dev
+Name=jniguihead
+UnitCount=7
+Type=0
+Ver=2
+ObjFiles=
+Includes="C:\Program Files (x86)\Java\jdk 1.4\include";"C:\Program Files (x86)\Java\jdk 1.4\include\win32"
+Libs=
+PrivateResource=
+ResourceIncludes=
+MakeIncludes=
+Compiler=
+CppCompiler=
+Linker=-n_@@_
+IsCpp=0
+Icon=
+ExeOutput=
+ObjectOutput=..\..\head_jni_BETA
+OverrideOutput=0
+OverrideOutputName=jniguihead.exe
+HostApplication=
+Folders=
+CommandLine=
+UseCustomMakefile=0
+CustomMakefile=Makefile.win
+IncludeVersionInfo=0
+SupportXPThemes=0
+CompilerSet=0
+CompilerSettings=000000d000000000000001000
+LogOutput=
+LogOutputEnabled=0
+
+[Unit1]
+FileName=jniguihead.c
+CompileCpp=0
+Folder=jniguihead_BETA
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=$(CC) -c jniguihead.c -o ../../head_jni_BETA/jniguihead.o $(CFLAGS)
+
+[Unit2]
+FileName=jniguihead.h
+CompileCpp=0
+Folder=jniguihead_BETA
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[VersionInfo]
+Major=0
+Minor=1
+Release=1
+Build=1
+LanguageID=1033
+CharsetID=1252
+CompanyName=
+FileVersion=0.1.1.1
+FileDescription=Developed using the Dev-C++ IDE
+InternalName=
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=
+ProductName=
+ProductVersion=
+AutoIncBuildNr=0
+SyncProduct=0
+
+[Unit4]
+FileName=..\head.h
+CompileCpp=0
+Folder=jniguihead_BETA
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit6]
+FileName=..\jnihead.c
+CompileCpp=0
+Folder=jniguihead_BETA
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit3]
+FileName=..\head.c
+CompileCpp=0
+Folder=jniguihead_BETA
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=$(CC) -c head.c -o ../../head/head.o $(CFLAGS)
+
+[Unit5]
+FileName=..\resource.h
+CompileCpp=0
+Folder=jniguihead_BETA
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit7]
+FileName=..\jnihead.h
+CompileCpp=0
+Folder=jniguihead_BETA
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
diff --git a/src/Launch4JStub/head_src/jniguihead_BETA/jniguihead.h b/src/Launch4JStub/head_src/jniguihead_BETA/jniguihead.h
new file mode 100644 (file)
index 0000000..ebef396
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+       Launch4j (http://launch4j.sourceforge.net/)
+       Cross-platform Java application wrapper for creating Windows native executables.
+
+       Copyright (c) 2004, 2007 Grzegorz Kowal
+
+       Permission is hereby granted, free of charge, to any person obtaining a copy
+       of this software and associated documentation files (the "Software"), to deal
+       in the Software without restriction, including without limitation the rights
+       to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+       copies of the Software, and to permit persons to whom the Software is
+       furnished to do so, subject to the following conditions:
+
+       The above copyright notice and this permission notice shall be included in
+       all copies or substantial portions of the Software.
+
+       Except as contained in this notice, the name(s) of the above copyright holders
+       shall not be used in advertising or otherwise to promote the sale, use or other
+       dealings in this Software without prior written authorization.
+
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+       IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+       FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+       AUTHORS OR 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.
+*/
+
+#define ID_TIMER 1
+#define DEFAULT_SPLASH_TIMEOUT 60                      /* 60 seconds */
+#define MAX_SPLASH_TIMEOUT             60 * 15         /* 15 minutes */
+
+HWND getInstanceWindow();
+
+BOOL CALLBACK enumwndfn(HWND hwnd, LPARAM lParam);
+
+VOID CALLBACK TimerProc(
+  HWND hwnd,     // handle of window for timer messages
+  UINT uMsg,     // WM_TIMER message
+  UINT idEvent,  // timer identifier
+  DWORD dwTime   // current system time
+);
diff --git a/src/Launch4JStub/head_src/jnihead.c b/src/Launch4JStub/head_src/jnihead.c
new file mode 100644 (file)
index 0000000..16464dd
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+       Launch4j (http://launch4j.sourceforge.net/)
+       Cross-platform Java application wrapper for creating Windows native executables.
+
+       Copyright (c) 2007 Ryan Rusaw
+
+       Permission is hereby granted, free of charge, to any person obtaining a copy
+       of this software and associated documentation files (the "Software"), to deal
+       in the Software without restriction, including without limitation the rights
+       to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+       copies of the Software, and to permit persons to whom the Software is
+       furnished to do so, subject to the following conditions:
+
+       The above copyright notice and this permission notice shall be included in
+       all copies or substantial portions of the Software.
+
+       Except as contained in this notice, the name(s) of the above copyright holders
+       shall not be used in advertising or otherwise to promote the sale, use or other
+       dealings in this Software without prior written authorization.
+
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+       IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+       FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+       AUTHORS OR 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.
+*/
+
+#include "jnihead.h"
+
+/* Java Invocation API stuff */
+typedef jint (JNICALL CreateJavaVM_t)(JavaVM **pvm, void **env, void *args);
+JavaVM* g_pJavaVM = NULL;
+JNIEnv* g_pJNIEnv = NULL;
+JavaVMInitArgs g_sJavaVMInitArgs;
+char    g_rgcMnClsArgs[MAX_ARGS]  = {0};
+char   g_rgcMnCls[_MAX_PATH] = {0};
+char   g_rgcCurrJrePth[_MAX_PATH]  = {0};
+HINSTANCE  g_hInstance;
+const char* g_pcSep = " \t\f\r\n\v";
+
+int getArgCount(const char* pcArgStr) 
+{
+       const char *pCopy;
+       int iArgCnt= 0;
+       int bInWtSpc = 1;
+       for(pCopy = pcArgStr; *pCopy; pCopy++)
+       {
+               if (!isspace(*pCopy) && bInWtSpc)
+               {
+                       iArgCnt++;
+               }
+               bInWtSpc = isspace(*pCopy);
+       }
+       return iArgCnt;
+}
+
+void saveJvmOptions(const char *jrePath, const char *mainClass, const char *pcOpts)
+{
+       strcpy(g_rgcCurrJrePth, jrePath);
+       strcpy(g_rgcMnCls, mainClass);
+
+       char                            rgcOptCpy[MAX_ARGS] = {0};
+       int                             iArgCnt = 0, iCurrArg = 0, iSkipArgCnt = 0;
+       char                            *pcCurrOpt;
+       char                            **prgcVmArgs = NULL;
+       strncpy(rgcOptCpy, pcOpts, MAX_ARGS - 1);
+       
+
+       iArgCnt = getArgCount(rgcOptCpy);
+       if (iArgCnt > 0)
+       {
+               /* Allocate iArgCnt char pointers */
+               prgcVmArgs = malloc(iArgCnt * sizeof(char *)); 
+               for (pcCurrOpt = strtok(rgcOptCpy, g_pcSep); pcCurrOpt; pcCurrOpt = strtok(NULL, g_pcSep), iCurrArg++)
+               {
+                       /* Use the allocated pointers to make an array of substrings */
+                       prgcVmArgs[iCurrArg] = pcCurrOpt;
+               }
+               /* Allocat iArgCnt JavaVMOptions for the g_sJavaVMInitArgs struct */
+               g_sJavaVMInitArgs.options = malloc(iArgCnt * sizeof(JavaVMOption));
+               memset(g_sJavaVMInitArgs.options, 0, iArgCnt * sizeof(JavaVMOption));
+               char* rgcClsPth = 0;
+               /* Copy the tokenized array into the allocated JavaVMOption array,
+                * with some special handling for classpath related arguments */
+               for (iCurrArg = 0; iCurrArg < iArgCnt; iCurrArg++)
+               {
+                       if ((strcmp(prgcVmArgs[iCurrArg], "-classpath") == 0) ||
+                                         (strcmp(prgcVmArgs[iCurrArg], "-jar") == 0))
+                       {
+                               iCurrArg++;
+                               iSkipArgCnt++;
+                               if (iCurrArg < iArgCnt)
+                               {
+                                       int iOffset = *prgcVmArgs[iCurrArg] == '"' ? 1 : 0;
+                                       char rgcTmp[MAX_ARGS] = {0};
+                                       /* Remove leading and trailing "'s */\
+                                       strncpy(rgcTmp, prgcVmArgs[iCurrArg] + iOffset, 
+                                               strlen(prgcVmArgs[iCurrArg]) - iOffset);
+                                       if (rgcTmp[strlen(rgcTmp)-1] == '"')
+                                               rgcTmp[strlen(rgcTmp)-1] = '\0';
+                                       /* If we haven't defined a classpath yet start one, otherwise
+                                        * we just append the this classpath to it */
+                                       if (!rgcClsPth)
+                                       {
+                                               rgcClsPth = malloc(MAX_ARGS * sizeof(char));
+                                               memset(rgcClsPth, 0, MAX_ARGS * sizeof(char));
+                                               sprintf(rgcClsPth,"-Djava.class.path=%s", rgcTmp);
+                                               g_sJavaVMInitArgs.options[iCurrArg - iSkipArgCnt].optionString = rgcClsPth;
+                                       }
+                                       else
+                                       {
+                                               iSkipArgCnt++;
+                                               strcat(rgcClsPth,";");
+                                               strcat(rgcClsPth,rgcTmp);
+                                       }
+                                       
+                               }
+                       }
+                       else
+                       {
+                               g_sJavaVMInitArgs.options[iCurrArg - iSkipArgCnt].optionString
+                                       = malloc(strlen(prgcVmArgs[iCurrArg]) + 1);
+                               strcpy(g_sJavaVMInitArgs.options[iCurrArg - iSkipArgCnt].optionString, 
+                                               prgcVmArgs[iCurrArg]);
+                       }
+               }
+               g_sJavaVMInitArgs.nOptions = iArgCnt - iSkipArgCnt;
+               /* Free the malloc'd memory, we dont want to leak */
+               free(prgcVmArgs);
+       }
+}
+
+JNIEnv* createVm()
+{
+       int                             iRetVal;
+       CreateJavaVM_t  *pfnCreateJavaVM;
+       char                    rgcLibPth[_MAX_PATH + 18];
+       // sprintf(rgcLibPth, "%s\\bin\\client\\jvm.dll", g_rgcCurrJrePth); // TODO - could be client or server
+       sprintf(rgcLibPth, "%s\\bin\\client\\jvm.dll", g_rgcCurrJrePth);
+       
+       /* Get a handle to the jvm dll */
+       if ((g_hInstance = LoadLibrary(rgcLibPth)) == NULL)
+       {
+               return NULL;
+       }
+
+       /* Get the CreateJavaVM() function */
+       pfnCreateJavaVM = (CreateJavaVM_t *)GetProcAddress(g_hInstance, "JNI_CreateJavaVM");
+
+       if (pfnCreateJavaVM == NULL)
+       {
+               return NULL;
+       }
+
+       g_sJavaVMInitArgs.version                               = JNI_VERSION_1_2;
+       g_sJavaVMInitArgs.ignoreUnrecognized    = JNI_TRUE;
+       /* Start the VM */
+       iRetVal = pfnCreateJavaVM(&g_pJavaVM, (void **)&g_pJNIEnv, &g_sJavaVMInitArgs);
+
+       if (iRetVal != 0)
+       {
+               return NULL;
+       }
+       
+       return g_pJNIEnv;
+}
+
+int invokeMainClass(JNIEnv* psJNIEnv) 
+{
+       jclass                  jcMnCls;
+       jmethodID               jmMnMthd;
+       jobjectArray    joAppArgs;
+       jstring                 jsAppArg;
+       jthrowable              jtExcptn;
+       char                    *pcCurrArg;
+       int                             iArgCnt= 0, iOption = -1;
+       char                    rgcMnClsCpy[MAX_ARGS] = {0};
+
+       /* Ensure Java JNI Env is set up */
+       if(psJNIEnv == NULL)
+       {
+               return -1;
+       }
+       /* We need a class name */
+       if (g_rgcMnCls[0] == '\0')
+       {
+               return -1;
+       }
+       else
+       {
+               /* Replace . with / in fully qualified class name */
+               char *pClsNm;
+               for(pClsNm = g_rgcMnCls; *pClsNm; pClsNm++)
+               {
+                       if(*pClsNm == '.')
+                               *pClsNm = '/';
+               }
+       }
+       /* Find the class */
+       jcMnCls = (*psJNIEnv)->FindClass(psJNIEnv, g_rgcMnCls);
+       jtExcptn = (*psJNIEnv)->ExceptionOccurred(psJNIEnv);
+       if (jtExcptn != NULL)
+       {
+               (*psJNIEnv)->ExceptionDescribe(psJNIEnv);
+               return -1;
+       }
+       if (jcMnCls == NULL)
+       {
+               return -1;
+       }
+       /* Get the static main method */
+       jmMnMthd = (*psJNIEnv)->GetStaticMethodID(psJNIEnv, jcMnCls, "main", "([Ljava/lang/String;)V");
+       jtExcptn = (*psJNIEnv)->ExceptionOccurred(psJNIEnv);
+       if (jtExcptn != NULL)
+       {
+               (*psJNIEnv)->ExceptionDescribe(psJNIEnv);
+       }
+       if (jmMnMthd == NULL)
+       {
+               return -1;
+       }
+       /* Build the String[] array if we need one */
+       strncpy(rgcMnClsCpy, g_rgcMnClsArgs, MAX_ARGS);
+       iArgCnt = getArgCount(rgcMnClsCpy);
+       joAppArgs = (jobjectArray)(*psJNIEnv)->NewObjectArray(psJNIEnv, iArgCnt, 
+               (*psJNIEnv)->FindClass(psJNIEnv, "java/lang/String"), NULL);
+       jtExcptn = (*psJNIEnv)->ExceptionOccurred(psJNIEnv);
+       if (jtExcptn != NULL)
+       {
+               (*psJNIEnv)->ExceptionDescribe(psJNIEnv);
+               return -1;
+       }
+       for (pcCurrArg = strtok(rgcMnClsCpy, g_pcSep); pcCurrArg; pcCurrArg = strtok(NULL, g_pcSep))
+       {
+               iOption++;
+               jsAppArg = (*psJNIEnv)->NewStringUTF(psJNIEnv, pcCurrArg);
+               (*psJNIEnv)->SetObjectArrayElement(psJNIEnv, joAppArgs, iOption, jsAppArg);
+               jtExcptn = (*psJNIEnv)->ExceptionOccurred(psJNIEnv);
+               if(jtExcptn != NULL)
+               {
+                       (*psJNIEnv)->ExceptionDescribe(psJNIEnv);
+                       return -1;
+               }
+       }
+       /* Execute the class */
+       (*psJNIEnv)->CallStaticVoidMethod(psJNIEnv, jcMnCls, jmMnMthd, joAppArgs);
+       return 0;
+}
+
+void cleanupVm()
+{
+       /* Destroy the VM */
+       (*g_pJavaVM)->DestroyJavaVM(g_pJavaVM);
+}
+
+BOOL executeVm(DWORD *dwExitCode)
+{
+       BOOL result = TRUE;
+       *dwExitCode = -1;
+
+       int iIdx;
+       /* Use Invocation API */
+       if (createVm())
+       {
+               *dwExitCode = invokeMainClass(g_pJNIEnv);
+               cleanupVm();
+       }
+       else
+       {
+               result = FALSE;
+       }
+
+       /* Free the allocated memory */
+       for (iIdx = 0; iIdx < g_sJavaVMInitArgs.nOptions; iIdx++)
+       {
+               free(g_sJavaVMInitArgs.options[iIdx].optionString);
+       }
+       free(g_sJavaVMInitArgs.options);
+
+       return result;
+}
+
diff --git a/src/Launch4JStub/head_src/jnihead.h b/src/Launch4JStub/head_src/jnihead.h
new file mode 100644 (file)
index 0000000..3bd61f3
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+       Launch4j (http://launch4j.sourceforge.net/)
+       Cross-platform Java application wrapper for creating Windows native executables.
+
+       Copyright (c) 2007 Ryan Rusaw
+
+       Permission is hereby granted, free of charge, to any person obtaining a copy
+       of this software and associated documentation files (the "Software"), to deal
+       in the Software without restriction, including without limitation the rights
+       to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+       copies of the Software, and to permit persons to whom the Software is
+       furnished to do so, subject to the following conditions:
+
+       The above copyright notice and this permission notice shall be included in
+       all copies or substantial portions of the Software.
+
+       Except as contained in this notice, the name(s) of the above copyright holders
+       shall not be used in advertising or otherwise to promote the sale, use or other
+       dealings in this Software without prior written authorization.
+
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+       IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+       FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+       AUTHORS OR 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.
+*/
+
+#include <jni.h>
+#include <ctype.h>
+
+#include "head.h"
+
+int getArgCount(const char* pcArgStr);
+void saveJvmOptions(const char *jrePath, const char *mainClass, const char *pcOpts);
+JNIEnv* createVm();
+int invokeMainClass(JNIEnv* psJNIEnv);
+void cleanupVm();
+BOOL executeVm(DWORD *dwExitCode);
+
diff --git a/src/Launch4JStub/head_src/resource.h b/src/Launch4JStub/head_src/resource.h
new file mode 100644 (file)
index 0000000..829923d
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+       Launch4j (http://launch4j.sourceforge.net/)
+       Cross-platform Java application wrapper for creating Windows native executables.
+
+       Copyright (c) 2004, 2014 Grzegorz Kowal
+                                                        Ian Roberts (jdk preference patch)
+
+       Permission is hereby granted, free of charge, to any person obtaining a copy
+       of this software and associated documentation files (the "Software"), to deal
+       in the Software without restriction, including without limitation the rights
+       to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+       copies of the Software, and to permit persons to whom the Software is
+       furnished to do so, subject to the following conditions:
+
+       The above copyright notice and this permission notice shall be included in
+       all copies or substantial portions of the Software.
+
+       Except as contained in this notice, the name(s) of the above copyright holders
+       shall not be used in advertising or otherwise to promote the sale, use or other
+       dealings in this Software without prior written authorization.
+
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+       IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+       FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+       AUTHORS OR 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.
+*/
+
+// ICON
+#define APP_ICON                                       1
+
+// BITMAP
+#define SPLASH_BITMAP                          1
+
+// RCDATA
+#define JRE_PATH                                       1
+#define JAVA_MIN_VER                           2
+#define JAVA_MAX_VER                           3
+#define SHOW_SPLASH                                    4
+#define SPLASH_WAITS_FOR_WINDOW                5
+#define SPLASH_TIMEOUT                         6 
+#define SPLASH_TIMEOUT_ERR                     7
+#define CHDIR                                          8
+#define SET_PROC_NAME                          9
+#define ERR_TITLE                                      10
+#define GUI_HEADER_STAYS_ALIVE         11
+#define JVM_OPTIONS                                    12
+#define CMD_LINE                                       13
+#define JAR                                                    14
+#define MAIN_CLASS                                     15
+#define CLASSPATH                                      16
+#define WRAPPER                                                17
+#define JDK_PREFERENCE                         18
+#define ENV_VARIABLES                          19
+#define PRIORITY_CLASS                         20
+#define DOWNLOAD_URL                           21
+#define SUPPORT_URL                                    22
+#define MUTEX_NAME                                     23
+#define INSTANCE_WINDOW_TITLE          24
+#define INITIAL_HEAP_SIZE                      25
+#define INITIAL_HEAP_PERCENT           26
+#define MAX_HEAP_SIZE                          27
+#define MAX_HEAP_PERCENT                       28
+#define BUNDLED_JRE_64_BIT                     29
+#define RUNTIME_BITS                           30
+#define RESTART_ON_CRASH                       31
+#define BUNDLED_JRE_AS_FALLBACK                32
+
+#define STARTUP_ERR                                    101
+#define BUNDLED_JRE_ERR                                102
+#define JRE_VERSION_ERR                                103
+#define LAUNCHER_ERR                           104
+#define INSTANCE_ALREADY_EXISTS_MSG    105
diff --git a/src/Launch4JStub/w32api/crt2.o b/src/Launch4JStub/w32api/crt2.o
new file mode 100644 (file)
index 0000000..fc95803
Binary files /dev/null and b/src/Launch4JStub/w32api/crt2.o differ
diff --git a/src/Launch4JStub/w32api/libadvapi32.a b/src/Launch4JStub/w32api/libadvapi32.a
new file mode 100644 (file)
index 0000000..c3822c1
Binary files /dev/null and b/src/Launch4JStub/w32api/libadvapi32.a differ
diff --git a/src/Launch4JStub/w32api/libgcc.a b/src/Launch4JStub/w32api/libgcc.a
new file mode 100644 (file)
index 0000000..b369ce2
Binary files /dev/null and b/src/Launch4JStub/w32api/libgcc.a differ
diff --git a/src/Launch4JStub/w32api/libkernel32.a b/src/Launch4JStub/w32api/libkernel32.a
new file mode 100644 (file)
index 0000000..6b8a30a
Binary files /dev/null and b/src/Launch4JStub/w32api/libkernel32.a differ
diff --git a/src/Launch4JStub/w32api/libmingw32.a b/src/Launch4JStub/w32api/libmingw32.a
new file mode 100644 (file)
index 0000000..4fdcde0
Binary files /dev/null and b/src/Launch4JStub/w32api/libmingw32.a differ
diff --git a/src/Launch4JStub/w32api/libmsvcrt.a b/src/Launch4JStub/w32api/libmsvcrt.a
new file mode 100644 (file)
index 0000000..78731d2
Binary files /dev/null and b/src/Launch4JStub/w32api/libmsvcrt.a differ
diff --git a/src/Launch4JStub/w32api/libshell32.a b/src/Launch4JStub/w32api/libshell32.a
new file mode 100644 (file)
index 0000000..76cbabf
Binary files /dev/null and b/src/Launch4JStub/w32api/libshell32.a differ
diff --git a/src/Launch4JStub/w32api/libshfolder.a b/src/Launch4JStub/w32api/libshfolder.a
new file mode 100644 (file)
index 0000000..eaf1779
Binary files /dev/null and b/src/Launch4JStub/w32api/libshfolder.a differ
diff --git a/src/Launch4JStub/w32api/libuser32.a b/src/Launch4JStub/w32api/libuser32.a
new file mode 100644 (file)
index 0000000..a975fd1
Binary files /dev/null and b/src/Launch4JStub/w32api/libuser32.a differ