<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>
--- /dev/null
+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.
--- /dev/null
+/consolehead.exe
+/consolehead.layout
--- /dev/null
+# 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)
--- /dev/null
+/*
+ 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;
+}
--- /dev/null
+[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=
+
--- /dev/null
+/guihead.exe
+/guihead.layout
--- /dev/null
+# 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)
--- /dev/null
+/*
+ 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);
+ }
+}
--- /dev/null
+[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=
+
--- /dev/null
+/*
+ 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
+);
--- /dev/null
+/*
+ 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¼\91O
+ */
+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Í\81A
+ // \8c\8b\8bÇ\81A\83\8b\81[\83v\82ð\91Å\82¿\90Ø\82é\82¾\82¯\82È\82Ì\82Å\8fÈ\97ª\81B
+ 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\8aJ
+ 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µ\81A
+ // \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;
+}
+
--- /dev/null
+/*
+ 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_
--- /dev/null
+/jniconsolehead.exe
+/jniconsolehead.layout
--- /dev/null
+# 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)
--- /dev/null
+/*
+ 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;
+}
--- /dev/null
+[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=
+
--- /dev/null
+/jniguihead.exe
+/jniguihead.layout
--- /dev/null
+# 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)
--- /dev/null
+/*
+ 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);
+ }
+}
--- /dev/null
+[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=
+
--- /dev/null
+/*
+ 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
+);
--- /dev/null
+/*
+ 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;
+}
+
--- /dev/null
+/*
+ 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);
+
--- /dev/null
+/*
+ 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