• R/O
  • HTTP
  • SSH
  • HTTPS

CharacterManaJ: Commit

キャラクターなんとかJの本体


Commit MetaInfo

Revision4d4debd6a162a4dc9178726db7cc3feb5ee9eb5e (tree)
Time2018-12-30 17:43:36
Authorseraphy <seraphy@user...>
Commiterseraphy

Log Message

起動時にJava環境がバンドル位置にもレジストリからも発見できなかった場合、
ユーザーにJAVA_HOMEの場所を問い合わせるランチャにした。

Change Summary

Incremental Difference

--- a/pom.xml
+++ b/pom.xml
@@ -167,11 +167,11 @@
167167 <plugins>
168168 <plugin>
169169 <!-- Launch4jによるjarファイルのexe化を行う. http://launch4j.sourceforge.net/docs.html
170- プラグインが1.7.24の場合、使用するのはLaunch4j 3.12 である。
170+ プラグインが1.7.25の場合、使用するのはLaunch4j 3.12 である。
171171 https://github.com/lukaszlenart/launch4j-maven-plugin/blob/master/pom.xml -->
172172 <groupId>com.akathist.maven.plugins.launch4j</groupId>
173173 <artifactId>launch4j-maven-plugin</artifactId>
174- <version>1.7.24</version>
174+ <version>1.7.25</version>
175175 <executions>
176176 <execution>
177177 <id>l4j-gui</id>
@@ -185,9 +185,28 @@
185185 <jar>target/${project.artifactId}.jar</jar>
186186 <errTitle>Failed to execute the ${project.artifactId}</errTitle>
187187 <icon>icon.ico</icon>
188+ <downloadUrl>https://adoptopenjdk.net/</downloadUrl>
189+ <supportUrl>https://osdn.net/projects/charactermanaj/</supportUrl>
190+ <objs>
191+ <!-- 標準のLaunch4jの起動をカスタマイズして、JREがバンドル位置にも
192+ レジストリにも見つからなかった場合は、ユーザーに場所の選択を問い合わせる -->
193+ <obj>src/Launch4JStub/w32api/crt2.o</obj>
194+ <obj>src/Launch4JStub/head/head.o</obj>
195+ <obj>src/Launch4JStub/head/guihead.o</obj>
196+ </objs>
197+ <libs>
198+ <lib>src/Launch4jStub/w32api/libmingw32.a</lib>
199+ <lib>src/Launch4jStub/w32api/libgcc.a</lib>
200+ <lib>src/Launch4jStub/w32api/libmsvcrt.a</lib>
201+ <lib>src/Launch4jStub/w32api/libkernel32.a</lib>
202+ <lib>src/Launch4jStub/w32api/libuser32.a</lib>
203+ <lib>src/Launch4jStub/w32api/libadvapi32.a</lib>
204+ <lib>src/Launch4jStub/w32api/libshell32.a</lib>
205+ <lib>src/Launch4jStub/w32api/libshfolder.a</lib>
206+ </libs>
188207 <jre>
189208 <path>jre</path>
190- <minVersion>1.5.0</minVersion>
209+ <minVersion>1.6.0</minVersion>
191210 <initialHeapSize>64</initialHeapSize>
192211 <maxHeapSize>128</maxHeapSize>
193212 </jre>
Binary files /dev/null and b/src/Launch4JStub/head/consolehead.o differ
Binary files /dev/null and b/src/Launch4JStub/head/guihead.o differ
Binary files /dev/null and b/src/Launch4JStub/head/head.o differ
--- /dev/null
+++ b/src/Launch4JStub/head_src/LICENSE.txt
@@ -0,0 +1,26 @@
1+Launch4j (http://launch4j.sourceforge.net/)
2+Cross-platform Java application wrapper for creating Windows native executables.
3+
4+Copyright (c) 2004, 2015 Grzegorz Kowal
5+
6+Permission is hereby granted, free of charge, to any person obtaining a copy
7+of this software and associated documentation files (the "Software"), to deal
8+in the Software without restriction, including without limitation the rights
9+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+copies of the Software, and to permit persons to whom the Software is
11+furnished to do so, subject to the following conditions:
12+
13+The above copyright notice and this permission notice shall be included in
14+all copies or substantial portions of the Software.
15+
16+Except as contained in this notice, the name(s) of the above copyright holders
17+shall not be used in advertising or otherwise to promote the sale, use or other
18+dealings in this Software without prior written authorization.
19+
20+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26+THE SOFTWARE.
--- /dev/null
+++ b/src/Launch4JStub/head_src/consolehead/.gitignore
@@ -0,0 +1,2 @@
1+/consolehead.exe
2+/consolehead.layout
--- /dev/null
+++ b/src/Launch4JStub/head_src/consolehead/Makefile.win
@@ -0,0 +1,33 @@
1+# Project: consolehead
2+# Makefile created by Dev-C++ 4.9.9.2
3+
4+CPP = g++.exe
5+CC = gcc.exe
6+WINDRES = windres.exe
7+RES =
8+OBJ = ../../head/consolehead.o ../../head/head.o $(RES)
9+LINKOBJ = ../../head/consolehead.o ../../head/head.o $(RES)
10+LIBS = -L"C:/Dev-Cpp/lib" -n -s
11+INCS = -I"C:/Dev-Cpp/include"
12+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"
13+BIN = consolehead.exe
14+CXXFLAGS = $(CXXINCS) -fexpensive-optimizations -O3
15+CFLAGS = $(INCS) -fexpensive-optimizations -O3
16+RM = rm -f
17+
18+.PHONY: all all-before all-after clean clean-custom
19+
20+all: all-before consolehead.exe all-after
21+
22+
23+clean: clean-custom
24+ ${RM} $(OBJ) $(BIN)
25+
26+$(BIN): $(OBJ)
27+# $(CC) $(LINKOBJ) -o "consolehead.exe" $(LIBS)
28+
29+../../head/consolehead.o: consolehead.c
30+ $(CC) -c consolehead.c -o ../../head/consolehead.o $(CFLAGS)
31+
32+../../head/head.o: ../head.c
33+ $(CC) -c ../head.c -o ../../head/head.o $(CFLAGS)
--- /dev/null
+++ b/src/Launch4JStub/head_src/consolehead/consolehead.c
@@ -0,0 +1,97 @@
1+/*
2+ Launch4j (http://launch4j.sourceforge.net/)
3+ Cross-platform Java application wrapper for creating Windows native executables.
4+
5+ Copyright (c) 2004, 2007 Grzegorz Kowal
6+
7+ Permission is hereby granted, free of charge, to any person obtaining a copy
8+ of this software and associated documentation files (the "Software"), to deal
9+ in the Software without restriction, including without limitation the rights
10+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+ copies of the Software, and to permit persons to whom the Software is
12+ furnished to do so, subject to the following conditions:
13+
14+ The above copyright notice and this permission notice shall be included in
15+ all copies or substantial portions of the Software.
16+
17+ Except as contained in this notice, the name(s) of the above copyright holders
18+ shall not be used in advertising or otherwise to promote the sale, use or other
19+ dealings in this Software without prior written authorization.
20+
21+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27+ THE SOFTWARE.
28+*/
29+
30+#include "../resource.h"
31+#include "../head.h"
32+
33+extern FILE* hLog;
34+
35+BOOL restartOnCrash = FALSE;
36+
37+int main(int argc, char* argv[])
38+{
39+ setConsoleFlag();
40+ LPTSTR cmdLine = GetCommandLine();
41+
42+ if (*cmdLine == '"')
43+ {
44+ if (*(cmdLine = strchr(cmdLine + 1, '"') + 1))
45+ {
46+ cmdLine++;
47+ }
48+ }
49+ else if ((cmdLine = strchr(cmdLine, ' ')) != NULL)
50+ {
51+ cmdLine++;
52+ }
53+ else
54+ {
55+ cmdLine = "";
56+ }
57+
58+ int result = prepare(cmdLine);
59+
60+ if (result == ERROR_ALREADY_EXISTS)
61+ {
62+ char errMsg[BIG_STR] = {0};
63+ loadString(INSTANCE_ALREADY_EXISTS_MSG, errMsg);
64+ msgBox(errMsg);
65+ closeLogFile();
66+ return 2;
67+ }
68+
69+ if (result != TRUE)
70+ {
71+ signalError();
72+ return 1;
73+ }
74+
75+ restartOnCrash = loadBool(RESTART_ON_CRASH);
76+ DWORD dwExitCode;
77+
78+ do
79+ {
80+ dwExitCode = 0;
81+
82+ if (!execute(TRUE, &dwExitCode))
83+ {
84+ signalError();
85+ break;
86+ }
87+
88+ if (restartOnCrash && dwExitCode != 0)
89+ {
90+ debug("Exit code:\t%d, restarting the application!\n", dwExitCode);
91+ }
92+ } while (restartOnCrash && dwExitCode != 0);
93+
94+ debug("Exit code:\t%d\n", dwExitCode);
95+ closeLogFile();
96+ return (int) dwExitCode;
97+}
--- /dev/null
+++ b/src/Launch4JStub/head_src/consolehead/consolehead.dev
@@ -0,0 +1,108 @@
1+[Project]
2+FileName=consolehead.dev
3+Name=consolehead
4+UnitCount=4
5+Type=1
6+Ver=1
7+ObjFiles=
8+Includes=
9+Libs=
10+PrivateResource=
11+ResourceIncludes=
12+MakeIncludes=
13+Compiler=
14+CppCompiler=
15+Linker=-n_@@_
16+IsCpp=0
17+Icon=
18+ExeOutput=
19+ObjectOutput=..\..\head
20+OverrideOutput=0
21+OverrideOutputName=consolehead.exe
22+HostApplication=
23+Folders=
24+CommandLine=
25+UseCustomMakefile=1
26+CustomMakefile=Makefile.win
27+IncludeVersionInfo=0
28+SupportXPThemes=0
29+CompilerSet=0
30+CompilerSettings=0000000001001000000100
31+
32+[Unit1]
33+FileName=consolehead.c
34+CompileCpp=0
35+Folder=consolehead
36+Compile=1
37+Link=1
38+Priority=1000
39+OverrideBuildCmd=0
40+BuildCmd=
41+
42+[VersionInfo]
43+Major=0
44+Minor=1
45+Release=1
46+Build=1
47+LanguageID=1033
48+CharsetID=1252
49+CompanyName=
50+FileVersion=
51+FileDescription=Developed using the Dev-C++ IDE
52+InternalName=
53+LegalCopyright=
54+LegalTrademarks=
55+OriginalFilename=
56+ProductName=
57+ProductVersion=
58+AutoIncBuildNr=0
59+
60+[Unit2]
61+FileName=..\resource.h
62+CompileCpp=0
63+Folder=consolehead
64+Compile=1
65+Link=1
66+Priority=1000
67+OverrideBuildCmd=0
68+BuildCmd=
69+
70+[Unit3]
71+FileName=..\head.c
72+CompileCpp=0
73+Folder=consolehead
74+Compile=1
75+Link=1
76+Priority=1000
77+OverrideBuildCmd=0
78+BuildCmd=
79+
80+[Unit4]
81+FileName=..\head.h
82+CompileCpp=0
83+Folder=consolehead
84+Compile=1
85+Link=1
86+Priority=1000
87+OverrideBuildCmd=0
88+BuildCmd=
89+
90+[Unit5]
91+FileName=..\head.rc
92+Folder=consolehead
93+Compile=1
94+Link=0
95+Priority=1000
96+OverrideBuildCmd=0
97+BuildCmd=
98+
99+[Unit6]
100+FileName=..\resid.h
101+CompileCpp=0
102+Folder=consolehead
103+Compile=1
104+Link=1
105+Priority=1000
106+OverrideBuildCmd=0
107+BuildCmd=
108+
--- /dev/null
+++ b/src/Launch4JStub/head_src/guihead/.gitignore
@@ -0,0 +1,2 @@
1+/guihead.exe
2+/guihead.layout
--- /dev/null
+++ b/src/Launch4JStub/head_src/guihead/Makefile.win
@@ -0,0 +1,33 @@
1+# Project: guihead
2+# Makefile created by Dev-C++ 4.9.9.2
3+
4+CPP = g++.exe
5+CC = gcc.exe
6+WINDRES = windres.exe
7+RES =
8+OBJ = ../../head/guihead.o ../../head/head.o $(RES)
9+LINKOBJ = ../../head/guihead.o ../../head/head.o $(RES)
10+LIBS = -L"C:/Dev-Cpp/lib" -mwindows -n -s
11+INCS = -I"C:/Dev-Cpp/include"
12+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"
13+BIN = guihead.exe
14+CXXFLAGS = $(CXXINCS) -fexpensive-optimizations -O3
15+CFLAGS = $(INCS) -fexpensive-optimizations -O3
16+RM = rm -f
17+
18+.PHONY: all all-before all-after clean clean-custom
19+
20+all: all-before guihead.exe all-after
21+
22+
23+clean: clean-custom
24+ ${RM} $(OBJ) $(BIN)
25+
26+$(BIN): $(OBJ)
27+# $(CC) $(LINKOBJ) -o "guihead.exe" $(LIBS)
28+
29+../../head/guihead.o: guihead.c
30+ $(CC) -c guihead.c -o ../../head/guihead.o $(CFLAGS)
31+
32+../../head/head.o: ../head.c
33+ $(CC) -c ../head.c -o ../../head/head.o $(CFLAGS)
--- /dev/null
+++ b/src/Launch4JStub/head_src/guihead/guihead.c
@@ -0,0 +1,241 @@
1+/*
2+ Launch4j (http://launch4j.sourceforge.net/)
3+ Cross-platform Java application wrapper for creating Windows native executables.
4+
5+ Copyright (c) 2004, 2015 Grzegorz Kowal
6+ Sylvain Mina (single instance patch)
7+
8+ Permission is hereby granted, free of charge, to any person obtaining a copy
9+ of this software and associated documentation files (the "Software"), to deal
10+ in the Software without restriction, including without limitation the rights
11+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+ copies of the Software, and to permit persons to whom the Software is
13+ furnished to do so, subject to the following conditions:
14+
15+ The above copyright notice and this permission notice shall be included in
16+ all copies or substantial portions of the Software.
17+
18+ Except as contained in this notice, the name(s) of the above copyright holders
19+ shall not be used in advertising or otherwise to promote the sale, use or other
20+ dealings in this Software without prior written authorization.
21+
22+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28+ THE SOFTWARE.
29+*/
30+
31+#include "../resource.h"
32+#include "../head.h"
33+#include "guihead.h"
34+
35+extern FILE* hLog;
36+extern PROCESS_INFORMATION processInformation;
37+
38+HWND hWnd;
39+DWORD dwExitCode = 0;
40+BOOL stayAlive = FALSE;
41+BOOL splash = FALSE;
42+BOOL splashTimeoutErr;
43+BOOL waitForWindow;
44+BOOL restartOnCrash = FALSE;
45+int splashTimeout = DEFAULT_SPLASH_TIMEOUT;
46+
47+int APIENTRY WinMain(HINSTANCE hInstance,
48+ HINSTANCE hPrevInstance,
49+ LPSTR lpCmdLine,
50+ int nCmdShow)
51+{
52+ int result = prepare(lpCmdLine);
53+
54+ if (result == ERROR_ALREADY_EXISTS)
55+ {
56+ HWND handle = getInstanceWindow();
57+ ShowWindow(handle, SW_SHOW);
58+ SetForegroundWindow(handle);
59+ closeLogFile();
60+ return 2;
61+ }
62+
63+ if (result != TRUE)
64+ {
65+ signalError();
66+ return 1;
67+ }
68+
69+ splash = loadBool(SHOW_SPLASH)
70+ && strstr(lpCmdLine, "--l4j-no-splash") == NULL;
71+ restartOnCrash = loadBool(RESTART_ON_CRASH);
72+
73+ // if we should restart on crash, we must also stay alive to check for crashes
74+ stayAlive = restartOnCrash ||
75+ (loadBool(GUI_HEADER_STAYS_ALIVE)
76+ && strstr(lpCmdLine, "--l4j-dont-wait") == NULL);
77+
78+ if (splash || stayAlive)
79+ {
80+ hWnd = CreateWindowEx(WS_EX_TOOLWINDOW, "STATIC", "",
81+ WS_POPUP | SS_BITMAP,
82+ 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
83+ if (splash)
84+ {
85+ char timeout[10] = {0};
86+ if (loadString(SPLASH_TIMEOUT, timeout))
87+ {
88+ splashTimeout = atoi(timeout);
89+ if (splashTimeout <= 0 || splashTimeout > MAX_SPLASH_TIMEOUT)
90+ {
91+ splashTimeout = DEFAULT_SPLASH_TIMEOUT;
92+ }
93+ }
94+ splashTimeout = splashTimeout * 1000; // to millis
95+ splashTimeoutErr = loadBool(SPLASH_TIMEOUT_ERR)
96+ && strstr(lpCmdLine, "--l4j-no-splash-err") == NULL;
97+ waitForWindow = loadBool(SPLASH_WAITS_FOR_WINDOW);
98+ HANDLE hImage = LoadImage(hInstance, // handle of the instance containing the image
99+ MAKEINTRESOURCE(SPLASH_BITMAP), // name or identifier of image
100+ IMAGE_BITMAP, // type of image
101+ 0, // desired width
102+ 0, // desired height
103+ LR_DEFAULTSIZE);
104+ if (hImage == NULL)
105+ {
106+ signalError();
107+ return 1;
108+ }
109+ SendMessage(hWnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hImage);
110+ RECT rect;
111+ GetWindowRect(hWnd, &rect);
112+ int x = (GetSystemMetrics(SM_CXSCREEN) - (rect.right - rect.left)) / 2;
113+ int y = (GetSystemMetrics(SM_CYSCREEN) - (rect.bottom - rect.top)) / 2;
114+ SetWindowPos(hWnd, HWND_TOP, x, y, 0, 0, SWP_NOSIZE);
115+ ShowWindow(hWnd, nCmdShow);
116+ UpdateWindow (hWnd);
117+ }
118+ }
119+
120+ do
121+ {
122+ if (splash || stayAlive)
123+ {
124+ if (!SetTimer (hWnd, ID_TIMER, TIMER_PROC_INTERVAL, TimerProc))
125+ {
126+ signalError();
127+ return 1;
128+ }
129+ }
130+
131+ if (!execute(FALSE, &dwExitCode))
132+ {
133+ signalError();
134+ return 1;
135+ }
136+
137+ if (!(splash || stayAlive))
138+ {
139+ debug("Exit code:\t0\n");
140+ closeProcessHandles();
141+ closeLogFile();
142+ return 0;
143+ }
144+
145+ MSG msg;
146+ while (GetMessage(&msg, NULL, 0, 0))
147+ {
148+ TranslateMessage(&msg);
149+ DispatchMessage(&msg);
150+ }
151+
152+ if (restartOnCrash && dwExitCode != 0)
153+ {
154+ debug("Exit code:\t%d, restarting the application!\n", dwExitCode);
155+ }
156+
157+ closeProcessHandles();
158+ } while (restartOnCrash && dwExitCode != 0);
159+
160+ debug("Exit code:\t%d\n", dwExitCode);
161+ closeLogFile();
162+ return dwExitCode;
163+}
164+
165+HWND getInstanceWindow()
166+{
167+ char windowTitle[STR];
168+ char instWindowTitle[STR] = {0};
169+ if (loadString(INSTANCE_WINDOW_TITLE, instWindowTitle))
170+ {
171+ HWND handle = FindWindowEx(NULL, NULL, NULL, NULL);
172+ while (handle != NULL)
173+ {
174+ GetWindowText(handle, windowTitle, STR - 1);
175+ if (strstr(windowTitle, instWindowTitle) != NULL)
176+ {
177+ return handle;
178+ }
179+ else
180+ {
181+ handle = FindWindowEx(NULL, handle, NULL, NULL);
182+ }
183+ }
184+ }
185+ return NULL;
186+}
187+
188+BOOL CALLBACK enumwndfn(HWND hwnd, LPARAM lParam)
189+{
190+ DWORD processId;
191+ GetWindowThreadProcessId(hwnd, &processId);
192+ if (processInformation.dwProcessId == processId)
193+ {
194+ LONG styles = GetWindowLong(hwnd, GWL_STYLE);
195+ if ((styles & WS_VISIBLE) != 0)
196+ {
197+ splash = FALSE;
198+ ShowWindow(hWnd, SW_HIDE);
199+ return FALSE;
200+ }
201+ }
202+ return TRUE;
203+}
204+
205+VOID CALLBACK TimerProc(
206+ HWND hwnd, // handle of window for timer messages
207+ UINT uMsg, // WM_TIMER message
208+ UINT idEvent, // timer identifier
209+ DWORD dwTime) // current system time
210+{
211+ if (splash)
212+ {
213+ if (splashTimeout == 0)
214+ {
215+ splash = FALSE;
216+ ShowWindow(hWnd, SW_HIDE);
217+ if (waitForWindow && splashTimeoutErr)
218+ {
219+ KillTimer(hwnd, ID_TIMER);
220+ signalError();
221+ PostQuitMessage(0);
222+ }
223+ }
224+ else
225+ {
226+ splashTimeout -= TIMER_PROC_INTERVAL;
227+ if (waitForWindow)
228+ {
229+ EnumWindows(enumwndfn, 0);
230+ }
231+ }
232+ }
233+
234+ GetExitCodeProcess(processInformation.hProcess, &dwExitCode);
235+ if (dwExitCode != STILL_ACTIVE
236+ || !(splash || stayAlive))
237+ {
238+ KillTimer(hWnd, ID_TIMER);
239+ PostQuitMessage(0);
240+ }
241+}
--- /dev/null
+++ b/src/Launch4JStub/head_src/guihead/guihead.dev
@@ -0,0 +1,109 @@
1+[Project]
2+FileName=guihead.dev
3+Name=guihead
4+UnitCount=5
5+Type=0
6+Ver=1
7+ObjFiles=
8+Includes=
9+Libs=
10+PrivateResource=
11+ResourceIncludes=
12+MakeIncludes=
13+Compiler=
14+CppCompiler=
15+Linker=-n_@@_
16+IsCpp=0
17+Icon=
18+ExeOutput=
19+ObjectOutput=..\..\head
20+OverrideOutput=0
21+OverrideOutputName=guihead.exe
22+HostApplication=
23+Folders=
24+CommandLine=
25+UseCustomMakefile=1
26+CustomMakefile=Makefile.win
27+IncludeVersionInfo=0
28+SupportXPThemes=0
29+CompilerSet=0
30+CompilerSettings=0000000001001000000100
31+
32+[Unit1]
33+FileName=guihead.c
34+CompileCpp=0
35+Folder=guihead
36+Compile=1
37+Link=1
38+Priority=1000
39+OverrideBuildCmd=0
40+BuildCmd=$(CC) -c guihead.c -o ../../head/guihead.o $(CFLAGS)
41+
42+[Unit2]
43+FileName=guihead.h
44+CompileCpp=0
45+Folder=guihead
46+Compile=1
47+Link=1
48+Priority=1000
49+OverrideBuildCmd=0
50+BuildCmd=
51+
52+[VersionInfo]
53+Major=0
54+Minor=1
55+Release=1
56+Build=1
57+LanguageID=1033
58+CharsetID=1252
59+CompanyName=
60+FileVersion=
61+FileDescription=Developed using the Dev-C++ IDE
62+InternalName=
63+LegalCopyright=
64+LegalTrademarks=
65+OriginalFilename=
66+ProductName=
67+ProductVersion=
68+AutoIncBuildNr=0
69+
70+[Unit4]
71+FileName=..\head.h
72+CompileCpp=0
73+Folder=guihead
74+Compile=1
75+Link=1
76+Priority=1000
77+OverrideBuildCmd=0
78+BuildCmd=
79+
80+[Unit6]
81+FileName=..\resid.h
82+CompileCpp=0
83+Folder=guihead
84+Compile=1
85+Link=1
86+Priority=1000
87+OverrideBuildCmd=0
88+BuildCmd=
89+
90+[Unit3]
91+FileName=..\head.c
92+CompileCpp=0
93+Folder=guihead
94+Compile=1
95+Link=1
96+Priority=1000
97+OverrideBuildCmd=0
98+BuildCmd=
99+
100+[Unit5]
101+FileName=..\resource.h
102+CompileCpp=0
103+Folder=guihead
104+Compile=1
105+Link=1
106+Priority=1000
107+OverrideBuildCmd=0
108+BuildCmd=
109+
--- /dev/null
+++ b/src/Launch4JStub/head_src/guihead/guihead.h
@@ -0,0 +1,44 @@
1+/*
2+ Launch4j (http://launch4j.sourceforge.net/)
3+ Cross-platform Java application wrapper for creating Windows native executables.
4+
5+ Copyright (c) 2004, 2007 Grzegorz Kowal
6+
7+ Permission is hereby granted, free of charge, to any person obtaining a copy
8+ of this software and associated documentation files (the "Software"), to deal
9+ in the Software without restriction, including without limitation the rights
10+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+ copies of the Software, and to permit persons to whom the Software is
12+ furnished to do so, subject to the following conditions:
13+
14+ The above copyright notice and this permission notice shall be included in
15+ all copies or substantial portions of the Software.
16+
17+ Except as contained in this notice, the name(s) of the above copyright holders
18+ shall not be used in advertising or otherwise to promote the sale, use or other
19+ dealings in this Software without prior written authorization.
20+
21+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27+ THE SOFTWARE.
28+*/
29+
30+#define ID_TIMER 1
31+#define DEFAULT_SPLASH_TIMEOUT 60 /* 60 seconds */
32+#define MAX_SPLASH_TIMEOUT 60 * 15 /* 15 minutes */
33+#define TIMER_PROC_INTERVAL 100 /* interval in ms between calls to EnumWindows */
34+
35+HWND getInstanceWindow();
36+
37+BOOL CALLBACK enumwndfn(HWND hwnd, LPARAM lParam);
38+
39+VOID CALLBACK TimerProc(
40+ HWND hwnd, // handle of window for timer messages
41+ UINT uMsg, // WM_TIMER message
42+ UINT idEvent, // timer identifier
43+ DWORD dwTime // current system time
44+);
--- /dev/null
+++ b/src/Launch4JStub/head_src/head.c
@@ -0,0 +1,1580 @@
1+/*
2+ Launch4j (http://launch4j.sourceforge.net/)
3+ Cross-platform Java application wrapper for creating Windows native executables.
4+
5+ Copyright (c) 2004, 2015 Grzegorz Kowal,
6+ Ian Roberts (jdk preference patch)
7+ Sylvain Mina (single instance patch)
8+
9+ Permission is hereby granted, free of charge, to any person obtaining a copy
10+ of this software and associated documentation files (the "Software"), to deal
11+ in the Software without restriction, including without limitation the rights
12+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+ copies of the Software, and to permit persons to whom the Software is
14+ furnished to do so, subject to the following conditions:
15+
16+ The above copyright notice and this permission notice shall be included in
17+ all copies or substantial portions of the Software.
18+
19+ Except as contained in this notice, the name(s) of the above copyright holders
20+ shall not be used in advertising or otherwise to promote the sale, use or other
21+ dealings in this Software without prior written authorization.
22+
23+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29+ THE SOFTWARE.
30+*/
31+
32+#include "resource.h"
33+#include "head.h"
34+
35+HMODULE hModule;
36+FILE* hLog;
37+BOOL debugAll = FALSE;
38+BOOL console = FALSE;
39+BOOL wow64 = FALSE;
40+char oldPwd[_MAX_PATH];
41+
42+PROCESS_INFORMATION processInformation;
43+DWORD processPriority;
44+
45+struct
46+{
47+ char title[STR];
48+ char msg[BIG_STR];
49+ char url[256];
50+} error;
51+
52+struct
53+{
54+ int runtimeBits;
55+ int foundJava;
56+ BOOL bundledJreAsFallback;
57+ BOOL corruptedJreFound;
58+ char originalJavaMinVer[STR];
59+ char originalJavaMaxVer[STR];
60+ char javaMinVer[STR];
61+ char javaMaxVer[STR];
62+ char foundJavaVer[STR];
63+ char foundJavaKey[_MAX_PATH];
64+ char foundJavaHome[_MAX_PATH];
65+} search;
66+
67+struct
68+{
69+ char mainClass[_MAX_PATH];
70+ char cmd[_MAX_PATH];
71+ char args[MAX_ARGS];
72+} launcher;
73+
74+BOOL initGlobals()
75+{
76+ hModule = GetModuleHandle(NULL);
77+
78+ if (hModule == NULL)
79+ {
80+ return FALSE;
81+ }
82+
83+ strcpy(error.title, LAUNCH4j);
84+
85+ search.runtimeBits = INIT_RUNTIME_BITS;
86+ search.foundJava = NO_JAVA_FOUND;
87+ search.bundledJreAsFallback = FALSE;
88+ search.corruptedJreFound = FALSE;
89+
90+ return TRUE;
91+}
92+
93+FILE* openLogFile(const char* exePath, const int pathLen)
94+{
95+ char path[_MAX_PATH] = {0};
96+ strncpy(path, exePath, pathLen);
97+ strcat(path, "\\launch4j.log");
98+ return fopen(path, "a");
99+}
100+
101+void closeLogFile()
102+{
103+ if (hLog != NULL)
104+ {
105+ fclose(hLog);
106+ }
107+}
108+
109+BOOL initializeLogging(const char *lpCmdLine, const char* exePath, const int pathLen)
110+{
111+ char varValue[MAX_VAR_SIZE] = {0};
112+ GetEnvironmentVariable(LAUNCH4j, varValue, MAX_VAR_SIZE);
113+
114+ if (strstr(lpCmdLine, "--l4j-debug") != NULL
115+ || strstr(varValue, "debug") != NULL)
116+ {
117+ hLog = openLogFile(exePath, pathLen);
118+
119+ if (hLog == NULL)
120+ {
121+ return FALSE;
122+ }
123+
124+ debugAll = strstr(lpCmdLine, "--l4j-debug-all") != NULL
125+ || strstr(varValue, "debug-all") != NULL;
126+ }
127+
128+ debug("\n\nVersion:\t%s\n", VERSION);
129+ debug("CmdLine:\t%s %s\n", exePath, lpCmdLine);
130+
131+ return TRUE;
132+}
133+
134+void setWow64Flag()
135+{
136+ LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(
137+ GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
138+
139+ if (fnIsWow64Process != NULL)
140+ {
141+ fnIsWow64Process(GetCurrentProcess(), &wow64);
142+ }
143+
144+ debug("WOW64:\t\t%s\n", wow64 ? "yes" : "no");
145+}
146+
147+void setConsoleFlag()
148+{
149+ console = TRUE;
150+}
151+
152+void msgBox(const char* text)
153+{
154+ if (console)
155+ {
156+ if (*error.title)
157+ {
158+ printf("%s: %s\n", error.title, text);
159+ }
160+ else
161+ {
162+ printf("%s\n", text);
163+ }
164+ }
165+ else
166+ {
167+ MessageBox(NULL, text, error.title, MB_OK);
168+ }
169+}
170+
171+void signalError()
172+{
173+ DWORD err = GetLastError();
174+ debug("Error msg:\t%s\n", error.msg);
175+
176+ if (err)
177+ {
178+ LPVOID lpMsgBuf;
179+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
180+ | FORMAT_MESSAGE_FROM_SYSTEM
181+ | FORMAT_MESSAGE_IGNORE_INSERTS,
182+ NULL,
183+ err,
184+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
185+ (LPTSTR) &lpMsgBuf,
186+ 0,
187+ NULL);
188+ debug(ERROR_FORMAT, (LPCTSTR) lpMsgBuf);
189+ strcat(error.msg, "\n\n");
190+ strcat(error.msg, (LPCTSTR) lpMsgBuf);
191+ LocalFree(lpMsgBuf);
192+ }
193+
194+ msgBox(error.msg);
195+
196+ if (*error.url)
197+ {
198+ debug("Open URL:\t%s\n", error.url);
199+ ShellExecute(NULL, "open", error.url, NULL, NULL, SW_SHOWNORMAL);
200+ }
201+
202+ closeLogFile();
203+}
204+
205+BOOL loadString(const int resID, char* buffer)
206+{
207+ HRSRC hResource;
208+ HGLOBAL hResourceLoaded;
209+ LPBYTE lpBuffer;
210+ debugAll("Resource %d:\t", resID);
211+
212+ hResource = FindResourceEx(hModule, RT_RCDATA, MAKEINTRESOURCE(resID),
213+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT));
214+ if (NULL != hResource)
215+ {
216+ hResourceLoaded = LoadResource(hModule, hResource);
217+ if (NULL != hResourceLoaded)
218+ {
219+ lpBuffer = (LPBYTE) LockResource(hResourceLoaded);
220+ if (NULL != lpBuffer)
221+ {
222+ int x = 0;
223+ do
224+ {
225+ buffer[x] = (char) lpBuffer[x];
226+ } while (buffer[x++] != 0);
227+
228+ debugAll("%s\n", buffer);
229+ return TRUE;
230+ }
231+ }
232+ }
233+ else
234+ {
235+ SetLastError(0);
236+ buffer[0] = 0;
237+ }
238+
239+ debugAll("<NULL>\n");
240+ return FALSE;
241+}
242+
243+BOOL loadBool(const int resID)
244+{
245+ char boolStr[20] = {0};
246+ loadString(resID, boolStr);
247+ return strcmp(boolStr, TRUE_STR) == 0;
248+}
249+
250+int loadInt(const int resID)
251+{
252+ char intStr[20] = {0};
253+ loadString(resID, intStr);
254+ return atoi(intStr);
255+}
256+
257+BOOL regQueryValue(const char* regPath, unsigned char* buffer,
258+ unsigned long bufferLength)
259+{
260+ HKEY hRootKey;
261+ char* key;
262+ char* value;
263+
264+ if (strstr(regPath, HKEY_CLASSES_ROOT_STR) == regPath)
265+ {
266+ hRootKey = HKEY_CLASSES_ROOT;
267+ }
268+ else if (strstr(regPath, HKEY_CURRENT_USER_STR) == regPath)
269+ {
270+ hRootKey = HKEY_CURRENT_USER;
271+ }
272+ else if (strstr(regPath, HKEY_LOCAL_MACHINE_STR) == regPath)
273+ {
274+ hRootKey = HKEY_LOCAL_MACHINE;
275+ }
276+ else if (strstr(regPath, HKEY_USERS_STR) == regPath)
277+ {
278+ hRootKey = HKEY_USERS;
279+ }
280+ else if (strstr(regPath, HKEY_CURRENT_CONFIG_STR) == regPath)
281+ {
282+ hRootKey = HKEY_CURRENT_CONFIG;
283+ }
284+ else
285+ {
286+ return FALSE;
287+ }
288+
289+ key = strchr(regPath, '\\') + 1;
290+ value = strrchr(regPath, '\\') + 1;
291+ *(value - 1) = 0;
292+
293+ HKEY hKey;
294+ unsigned long datatype;
295+ BOOL result = FALSE;
296+ if ((wow64 && RegOpenKeyEx(hRootKey,
297+ key,
298+ 0,
299+ KEY_READ | KEY_WOW64_64KEY,
300+ &hKey) == ERROR_SUCCESS)
301+ || RegOpenKeyEx(hRootKey,
302+ key,
303+ 0,
304+ KEY_READ,
305+ &hKey) == ERROR_SUCCESS)
306+ {
307+ result = RegQueryValueEx(hKey, value, NULL, &datatype, buffer, &bufferLength)
308+ == ERROR_SUCCESS;
309+ RegCloseKey(hKey);
310+ }
311+ *(value - 1) = '\\';
312+ return result;
313+}
314+
315+int findNextVersionPart(const char* startAt)
316+{
317+ if (startAt == NULL || strlen(startAt) == 0)
318+ {
319+ return 0;
320+ }
321+
322+ char* firstSeparatorA = strchr(startAt, '.');
323+ char* firstSeparatorB = strchr(startAt, '_');
324+ char* firstSeparator;
325+ if (firstSeparatorA == NULL)
326+ {
327+ firstSeparator = firstSeparatorB;
328+ }
329+ else if (firstSeparatorB == NULL)
330+ {
331+ firstSeparator = firstSeparatorA;
332+ }
333+ else
334+ {
335+ firstSeparator = min(firstSeparatorA, firstSeparatorB);
336+ }
337+
338+ if (firstSeparator == NULL)
339+ {
340+ return strlen(startAt);
341+ }
342+
343+ return firstSeparator - startAt;
344+}
345+
346+/**
347+ * This method will take java version from `originalVersion` string and convert/format it
348+ * into `version` string that can be used for string comparison with other versions.
349+ *
350+ * Due to different version schemas <=8 vs. >=9 it will "normalize" versions to 1 format
351+ * so we can directly compare old and new versions.
352+ */
353+void formatJavaVersion(char* version, const char* originalVersion)
354+{
355+ strcpy(version, "");
356+ if (originalVersion == NULL || strlen(originalVersion) == 0)
357+ {
358+ return;
359+ }
360+
361+ int partsAdded = 0;
362+ int i;
363+ char* pos = (char*) originalVersion;
364+ int curPartLen;
365+
366+ while ((curPartLen = findNextVersionPart(pos)) > 0)
367+ {
368+ char number[curPartLen + 1];
369+ memset(number, 0, curPartLen + 1);
370+ strncpy(number, pos, curPartLen);
371+
372+ if (partsAdded == 0 && (curPartLen != 1 || number[0] != '1'))
373+ {
374+ // NOTE: When it's java 9+ we'll add "1" as the first part of the version
375+ strcpy(version, "1");
376+ partsAdded++;
377+ }
378+
379+ if (partsAdded < 3)
380+ {
381+ if (partsAdded > 0)
382+ {
383+ strcat(version, ".");
384+ }
385+ for (i = 0;
386+ (partsAdded > 0)
387+ && (i < JRE_VER_MAX_DIGITS_PER_PART - strlen(number));
388+ i++)
389+ {
390+ strcat(version, "0");
391+ }
392+ strcat(version, number);
393+ }
394+ else if (partsAdded == 3)
395+ {
396+ // add as an update
397+ strcat(version, "_");
398+ for (i = 0; i < JRE_VER_MAX_DIGITS_PER_PART - strlen(number); i++)
399+ {
400+ strcat(version, "0");
401+ }
402+ strcat(version, number);
403+ }
404+ else if (partsAdded >= 4)
405+ {
406+ debug("Warning:\tformatJavaVersion() too many parts added.\n");
407+ break;
408+ }
409+ partsAdded++;
410+
411+ pos += curPartLen + 1;
412+ if (pos >= originalVersion + strlen(originalVersion))
413+ {
414+ break;
415+ }
416+ }
417+
418+ for (i = partsAdded; i < 3; i++)
419+ {
420+ strcat(version, ".");
421+ int j;
422+ for (j = 0; j < JRE_VER_MAX_DIGITS_PER_PART; j++)
423+ {
424+ strcat(version, "0");
425+ }
426+ }
427+}
428+
429+void regSearch(const char* keyName, const int searchType)
430+{
431+ HKEY hKey;
432+ const DWORD wow64KeyMask = searchType & KEY_WOW64_64KEY;
433+
434+ debug("%s-bit search:\t%s...\n", wow64KeyMask ? "64" : "32", keyName);
435+
436+ if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE,
437+ keyName,
438+ 0,
439+ KEY_READ | wow64KeyMask,
440+ &hKey) == ERROR_SUCCESS)
441+ {
442+ return;
443+ }
444+
445+ DWORD x = 0;
446+ unsigned long versionSize = _MAX_PATH;
447+ FILETIME time;
448+ char fullKeyName[_MAX_PATH] = {0};
449+ char originalVersion[_MAX_PATH] = {0};
450+ char version[_MAX_PATH] = {0};
451+
452+ while (RegEnumKeyEx(
453+ hKey, // handle to key to enumerate
454+ x++, // index of subkey to enumerate
455+ originalVersion,// address of buffer for subkey name
456+ &versionSize, // address for size of subkey buffer
457+ NULL, // reserved
458+ NULL, // address of buffer for class string
459+ NULL, // address for size of class buffer
460+ &time) == ERROR_SUCCESS)
461+ {
462+ strcpy(fullKeyName, keyName);
463+ appendPath(fullKeyName, originalVersion);
464+ debug("Check:\t\t%s\n", fullKeyName);
465+ formatJavaVersion(version, originalVersion);
466+
467+ if (strcmp(version, search.javaMinVer) >= 0
468+ && (!*search.javaMaxVer || strcmp(version, search.javaMaxVer) <= 0)
469+ && strcmp(version, search.foundJavaVer) > 0
470+ && isJavaHomeValid(fullKeyName, searchType))
471+ {
472+ strcpy(search.foundJavaVer, version);
473+ strcpy(search.foundJavaKey, fullKeyName);
474+ search.foundJava = searchType;
475+ debug("Match:\t\t%s\n", version);
476+ }
477+ else
478+ {
479+ debug("Ignore:\t\t%s\n", version);
480+ }
481+
482+ versionSize = _MAX_PATH;
483+ }
484+
485+ RegCloseKey(hKey);
486+}
487+
488+BOOL isJavaHomeValid(const char* keyName, const int searchType)
489+{
490+ BOOL valid = FALSE;
491+ HKEY hKey;
492+ char path[_MAX_PATH] = {0};
493+
494+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
495+ keyName,
496+ 0,
497+ KEY_READ | (searchType & KEY_WOW64_64KEY),
498+ &hKey) == ERROR_SUCCESS)
499+ {
500+ unsigned char buffer[_MAX_PATH] = {0};
501+ unsigned long bufferlength = _MAX_PATH;
502+ unsigned long datatype;
503+
504+ if (RegQueryValueEx(hKey, "JavaHome", NULL, &datatype, buffer,
505+ &bufferlength) == ERROR_SUCCESS)
506+ {
507+ int i = 0;
508+ do
509+ {
510+ path[i] = buffer[i];
511+ } while (path[i++] != 0);
512+
513+ valid = isLauncherPathValid(path);
514+ }
515+ RegCloseKey(hKey);
516+ }
517+
518+ if (valid)
519+ {
520+ strcpy(search.foundJavaHome, path);
521+ }
522+ else
523+ {
524+ search.corruptedJreFound = TRUE;
525+ }
526+
527+ return valid;
528+}
529+
530+BOOL isLauncherPathValid(const char* path)
531+{
532+ struct _stat statBuf;
533+ char launcherPath[_MAX_PATH] = {0};
534+ BOOL result = FALSE;
535+
536+ if (*path)
537+ {
538+ strcpy(launcherPath, path);
539+ appendLauncher(launcherPath);
540+ result = _stat(launcherPath, &statBuf) == 0;
541+
542+ if (!result)
543+ {
544+ // Don't display additional info in the error popup.
545+ SetLastError(0);
546+ }
547+ }
548+
549+ debug("Check launcher:\t%s %s\n", launcherPath, result ? "(OK)" : "(not found)");
550+ return result;
551+}
552+
553+void regSearchWow(const char* keyName, const int searchType)
554+{
555+ if (search.runtimeBits == INIT_RUNTIME_BITS)
556+ {
557+ search.runtimeBits = loadInt(RUNTIME_BITS);
558+ }
559+
560+ switch (search.runtimeBits)
561+ {
562+ case USE_64_BIT_RUNTIME:
563+ if (wow64)
564+ {
565+ regSearch(keyName, searchType | KEY_WOW64_64KEY);
566+ }
567+ break;
568+
569+ case USE_64_AND_32_BIT_RUNTIME:
570+ if (wow64)
571+ {
572+ regSearch(keyName, searchType | KEY_WOW64_64KEY);
573+
574+ if ((search.foundJava & KEY_WOW64_64KEY) != NO_JAVA_FOUND)
575+ {
576+ break;
577+ }
578+ }
579+
580+ regSearch(keyName, searchType);
581+ break;
582+
583+ case USE_32_AND_64_BIT_RUNTIME:
584+ regSearch(keyName, searchType);
585+
586+ if (search.foundJava != NO_JAVA_FOUND
587+ && (search.foundJava & KEY_WOW64_64KEY) == NO_JAVA_FOUND)
588+ {
589+ break;
590+ }
591+
592+ if (wow64)
593+ {
594+ regSearch(keyName, searchType | KEY_WOW64_64KEY);
595+ }
596+ break;
597+
598+ case USE_32_BIT_RUNTIME:
599+ regSearch(keyName, searchType);
600+ break;
601+
602+ default:
603+ debug("Runtime bits:\tFailed to load.\n");
604+ break;
605+ }
606+}
607+
608+void regSearchJreSdk(const char* jreKeyName, const char* sdkKeyName,
609+ const int jdkPreference)
610+{
611+ if (jdkPreference == JDK_ONLY || jdkPreference == PREFER_JDK)
612+ {
613+ regSearchWow(sdkKeyName, FOUND_SDK);
614+ if (jdkPreference != JDK_ONLY)
615+ {
616+ regSearchWow(jreKeyName, FOUND_JRE);
617+ }
618+ }
619+ else
620+ {
621+ // jdkPreference == JRE_ONLY or PREFER_JRE
622+ regSearchWow(jreKeyName, FOUND_JRE);
623+ if (jdkPreference != JRE_ONLY)
624+ {
625+ regSearchWow(sdkKeyName, FOUND_SDK);
626+ }
627+ }
628+}
629+
630+BOOL findJavaHome(char* path, const int jdkPreference)
631+{
632+ debugAll("findJavaHome()\n");
633+ regSearchJreSdk("SOFTWARE\\JavaSoft\\Java Runtime Environment",
634+ "SOFTWARE\\JavaSoft\\Java Development Kit",
635+ jdkPreference);
636+
637+ // Java 9 support
638+ regSearchJreSdk("SOFTWARE\\JavaSoft\\JRE",
639+ "SOFTWARE\\JavaSoft\\JDK",
640+ jdkPreference);
641+
642+ // IBM Java 1.8
643+ if (search.foundJava == NO_JAVA_FOUND)
644+ {
645+ regSearchJreSdk("SOFTWARE\\IBM\\Java Runtime Environment",
646+ "SOFTWARE\\IBM\\Java Development Kit",
647+ jdkPreference);
648+ }
649+
650+ // IBM Java 1.7 and earlier
651+ if (search.foundJava == NO_JAVA_FOUND)
652+ {
653+ regSearchJreSdk("SOFTWARE\\IBM\\Java2 Runtime Environment",
654+ "SOFTWARE\\IBM\\Java Development Kit",
655+ jdkPreference);
656+ }
657+
658+ if (search.foundJava != NO_JAVA_FOUND)
659+ {
660+ strcpy(path, search.foundJavaHome);
661+ debug("Runtime used:\t%s (%s-bit)\n", search.foundJavaVer,
662+ (search.foundJava & KEY_WOW64_64KEY) != NO_JAVA_FOUND ? "64" : "32");
663+ return TRUE;
664+ }
665+
666+ return FALSE;
667+}
668+
669+BOOL checkJavaExe(char *path)
670+{
671+ char path2[MAX_PATH];
672+ strcpy(path2, path);
673+ strcat(path2, "\\bin\\java.exe");
674+
675+ DWORD attr = GetFileAttributes(path2);
676+ return attr != -1;
677+}
678+
679+BOOL chooseJavaHome(char *path)
680+{
681+ // フォルダ選択ダイアログに表示するメッセージはエラーメッセージを借用する
682+ createJreSearchError();
683+
684+ BROWSEINFO bInfo = { 0 };
685+ bInfo.hwndOwner = NULL;
686+ bInfo.pidlRoot = NULL;
687+ bInfo.pszDisplayName = path;
688+ bInfo.lpszTitle = error.msg;
689+ bInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
690+
691+ LPITEMIDLIST result = NULL;
692+ while (!checkJavaExe(path))
693+ {
694+ result = SHBrowseForFolder(&bInfo);
695+ if (result == NULL)
696+ {
697+ return FALSE;
698+ }
699+
700+ SHGetPathFromIDList(result, path);
701+ }
702+ return TRUE;
703+}
704+
705+/*
706+ * Extract the executable name, returns path length.
707+ */
708+int getExePath(char* exePath)
709+{
710+ if (GetModuleFileName(hModule, exePath, _MAX_PATH) == 0)
711+ {
712+ return -1;
713+ }
714+ return strrchr(exePath, '\\') - exePath;
715+}
716+
717+/**
718+ * exeへのフルパス(*.exe)を受け取り、*.cfgにしたパスを生成する
719+ */
720+void getCfgPath(const char *exePath, char *cfgPath)
721+{
722+ strcpy(cfgPath, exePath);
723+ strcpy(cfgPath + strlen(cfgPath) - 4, ".cfg");
724+}
725+
726+void appendPath(char* basepath, const char* path)
727+{
728+ if (basepath[strlen(basepath) - 1] != '\\')
729+ {
730+ strcat(basepath, "\\");
731+ }
732+ strcat(basepath, path);
733+}
734+
735+void appendLauncher(char* jrePath)
736+{
737+ if (console)
738+ {
739+ appendPath(jrePath, "bin\\java.exe");
740+ }
741+ else
742+ {
743+ appendPath(jrePath, "bin\\javaw.exe");
744+ }
745+}
746+
747+void appendAppClasspath(char* dst, const char* src)
748+{
749+ strcat(dst, src);
750+ strcat(dst, ";");
751+}
752+
753+/**
754+ * 指定したディレクトリを親にさかのぼって指定したファイル・フォルダ名に一致する
755+ * パスを検索してdstに追記する。存在しない場合は何もしない。
756+ * @param dst 発見されたパスを追記するバッファ
757+ * @param dir 最初に指定するのはEXEへのフルパス(*.exe)を指定する。
758+ * @param name 検索する名前
759+ */
760+void findAncestor(char* dst, const char *dir, const char* name)
761+{
762+ // 親フォルダを検索
763+ char parent[MAX_PATH];
764+ strcpy(parent, dir);
765+ char *p = parent;
766+ while (*p++);
767+
768+ while (p > parent)
769+ {
770+ if (*p == '\\' || *p == '/')
771+ {
772+ if (*(p + 1))
773+ {
774+ // 現在の末尾のフォルダ区切り以外であれば、ここを末尾にする
775+ *(p + 1) = 0;
776+ break;
777+ }
778+ }
779+ p = CharPrev(parent, p);
780+ }
781+ if (strcmp(dir, parent) == 0)
782+ {
783+ // 変化なしなので、すでに検索済みのはず
784+ debug("Find End");
785+ return;
786+ }
787+
788+ // 親フォルダを列挙
789+ WIN32_FIND_DATA data = {0};
790+
791+ char searchdir[MAX_PATH];
792+ strcpy(searchdir, parent);
793+ strcat(searchdir, "*.*");
794+ debug("FindFirstFile:\t%s\n", searchdir);
795+
796+ HANDLE fh = FindFirstFile(searchdir, &data);
797+ if (fh == INVALID_HANDLE_VALUE) {
798+ debug("FindFirstFile:\tErr=%d\n", GetLastError());
799+ return;
800+ }
801+
802+ for (;;)
803+ {
804+ //debug("cFileName:\t%s\n", data.cFileName);
805+
806+ if (strcasecmp(data.cFileName, name) == 0) // 大小文字は区別しない
807+ {
808+ strcat(dst, parent);
809+ strcat(dst, data.cFileName);
810+ return;
811+ }
812+
813+ if (!FindNextFile(fh, &data))
814+ {
815+ // ERROR_NO_MORE_FILES でエラー有無の判定は、
816+ // 結局、ループを打ち切るだけなので省略。
817+ break;
818+ }
819+ }
820+ FindClose(fh);
821+ debug("FindClose:\t%s\n", parent);
822+
823+ // 更に、この親を検索する
824+ findAncestor(dst, parent, name);
825+}
826+
827+/*
828+ * Expand environment %variables%
829+ */
830+BOOL expandVars(char *dst, const char *src, const char *exePath, const int pathLen)
831+{
832+ char varName[STR] = {0};
833+ char varValue[MAX_VAR_SIZE] = {0};
834+
835+ while (strlen(src) > 0)
836+ {
837+ char *start = strchr(src, '%');
838+ if (start != NULL)
839+ {
840+ char *end = strchr(start + 1, '%');
841+ if (end == NULL)
842+ {
843+ return FALSE;
844+ }
845+ // Copy content up to %VAR%
846+ strncat(dst, src, start - src);
847+ // Insert value of %VAR%
848+ *varName = 0;
849+ strncat(varName, start + 1, end - start - 1);
850+ // Remember value start for logging
851+ char *currentVarValue = dst + strlen(dst);
852+
853+ if (strstr(varName, "FIND_ANCESTOR:") == varName)
854+ {
855+ char *findName = varName + 14;
856+ findAncestor(dst, exePath, findName);
857+ }
858+ else if (strcmp(varName, "EXEDIR") == 0)
859+ {
860+ strncat(dst, exePath, pathLen);
861+ }
862+ else if (strcmp(varName, "EXEFILE") == 0)
863+ {
864+ strcat(dst, exePath);
865+ }
866+ else if (strcmp(varName, "PWD") == 0)
867+ {
868+ GetCurrentDirectory(_MAX_PATH, dst + strlen(dst));
869+ }
870+ else if (strcmp(varName, "OLDPWD") == 0)
871+ {
872+ strcat(dst, oldPwd);
873+ }
874+ else if (strcmp(varName, "JREHOMEDIR") == 0)
875+ {
876+ strcat(dst, search.foundJavaHome);
877+ }
878+ else if (strstr(varName, HKEY_STR) == varName)
879+ {
880+ regQueryValue(varName, dst + strlen(dst), BIG_STR);
881+ }
882+ else if (strcmp(varName, "") == 0)
883+ {
884+ strcat(dst, "%");
885+ }
886+ else if (GetEnvironmentVariable(varName, varValue, MAX_VAR_SIZE) > 0)
887+ {
888+ strcat(dst, varValue);
889+ }
890+
891+ debug("Substitute:\t%s = %s\n", varName, currentVarValue);
892+ src = end + 1;
893+ }
894+ else
895+ {
896+ // Copy remaining content
897+ strcat(dst, src);
898+ break;
899+ }
900+ }
901+ return TRUE;
902+}
903+
904+void appendHeapSizes(char *dst)
905+{
906+ MEMORYSTATUSEX statex;
907+ statex.dwLength = sizeof(statex);
908+ GlobalMemoryStatusEx(&statex);
909+
910+ appendHeapSize(dst, INITIAL_HEAP_SIZE, INITIAL_HEAP_PERCENT,
911+ statex.ullAvailPhys, "-Xms");
912+ appendHeapSize(dst, MAX_HEAP_SIZE, MAX_HEAP_PERCENT,
913+ statex.ullAvailPhys, "-Xmx");
914+}
915+
916+void appendHeapSize(char *dst, const int megabytesID, const int percentID,
917+ const DWORDLONG availableMemory, const char *option)
918+{
919+ const int mb = 1048576; // 1 MB
920+ const int mbLimit32 = 1024; // Max heap size in MB on 32-bit JREs
921+ const int megabytes = loadInt(megabytesID);
922+ const int percent = loadInt(percentID);
923+ const int availableMb = availableMemory * percent / (100 * mb); // 100% * 1 MB
924+ int heapSizeMb = availableMb > megabytes ? availableMb : megabytes;
925+
926+ if (heapSizeMb > 0)
927+ {
928+ if (!(search.foundJava & KEY_WOW64_64KEY) && heapSizeMb > mbLimit32)
929+ {
930+ debug("Heap limit:\tReduced %d MB heap size to 32-bit maximum %d MB\n",
931+ heapSizeMb, mbLimit32);
932+ heapSizeMb = mbLimit32;
933+ }
934+
935+ debug("Heap %s:\tRequested %d MB / %d%%, Available: %d MB, Heap size: %d MB\n",
936+ option, megabytes, percent, (int)(availableMemory / mb), heapSizeMb);
937+ strcat(dst, option);
938+ _itoa(heapSizeMb, dst + strlen(dst), 10); // 10 -- radix
939+ strcat(dst, "m ");
940+ }
941+}
942+
943+void setJvmOptions(char *jvmOptions, const char *exePath)
944+{
945+ if (loadString(JVM_OPTIONS, jvmOptions))
946+ {
947+ strcat(jvmOptions, " ");
948+ }
949+
950+ /*
951+ * Load additional JVM options from .l4j.ini file
952+ * Options are separated by spaces or CRLF
953+ * # starts an inline comment
954+ */
955+ char iniFilePath[_MAX_PATH] = {0};
956+
957+ strncpy(iniFilePath, exePath, strlen(exePath) - 3);
958+ strcat(iniFilePath, "l4j.ini");
959+
960+ long hFile;
961+ if ((hFile = _open(iniFilePath, _O_RDONLY)) == -1)
962+ {
963+ // *.l4j.iniがなければ *.ini で試す
964+ strncpy(iniFilePath, exePath, strlen(exePath) - 3);
965+ strcat(iniFilePath, ".ini");
966+ hFile = _open(iniFilePath, _O_RDONLY);
967+ }
968+
969+ if (hFile != -1)
970+ {
971+ debug("Loading:\t%s\n", iniFilePath);
972+ const int jvmOptLen = strlen(jvmOptions);
973+ char* src = jvmOptions + jvmOptLen;
974+ char* dst = src;
975+ const int len = _read(hFile, src, MAX_ARGS - jvmOptLen - BIG_STR);
976+ BOOL copy = TRUE;
977+ int i;
978+ for (i = 0; i < len; i++, src++)
979+ {
980+ if (*src == '#')
981+ {
982+ copy = FALSE;
983+ }
984+ else if (*src == 13 || *src == 10)
985+ {
986+ copy = TRUE;
987+ if (dst > jvmOptions && *(dst - 1) != ' ')
988+ {
989+ *dst++ = ' ';
990+ }
991+ }
992+ else if (copy)
993+ {
994+ *dst++ = *src;
995+ }
996+ }
997+ *dst = 0;
998+ if (len > 0 && *(dst - 1) != ' ')
999+ {
1000+ strcat(jvmOptions, " ");
1001+ }
1002+ _close(hFile);
1003+ }
1004+}
1005+
1006+BOOL createMutex()
1007+{
1008+ char mutexName[STR] = {0};
1009+
1010+ loadString(MUTEX_NAME, mutexName);
1011+
1012+ if (*mutexName)
1013+ {
1014+ debug("Create mutex:\t%s\n", mutexName);
1015+ SECURITY_ATTRIBUTES security;
1016+ security.nLength = sizeof(SECURITY_ATTRIBUTES);
1017+ security.bInheritHandle = TRUE;
1018+ security.lpSecurityDescriptor = NULL;
1019+ CreateMutexA(&security, FALSE, mutexName);
1020+
1021+ if (GetLastError() == ERROR_ALREADY_EXISTS)
1022+ {
1023+ debug(ERROR_FORMAT, "Instance already exists.");
1024+ return FALSE;
1025+ }
1026+ }
1027+
1028+ return TRUE;
1029+}
1030+
1031+void setWorkingDirectory(const char *exePath, const int pathLen)
1032+{
1033+ char workingDir[_MAX_PATH] = {0};
1034+ char tmpPath[_MAX_PATH] = {0};
1035+
1036+ GetCurrentDirectory(_MAX_PATH, oldPwd);
1037+
1038+ if (loadString(CHDIR, tmpPath))
1039+ {
1040+ strncpy(workingDir, exePath, pathLen);
1041+ appendPath(workingDir, tmpPath);
1042+ _chdir(workingDir);
1043+ debug("Working dir:\t%s\n", workingDir);
1044+ }
1045+}
1046+
1047+BOOL cfgJreSearch(const char *exePath, int pathLen)
1048+{
1049+ char tmpPath[MAX_PATH] = { 0 };
1050+
1051+ char cfgPath[MAX_PATH] = { 0 };
1052+ getCfgPath(exePath, cfgPath);
1053+
1054+ GetPrivateProfileString("Settings", "JAVA_HOME", "", tmpPath, MAX_PATH, cfgPath);
1055+ if (strlen(tmpPath) > 0)
1056+ {
1057+ char jrePath[MAX_ARGS] = {0};
1058+ expandVars(jrePath, tmpPath, exePath, pathLen);
1059+ debug("Config JRE:\t%s\n", jrePath);
1060+
1061+ if (checkJavaExe(jrePath))
1062+ {
1063+ strcpy(launcher.cmd, jrePath);
1064+
1065+ if (isLauncherPathValid(launcher.cmd))
1066+ {
1067+ search.foundJava = wow64 ? FOUND_BUNDLED | KEY_WOW64_64KEY : FOUND_BUNDLED;
1068+ strcpy(search.foundJavaHome, launcher.cmd);
1069+ return TRUE;
1070+ }
1071+ }
1072+ }
1073+
1074+ return FALSE;
1075+}
1076+
1077+BOOL bundledJreSearch(const char *exePath, const int pathLen)
1078+{
1079+ debugAll("bundledJreSearch()\n");
1080+ char tmpPath[_MAX_PATH] = {0};
1081+ BOOL is64BitJre = loadBool(BUNDLED_JRE_64_BIT);
1082+
1083+ if (!wow64 && is64BitJre)
1084+ {
1085+ debug("Bundled JRE:\tCannot use 64-bit runtime on 32-bit OS.\n");
1086+ return FALSE;
1087+ }
1088+
1089+ if (loadString(JRE_PATH, tmpPath))
1090+ {
1091+ char jrePath[MAX_ARGS] = {0};
1092+ expandVars(jrePath, tmpPath, exePath, pathLen);
1093+ debug("Bundled JRE:\t%s\n", jrePath);
1094+
1095+ if (jrePath[0] == '\\' || jrePath[1] == ':')
1096+ {
1097+ // Absolute
1098+ strcpy(launcher.cmd, jrePath);
1099+ }
1100+ else
1101+ {
1102+ // Relative
1103+ strncpy(launcher.cmd, exePath, pathLen);
1104+ appendPath(launcher.cmd, jrePath);
1105+ }
1106+
1107+ if (isLauncherPathValid(launcher.cmd))
1108+ {
1109+ search.foundJava = is64BitJre ? FOUND_BUNDLED | KEY_WOW64_64KEY : FOUND_BUNDLED;
1110+ strcpy(search.foundJavaHome, launcher.cmd);
1111+ return TRUE;
1112+ }
1113+ }
1114+
1115+ return FALSE;
1116+}
1117+
1118+BOOL installedJreSearch()
1119+{
1120+ debugAll("installedJreSearch()\n");
1121+ return *search.javaMinVer && findJavaHome(launcher.cmd, loadInt(JDK_PREFERENCE));
1122+}
1123+
1124+void createJreSearchError()
1125+{
1126+ if (*search.javaMinVer)
1127+ {
1128+ loadString(JRE_VERSION_ERR, error.msg);
1129+ strcat(error.msg, " ");
1130+ strcat(error.msg, search.originalJavaMinVer);
1131+
1132+ if (*search.javaMaxVer)
1133+ {
1134+ strcat(error.msg, " - ");
1135+ strcat(error.msg, search.originalJavaMaxVer);
1136+ }
1137+
1138+ if (search.runtimeBits == USE_64_BIT_RUNTIME
1139+ || search.runtimeBits == USE_32_BIT_RUNTIME)
1140+ {
1141+ strcat(error.msg, " (");
1142+ strcat(error.msg, search.runtimeBits == USE_64_BIT_RUNTIME ? "64" : "32");
1143+ strcat(error.msg, "-bit)");
1144+ }
1145+
1146+ if (search.corruptedJreFound)
1147+ {
1148+ char launcherErrMsg[BIG_STR] = {0};
1149+
1150+ if (loadString(LAUNCHER_ERR, launcherErrMsg))
1151+ {
1152+ strcat(error.msg, "\n");
1153+ strcat(error.msg, launcherErrMsg);
1154+ }
1155+ }
1156+
1157+ loadString(DOWNLOAD_URL, error.url);
1158+ }
1159+ else
1160+ {
1161+ loadString(BUNDLED_JRE_ERR, error.msg);
1162+ }
1163+}
1164+
1165+BOOL jreSearch(const char *exePath, const int pathLen)
1166+{
1167+ debugAll("jreSearch()\n");
1168+ BOOL result = TRUE;
1169+
1170+ // *.cfgに前回選択のJAVA_HOMEが記録されていれば、それを優先する
1171+ // 記録されていないか、JAVA_HOMEとして妥当でなければバンドルまたはレジストリの検索を行う
1172+ if (!cfgJreSearch(exePath, pathLen))
1173+ {
1174+ search.bundledJreAsFallback = loadBool(BUNDLED_JRE_AS_FALLBACK);
1175+ loadString(JAVA_MIN_VER, search.originalJavaMinVer);
1176+ formatJavaVersion(search.javaMinVer, search.originalJavaMinVer);
1177+ debug("Java min ver:\t%s\n", search.javaMinVer);
1178+ loadString(JAVA_MAX_VER, search.originalJavaMaxVer);
1179+ formatJavaVersion(search.javaMaxVer, search.originalJavaMaxVer);
1180+ debug("Java max ver:\t%s\n", search.javaMaxVer);
1181+
1182+ if (search.bundledJreAsFallback)
1183+ {
1184+ if (!installedJreSearch())
1185+ {
1186+ result = bundledJreSearch(exePath, pathLen);
1187+ }
1188+ }
1189+ else
1190+ {
1191+ if (!bundledJreSearch(exePath, pathLen))
1192+ {
1193+ result = installedJreSearch();
1194+ }
1195+ }
1196+
1197+ if (!result)
1198+ {
1199+ // バンドルの検索とレジストリの検索も失敗した場合
1200+ // ユーザーにJAVA_HOMEの選択を求める
1201+ char jrePath[MAX_PATH] = { 0 };
1202+ if (chooseJavaHome(jrePath))
1203+ {
1204+ // JAVA_HOMEを選択した場合
1205+ search.foundJava = wow64 ? FOUND_BUNDLED | KEY_WOW64_64KEY : FOUND_BUNDLED;
1206+ strcpy(launcher.cmd, jrePath);
1207+ strcpy(search.foundJavaHome, launcher.cmd);
1208+
1209+ // 成功とみなす
1210+ result = TRUE;
1211+ }
1212+ else
1213+ {
1214+ // エラー表示の準備
1215+ createJreSearchError();
1216+ }
1217+ }
1218+ }
1219+
1220+ return result;
1221+}
1222+
1223+/*
1224+ * Append a path to the Path environment variable
1225+ */
1226+BOOL appendToPathVar(const char* path)
1227+{
1228+ char chBuf[MAX_VAR_SIZE] = {0};
1229+ const int pathSize = GetEnvironmentVariable("Path", chBuf, MAX_VAR_SIZE);
1230+
1231+ if (MAX_VAR_SIZE - pathSize - 1 < strlen(path))
1232+ {
1233+ return FALSE;
1234+ }
1235+
1236+ strcat(chBuf, ";");
1237+ strcat(chBuf, path);
1238+ return SetEnvironmentVariable("Path", chBuf);
1239+}
1240+
1241+BOOL appendJreBinToPathVar()
1242+{
1243+ // Append a path to the Path environment variable
1244+ char jreBinPath[_MAX_PATH] = {0};
1245+ strcpy(jreBinPath, launcher.cmd);
1246+ strcat(jreBinPath, "\\bin");
1247+
1248+ if (!appendToPathVar(jreBinPath))
1249+ {
1250+ debug(ERROR_FORMAT, "appendToPathVar failed.");
1251+ return FALSE;
1252+ }
1253+
1254+ return TRUE;
1255+}
1256+
1257+void setEnvironmentVariables(const char *exePath, const int pathLen)
1258+{
1259+ char tmp[MAX_ARGS] = {0};
1260+
1261+ // リソースに埋め込まれている環境変数の展開
1262+ char envVars[MAX_VAR_SIZE] = {0};
1263+ loadString(ENV_VARIABLES, envVars);
1264+ char *var = strtok(envVars, "\t");
1265+
1266+ while (var != NULL)
1267+ {
1268+ char *varValue = strchr(var, '=');
1269+ *varValue++ = 0;
1270+ *tmp = 0;
1271+ expandVars(tmp, varValue, exePath, pathLen);
1272+ debug("Set var:\t%s = %s\n", var, tmp);
1273+ SetEnvironmentVariable(var, tmp);
1274+ var = strtok(NULL, "\t");
1275+ }
1276+
1277+ // *.cfgファイルから環境変数の読み取り
1278+ char cfgPath[MAX_PATH];
1279+ getCfgPath(exePath, cfgPath);
1280+ debug("cfgPath: %s\n", cfgPath);
1281+
1282+ char envbuf[MAX_VAR_SIZE] = { 0 }; // 32kbytes
1283+ char envValue[MAX_ARGS] = { 0 };
1284+ GetPrivateProfileString("Environments", NULL, "", envbuf, sizeof(envbuf), cfgPath);
1285+
1286+ char *pEnv = envbuf;
1287+ while (*pEnv)
1288+ {
1289+ GetPrivateProfileString("Environments", pEnv, "", envValue, sizeof(envValue), cfgPath);
1290+
1291+ *tmp = 0;
1292+ expandVars(tmp, envValue, exePath, pathLen);
1293+ debug("Set var:\t%s = %s\n", pEnv, tmp);
1294+ SetEnvironmentVariable(pEnv, tmp);
1295+
1296+ while (*pEnv++);
1297+ }
1298+}
1299+
1300+void setMainClassAndClassPath(const char *exePath, const int pathLen)
1301+{
1302+ char classPath[MAX_ARGS] = {0};
1303+ char expandedClassPath[MAX_ARGS] = {0};
1304+ char jar[_MAX_PATH] = {0};
1305+ char fullFileName[_MAX_PATH] = {0};
1306+ const BOOL wrapper = loadBool(WRAPPER);
1307+ loadString(JAR, jar);
1308+
1309+ if (loadString(MAIN_CLASS, launcher.mainClass))
1310+ {
1311+ debug("Main class:\t%s\n", launcher.mainClass);
1312+
1313+ if (!loadString(CLASSPATH, classPath))
1314+ {
1315+ debug("Info:\t\tClasspath not defined.\n");
1316+ }
1317+
1318+ expandVars(expandedClassPath, classPath, exePath, pathLen);
1319+ strcat(launcher.args, "-classpath \"");
1320+
1321+ if (wrapper)
1322+ {
1323+ appendAppClasspath(launcher.args, exePath);
1324+ }
1325+ else if (*jar)
1326+ {
1327+ appendAppClasspath(launcher.args, jar);
1328+ }
1329+
1330+ // Deal with wildcards or >> strcat(launcherArgs, exp); <<
1331+ char* cp = strtok(expandedClassPath, ";");
1332+
1333+ while(cp != NULL)
1334+ {
1335+ debug("Add classpath:\t%s\n", cp);
1336+ if (strpbrk(cp, "*?") != NULL)
1337+ {
1338+ char* lastBackslash = strrchr(cp, '\\');
1339+ int pathLen = lastBackslash != NULL ? lastBackslash - cp + 1 : 0;
1340+ *fullFileName = 0;
1341+ strncpy(fullFileName, cp, pathLen);
1342+ char* fileName = fullFileName + pathLen;
1343+ *fileName = 0;
1344+ struct _finddata_t c_file;
1345+ long hFile;
1346+
1347+ if ((hFile = _findfirst(cp, &c_file)) != -1L)
1348+ {
1349+ do
1350+ {
1351+ strcpy(fileName, c_file.name);
1352+ appendAppClasspath(launcher.args, fullFileName);
1353+ debug(" \" :\t%s\n", fullFileName);
1354+ } while (_findnext(hFile, &c_file) == 0);
1355+ }
1356+
1357+ _findclose(hFile);
1358+ }
1359+ else
1360+ {
1361+ appendAppClasspath(launcher.args, cp);
1362+ }
1363+ cp = strtok(NULL, ";");
1364+ }
1365+
1366+ *(launcher.args + strlen(launcher.args) - 1) = 0;
1367+ strcat(launcher.args, "\" ");
1368+ strcat(launcher.args, launcher.mainClass);
1369+ }
1370+ else if (wrapper)
1371+ {
1372+ strcat(launcher.args, "-jar \"");
1373+ strcat(launcher.args, exePath);
1374+ strcat(launcher.args, "\"");
1375+ }
1376+ else
1377+ {
1378+ strcat(launcher.args, "-jar \"");
1379+ strncat(launcher.args, exePath, pathLen);
1380+ appendPath(launcher.args, jar);
1381+ strcat(launcher.args, "\"");
1382+ }
1383+}
1384+
1385+void setCommandLineArgs(const char *lpCmdLine,
1386+ const char *exePath, const int pathLen)
1387+{
1388+ char tmp[MAX_ARGS] = {0};
1389+
1390+ // Constant command line arguments
1391+ if (loadString(CMD_LINE, tmp))
1392+ {
1393+ char tmp2[MAX_ARGS] = {0};
1394+ expandVars(tmp2, tmp, exePath, pathLen);
1395+ debug("constant commandline args: %s\r\n", tmp2);
1396+
1397+ strcat(launcher.args, " ");
1398+ strcat(launcher.args, tmp2);
1399+ }
1400+
1401+ // Command line arguments
1402+ if (*lpCmdLine)
1403+ {
1404+ strcpy(tmp, lpCmdLine);
1405+ char* dst;
1406+ while ((dst = strstr(tmp, "--l4j-")) != NULL)
1407+ {
1408+ char* src = strchr(dst, ' ');
1409+ if (src == NULL || *(src + 1) == 0)
1410+ {
1411+ *dst = 0;
1412+ }
1413+ else
1414+ {
1415+ strcpy(dst, src + 1);
1416+ }
1417+ }
1418+ if (*tmp)
1419+ {
1420+ strcat(launcher.args, " ");
1421+ strcat(launcher.args, tmp);
1422+ }
1423+ }
1424+}
1425+
1426+int prepare(const char *lpCmdLine)
1427+{
1428+ if (!initGlobals())
1429+ {
1430+ return FALSE;
1431+ }
1432+
1433+ // Get executable path
1434+ char exePath[_MAX_PATH] = {0};
1435+ int pathLen = getExePath(exePath);
1436+
1437+ if (pathLen == -1)
1438+ {
1439+ return FALSE;
1440+ }
1441+
1442+ if (!initializeLogging(lpCmdLine, exePath, pathLen))
1443+ {
1444+ return FALSE;
1445+ }
1446+
1447+ setWow64Flag();
1448+
1449+ // Set default error message, title and optional support web site url.
1450+ loadString(ERR_TITLE, error.title);
1451+ loadString(SUPPORT_URL, error.url);
1452+
1453+ if (!loadString(STARTUP_ERR, error.msg))
1454+ {
1455+ debug(ERROR_FORMAT, "Startup error message not defined.");
1456+ return FALSE;
1457+ }
1458+
1459+ // Single instance
1460+ if (!createMutex())
1461+ {
1462+ return ERROR_ALREADY_EXISTS;
1463+ }
1464+
1465+ setWorkingDirectory(exePath, pathLen);
1466+
1467+ if (!jreSearch(exePath, pathLen))
1468+ {
1469+ return FALSE;
1470+ }
1471+
1472+ if (!appendJreBinToPathVar())
1473+ {
1474+ return FALSE;
1475+ }
1476+
1477+ setEnvironmentVariables(exePath, pathLen);
1478+ processPriority = loadInt(PRIORITY_CLASS);
1479+ appendLauncher(launcher.cmd);
1480+ appendHeapSizes(launcher.args);
1481+
1482+ char jvmOptions[MAX_ARGS] = {0};
1483+ setJvmOptions(jvmOptions, exePath);
1484+ expandVars(launcher.args, jvmOptions, exePath, pathLen);
1485+ setMainClassAndClassPath(exePath, pathLen);
1486+ setCommandLineArgs(lpCmdLine, exePath, pathLen);
1487+
1488+ debug("Launcher:\t%s\n", launcher.cmd);
1489+ debug("Launcher args:\t%s\n", launcher.args);
1490+ debug("Args length:\t%d/32768 chars\n", strlen(launcher.args));
1491+ return TRUE;
1492+}
1493+
1494+void closeProcessHandles()
1495+{
1496+ CloseHandle(processInformation.hThread);
1497+ CloseHandle(processInformation.hProcess);
1498+}
1499+
1500+BOOL execute(const BOOL wait, DWORD *dwExitCode)
1501+{
1502+ STARTUPINFO si;
1503+
1504+ memset(&processInformation, 0, sizeof(processInformation));
1505+ memset(&si, 0, sizeof(si));
1506+ si.cb = sizeof(si);
1507+
1508+ char cmdline[MAX_ARGS] = {0};
1509+ strcpy(cmdline, "\"");
1510+ strcat(cmdline, launcher.cmd);
1511+ strcat(cmdline, "\" ");
1512+ strcat(cmdline, launcher.args);
1513+
1514+ if (CreateProcess(NULL, cmdline, NULL, NULL,
1515+ TRUE, processPriority, NULL, NULL, &si, &processInformation))
1516+ {
1517+ // プロセスが起動してすぐにエラーが落ちるかどうかを見極める
1518+ WaitForInputIdle(processInformation.hProcess, 10000); // メッセージループのアイドルを待つ
1519+ WaitForSingleObject(processInformation.hProcess, 3000); // 3秒まつ
1520+
1521+ // 現時点の終了コードを得る
1522+ GetExitCodeProcess(processInformation.hProcess, dwExitCode);
1523+ debug("Java PreExitCode: %ld\n", *dwExitCode);
1524+ if (*dwExitCode == STILL_ACTIVE)
1525+ {
1526+ // まだ終了していなければ0を仮設定する
1527+ *dwExitCode = 0;
1528+ }
1529+
1530+ if (*dwExitCode == 0)
1531+ {
1532+ // 起動直後にエラーが発生しているのでなければ
1533+ // JAVA_HOMEは正しかったものとみなし、
1534+ // バンドルまたはレジストリからの検索に成功したJAVA_HOME、
1535+ // またはユーザーが選択したJAVA_HOMEを、*.cfgに保存する
1536+ // (仮に書き込み禁止等で書き込めなくても特段問題はない)
1537+ char exePath[MAX_PATH] = { 0 };
1538+ char cfgPath[MAX_PATH] = { 0 };
1539+ getExePath(exePath);
1540+ getCfgPath(exePath, cfgPath);
1541+ int saveJavaHome = GetPrivateProfileInt("Settings", "SaveJavaHome", 1, cfgPath);
1542+ if (saveJavaHome)
1543+ {
1544+ // JAVA_HOMEの保存フラグが0でなければ使用したJAVA_HOMEを記録する
1545+ WritePrivateProfileString("Settings", "JAVA_HOME", search.foundJavaHome, cfgPath);
1546+ }
1547+ }
1548+
1549+ if (wait)
1550+ {
1551+ // 終了待ちが指定されていれば子プロセス終了を待機する
1552+ WaitForSingleObject(processInformation.hProcess, INFINITE);
1553+ GetExitCodeProcess(processInformation.hProcess, dwExitCode);
1554+ }
1555+
1556+ // 待機する必要がなくなったのならハンドルは破棄しておく
1557+ closeProcessHandles();
1558+
1559+ return TRUE;
1560+ }
1561+
1562+ *dwExitCode = -1;
1563+ return FALSE;
1564+}
1565+
1566+const char* getJavaHome()
1567+{
1568+ return search.foundJavaHome;
1569+}
1570+
1571+const char* getMainClass()
1572+{
1573+ return launcher.mainClass;
1574+}
1575+
1576+const char* getLauncherArgs()
1577+{
1578+ return launcher.args;
1579+}
1580+
--- /dev/null
+++ b/src/Launch4JStub/head_src/head.h
@@ -0,0 +1,148 @@
1+/*
2+ Launch4j (http://launch4j.sourceforge.net/)
3+ Cross-platform Java application wrapper for creating Windows native executables.
4+
5+ Copyright (c) 2004, 2015 Grzegorz Kowal,
6+ Ian Roberts (jdk preference patch)
7+
8+ Permission is hereby granted, free of charge, to any person obtaining a copy
9+ of this software and associated documentation files (the "Software"), to deal
10+ in the Software without restriction, including without limitation the rights
11+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+ copies of the Software, and to permit persons to whom the Software is
13+ furnished to do so, subject to the following conditions:
14+
15+ The above copyright notice and this permission notice shall be included in
16+ all copies or substantial portions of the Software.
17+
18+ Except as contained in this notice, the name(s) of the above copyright holders
19+ shall not be used in advertising or otherwise to promote the sale, use or other
20+ dealings in this Software without prior written authorization.
21+
22+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28+ THE SOFTWARE.
29+*/
30+
31+#ifndef _WIN32_WINNT
32+#define _WIN32_WINNT 0x0501
33+#endif // _WIN32_WINNT
34+
35+#ifndef _LAUNCH4J_HEAD__INCLUDED_
36+#define _LAUNCH4J_HEAD__INCLUDED_
37+
38+#define WIN32_LEAN_AND_MEAN // VC - Exclude rarely-used stuff from Windows headers
39+
40+// Windows Header Files:
41+#include <windows.h>
42+#include <shlobj.h>
43+
44+// C RunTime Header Files
45+#include <stdlib.h>
46+#include <malloc.h>
47+#include <memory.h>
48+#include <tchar.h>
49+#include <shellapi.h>
50+#include <direct.h>
51+#include <fcntl.h>
52+#include <stdio.h>
53+#include <sys/stat.h>
54+#include <io.h>
55+#include <process.h>
56+#include <locale.h>
57+
58+#define LAUNCH4j "Launch4j"
59+#define VERSION "3.12"
60+
61+#define JRE_VER_MAX_DIGITS_PER_PART 3
62+
63+#define NO_JAVA_FOUND 0
64+#define FOUND_JRE 1
65+#define FOUND_SDK 2
66+#define FOUND_BUNDLED 4
67+
68+#define JRE_ONLY 0
69+#define PREFER_JRE 1
70+#define PREFER_JDK 2
71+#define JDK_ONLY 3
72+
73+#define USE_64_BIT_RUNTIME 1
74+#define USE_64_AND_32_BIT_RUNTIME 2
75+#define USE_32_AND_64_BIT_RUNTIME 3
76+#define USE_32_BIT_RUNTIME 4
77+#define INIT_RUNTIME_BITS 9
78+
79+#define KEY_WOW64_64KEY 0x0100
80+
81+#define HKEY_STR "HKEY"
82+#define HKEY_CLASSES_ROOT_STR "HKEY_CLASSES_ROOT"
83+#define HKEY_CURRENT_USER_STR "HKEY_CURRENT_USER"
84+#define HKEY_LOCAL_MACHINE_STR "HKEY_LOCAL_MACHINE"
85+#define HKEY_USERS_STR "HKEY_USERS"
86+#define HKEY_CURRENT_CONFIG_STR "HKEY_CURRENT_CONFIG"
87+
88+#define STR 128
89+#define BIG_STR 1024
90+#define MAX_VAR_SIZE 32767
91+#define MAX_ARGS 32768
92+
93+#define TRUE_STR "true"
94+#define FALSE_STR "false"
95+
96+#define ERROR_FORMAT "Error:\t\t%s\n"
97+#define debug(args...) if (hLog != NULL) fprintf(hLog, ## args);
98+#define debugAll(args...) if (debugAll && hLog != NULL) fprintf(hLog, ## args);
99+
100+typedef void (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
101+
102+BOOL initGlobals();
103+FILE* openLogFile(const char* exePath, const int pathLen);
104+void closeLogFile();
105+BOOL initializeLogging(const char *lpCmdLine, const char* exePath, const int pathLen);
106+void msgBox(const char* text);
107+void signalError();
108+BOOL loadString(const int resID, char* buffer);
109+BOOL loadBool(const int resID);
110+int loadInt(const int resID);
111+BOOL regQueryValue(const char* regPath, unsigned char* buffer,
112+ unsigned long bufferLength);
113+void formatJavaVersion(char* version, const char* originalVersion);
114+void regSearch(const char* keyName, const int searchType);
115+BOOL isJavaHomeValid(const char* keyName, const int searchType);
116+BOOL isLauncherPathValid(const char* path);
117+void regSearchWow(const char* keyName, const int searchType);
118+void regSearchJreSdk(const char* jreKeyName, const char* sdkKeyName,
119+ const int jdkPreference);
120+BOOL findJavaHome(char* path, const int jdkPreference);
121+int getExePath(char* exePath);
122+void appendPath(char* basepath, const char* path);
123+void appendLauncher(char* jrePath);
124+void appendAppClasspath(char* dst, const char* src);
125+BOOL expandVars(char *dst, const char *src, const char *exePath, const int pathLen);
126+void appendHeapSizes(char *dst);
127+void appendHeapSize(char *dst, const int megabytesID, const int percentID,
128+ const DWORDLONG availableMemory, const char *option);
129+void setJvmOptions(char *jvmOptions, const char *exePath);
130+BOOL createMutex();
131+void setWorkingDirectory(const char *exePath, const int pathLen);
132+BOOL bundledJreSearch(const char *exePath, const int pathLen);
133+BOOL installedJreSearch();
134+void createJreSearchError();
135+BOOL jreSearch(const char *exePath, const int pathLen);
136+BOOL appendToPathVar(const char* path);
137+BOOL appendJreBinToPathVar();
138+void setEnvironmentVariables(const char *exePath, const int pathLen);
139+void setMainClassAndClassPath(const char *exePath, const int pathLen);
140+void setCommandLineArgs(const char *lpCmdLine, const char *exePath, const int pathLen);
141+int prepare(const char *lpCmdLine);
142+void closeProcessHandles();
143+BOOL execute(const BOOL wait, DWORD *dwExitCode);
144+const char* getJavaHome();
145+const char* getMainClass();
146+const char* getLauncherArgs();
147+
148+#endif // _LAUNCH4J_HEAD__INCLUDED_
--- /dev/null
+++ b/src/Launch4JStub/head_src/jniconsolehead_BETA/.gitignore
@@ -0,0 +1,2 @@
1+/jniconsolehead.exe
2+/jniconsolehead.layout
--- /dev/null
+++ b/src/Launch4JStub/head_src/jniconsolehead_BETA/Makefile.win
@@ -0,0 +1,34 @@
1+# Project: jniconsolehead
2+# Makefile created by Dev-C++ 5.7.1
3+
4+CPP = g++.exe
5+CC = gcc.exe
6+WINDRES = windres.exe
7+OBJ = ../../head_jni_BETA/jniconsolehead.o ../../head_jni_BETA/head.o ../../head_jni_BETA/jnihead.o
8+LINKOBJ = ../../head_jni_BETA/jniconsolehead.o ../../head_jni_BETA/head.o ../../head_jni_BETA/jnihead.o
9+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
10+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"
11+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"
12+BIN = jniconsolehead.exe
13+CXXFLAGS = $(CXXINCS) -Os
14+CFLAGS = $(INCS) -Os
15+RM = rm.exe -f
16+
17+.PHONY: all all-before all-after clean clean-custom
18+
19+all: all-before $(BIN) all-after
20+
21+clean: clean-custom
22+ ${RM} $(OBJ) $(BIN)
23+
24+$(BIN): $(OBJ)
25+ $(CC) $(LINKOBJ) -o $(BIN) $(LIBS)
26+
27+../../head_jni_BETA/jniconsolehead.o: jniconsolehead.c
28+ $(CC) -c jniconsolehead.c -o ../../head_jni_BETA/jniconsolehead.o $(CFLAGS)
29+
30+../../head_jni_BETA/head.o: ../head.c
31+ $(CC) -c ../head.c -o ../../head_jni_BETA/head.o $(CFLAGS)
32+
33+../../head_jni_BETA/jnihead.o: ../jnihead.c
34+ $(CC) -c ../jnihead.c -o ../../head_jni_BETA/jnihead.o $(CFLAGS)
--- /dev/null
+++ b/src/Launch4JStub/head_src/jniconsolehead_BETA/jniconsolehead.c
@@ -0,0 +1,99 @@
1+/*
2+ Launch4j (http://launch4j.sourceforge.net/)
3+ Cross-platform Java application wrapper for creating Windows native executables.
4+
5+ Copyright (c) 2004, 2007 Grzegorz Kowal
6+
7+ Permission is hereby granted, free of charge, to any person obtaining a copy
8+ of this software and associated documentation files (the "Software"), to deal
9+ in the Software without restriction, including without limitation the rights
10+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+ copies of the Software, and to permit persons to whom the Software is
12+ furnished to do so, subject to the following conditions:
13+
14+ The above copyright notice and this permission notice shall be included in
15+ all copies or substantial portions of the Software.
16+
17+ Except as contained in this notice, the name(s) of the above copyright holders
18+ shall not be used in advertising or otherwise to promote the sale, use or other
19+ dealings in this Software without prior written authorization.
20+
21+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27+ THE SOFTWARE.
28+*/
29+
30+#include "../resource.h"
31+#include "../head.h"
32+#include "../jnihead.h"
33+
34+extern FILE* hLog;
35+
36+BOOL restartOnCrash = FALSE;
37+
38+int main(int argc, char* argv[])
39+{
40+ setConsoleFlag();
41+ LPTSTR cmdLine = GetCommandLine();
42+
43+ if (*cmdLine == '"')
44+ {
45+ if (*(cmdLine = strchr(cmdLine + 1, '"') + 1))
46+ {
47+ cmdLine++;
48+ }
49+ }
50+ else if ((cmdLine = strchr(cmdLine, ' ')) != NULL)
51+ {
52+ cmdLine++;
53+ }
54+ else
55+ {
56+ cmdLine = "";
57+ }
58+
59+ int result = prepare(cmdLine);
60+
61+ if (result == ERROR_ALREADY_EXISTS)
62+ {
63+ char errMsg[BIG_STR] = {0};
64+ loadString(INSTANCE_ALREADY_EXISTS_MSG, errMsg);
65+ msgBox(errMsg);
66+ closeLogFile();
67+ return 2;
68+ }
69+
70+ if (result != TRUE)
71+ {
72+ signalError();
73+ return 1;
74+ }
75+
76+ restartOnCrash = loadBool(RESTART_ON_CRASH);
77+ DWORD dwExitCode;
78+
79+ do
80+ {
81+ dwExitCode = 0;
82+ saveJvmOptions(getJavaHome(), getMainClass(), getLauncherArgs());
83+
84+ if (!executeVm(&dwExitCode))
85+ {
86+ signalError();
87+ break;
88+ }
89+
90+ if (restartOnCrash && dwExitCode != 0)
91+ {
92+ debug("Exit code:\t%d, restarting the application!\n", dwExitCode);
93+ }
94+ } while (restartOnCrash && dwExitCode != 0);
95+
96+ debug("Exit code:\t%d\n", dwExitCode);
97+ closeLogFile();
98+ return (int) dwExitCode;
99+}
--- /dev/null
+++ b/src/Launch4JStub/head_src/jniconsolehead_BETA/jniconsolehead.dev
@@ -0,0 +1,112 @@
1+[Project]
2+FileName=jniconsolehead.dev
3+Name=jniconsolehead
4+UnitCount=6
5+Type=1
6+Ver=2
7+ObjFiles=
8+Includes="C:\Program Files (x86)\Java\jdk 1.4\include";"C:\Program Files (x86)\Java\jdk 1.4\include\win32"
9+Libs=
10+PrivateResource=
11+ResourceIncludes=
12+MakeIncludes=
13+Compiler=
14+CppCompiler=
15+Linker=-n_@@_
16+IsCpp=0
17+Icon=
18+ExeOutput=
19+ObjectOutput=..\..\head_jni_BETA
20+OverrideOutput=0
21+OverrideOutputName=jniconsolehead.exe
22+HostApplication=
23+Folders=
24+CommandLine=
25+UseCustomMakefile=0
26+CustomMakefile=Makefile.win
27+IncludeVersionInfo=0
28+SupportXPThemes=0
29+CompilerSet=0
30+CompilerSettings=000000d000000000000001000
31+LogOutput=
32+LogOutputEnabled=0
33+
34+[Unit1]
35+FileName=jniconsolehead.c
36+CompileCpp=0
37+Folder=jniconsolehead
38+Compile=1
39+Link=1
40+Priority=1000
41+OverrideBuildCmd=0
42+BuildCmd=
43+
44+[VersionInfo]
45+Major=0
46+Minor=1
47+Release=1
48+Build=1
49+LanguageID=1033
50+CharsetID=1252
51+CompanyName=
52+FileVersion=0.1.1.1
53+FileDescription=Developed using the Dev-C++ IDE
54+InternalName=
55+LegalCopyright=
56+LegalTrademarks=
57+OriginalFilename=
58+ProductName=
59+ProductVersion=
60+AutoIncBuildNr=0
61+SyncProduct=0
62+
63+[Unit2]
64+FileName=..\resource.h
65+CompileCpp=0
66+Folder=jniconsolehead
67+Compile=1
68+Link=1
69+Priority=1000
70+OverrideBuildCmd=0
71+BuildCmd=
72+
73+[Unit3]
74+FileName=..\head.c
75+CompileCpp=0
76+Folder=jniconsolehead
77+Compile=1
78+Link=1
79+Priority=1000
80+OverrideBuildCmd=0
81+BuildCmd=
82+
83+[Unit4]
84+FileName=..\head.h
85+CompileCpp=0
86+Folder=jniconsolehead
87+Compile=1
88+Link=1
89+Priority=1000
90+OverrideBuildCmd=0
91+BuildCmd=
92+
93+[Unit5]
94+FileName=..\jnihead.h
95+Folder=jniconsolehead
96+Compile=1
97+Link=1
98+Priority=1000
99+OverrideBuildCmd=0
100+BuildCmd=
101+CompileCpp=0
102+
103+[Unit6]
104+FileName=..\jnihead.c
105+CompileCpp=0
106+Folder=jniconsolehead
107+Compile=1
108+Link=1
109+Priority=1000
110+OverrideBuildCmd=0
111+BuildCmd=
112+
--- /dev/null
+++ b/src/Launch4JStub/head_src/jniguihead_BETA/.gitignore
@@ -0,0 +1,2 @@
1+/jniguihead.exe
2+/jniguihead.layout
--- /dev/null
+++ b/src/Launch4JStub/head_src/jniguihead_BETA/Makefile.win
@@ -0,0 +1,34 @@
1+# Project: jniguihead
2+# Makefile created by Dev-C++ 5.7.1
3+
4+CPP = g++.exe
5+CC = gcc.exe
6+WINDRES = windres.exe
7+OBJ = ../../head_jni_BETA/jniguihead.o ../../head_jni_BETA/head.o ../../head_jni_BETA/jnihead.o
8+LINKOBJ = ../../head_jni_BETA/jniguihead.o ../../head_jni_BETA/head.o ../../head_jni_BETA/jnihead.o
9+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
10+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"
11+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"
12+BIN = jniguihead.exe
13+CXXFLAGS = $(CXXINCS) -Os
14+CFLAGS = $(INCS) -Os
15+RM = rm.exe -f
16+
17+.PHONY: all all-before all-after clean clean-custom
18+
19+all: all-before $(BIN) all-after
20+
21+clean: clean-custom
22+ ${RM} $(OBJ) $(BIN)
23+
24+$(BIN): $(OBJ)
25+ $(CC) $(LINKOBJ) -o $(BIN) $(LIBS)
26+
27+../../head_jni_BETA/jniguihead.o: jniguihead.c
28+ $(CC) -c jniguihead.c -o ../../head_jni_BETA/jniguihead.o $(CFLAGS)
29+
30+../../head_jni_BETA/head.o: ../head.c
31+ $(CC) -c ../head.c -o ../../head_jni_BETA/head.o $(CFLAGS)
32+
33+../../head_jni_BETA/jnihead.o: ../jnihead.c
34+ $(CC) -c ../jnihead.c -o ../../head_jni_BETA/jnihead.o $(CFLAGS)
--- /dev/null
+++ b/src/Launch4JStub/head_src/jniguihead_BETA/jniguihead.c
@@ -0,0 +1,244 @@
1+/*
2+ Launch4j (http://launch4j.sourceforge.net/)
3+ Cross-platform Java application wrapper for creating Windows native executables.
4+
5+ Copyright (c) 2004, 2015 Grzegorz Kowal
6+ Sylvain Mina (single instance patch)
7+
8+ Permission is hereby granted, free of charge, to any person obtaining a copy
9+ of this software and associated documentation files (the "Software"), to deal
10+ in the Software without restriction, including without limitation the rights
11+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+ copies of the Software, and to permit persons to whom the Software is
13+ furnished to do so, subject to the following conditions:
14+
15+ The above copyright notice and this permission notice shall be included in
16+ all copies or substantial portions of the Software.
17+
18+ Except as contained in this notice, the name(s) of the above copyright holders
19+ shall not be used in advertising or otherwise to promote the sale, use or other
20+ dealings in this Software without prior written authorization.
21+
22+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28+ THE SOFTWARE.
29+*/
30+
31+#include "../resource.h"
32+#include "../head.h"
33+#include "../jnihead.h"
34+#include "jniguihead.h"
35+
36+extern FILE* hLog;
37+extern PROCESS_INFORMATION processInformation;
38+
39+HWND hWnd;
40+DWORD dwExitCode = 0;
41+BOOL stayAlive = FALSE;
42+BOOL splash = FALSE;
43+BOOL splashTimeoutErr;
44+BOOL waitForWindow;
45+BOOL restartOnCrash = FALSE;
46+int splashTimeout = DEFAULT_SPLASH_TIMEOUT;
47+
48+int APIENTRY WinMain(HINSTANCE hInstance,
49+ HINSTANCE hPrevInstance,
50+ LPSTR lpCmdLine,
51+ int nCmdShow)
52+{
53+ int result = prepare(lpCmdLine);
54+
55+ if (result == ERROR_ALREADY_EXISTS)
56+ {
57+ HWND handle = getInstanceWindow();
58+ ShowWindow(handle, SW_SHOW);
59+ SetForegroundWindow(handle);
60+ closeLogFile();
61+ return 2;
62+ }
63+
64+ if (result != TRUE)
65+ {
66+ signalError();
67+ return 1;
68+ }
69+
70+ splash = loadBool(SHOW_SPLASH)
71+ && strstr(lpCmdLine, "--l4j-no-splash") == NULL;
72+ restartOnCrash = loadBool(RESTART_ON_CRASH);
73+
74+ // if we should restart on crash, we must also stay alive to check for crashes
75+ stayAlive = restartOnCrash ||
76+ (loadBool(GUI_HEADER_STAYS_ALIVE)
77+ && strstr(lpCmdLine, "--l4j-dont-wait") == NULL);
78+
79+ if (splash || stayAlive)
80+ {
81+ hWnd = CreateWindowEx(WS_EX_TOOLWINDOW, "STATIC", "",
82+ WS_POPUP | SS_BITMAP,
83+ 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
84+ if (splash)
85+ {
86+ char timeout[10] = {0};
87+ if (loadString(SPLASH_TIMEOUT, timeout))
88+ {
89+ splashTimeout = atoi(timeout);
90+ if (splashTimeout <= 0 || splashTimeout > MAX_SPLASH_TIMEOUT)
91+ {
92+ splashTimeout = DEFAULT_SPLASH_TIMEOUT;
93+ }
94+ }
95+ splashTimeoutErr = loadBool(SPLASH_TIMEOUT_ERR)
96+ && strstr(lpCmdLine, "--l4j-no-splash-err") == NULL;
97+ waitForWindow = loadBool(SPLASH_WAITS_FOR_WINDOW);
98+ HANDLE hImage = LoadImage(hInstance, // handle of the instance containing the image
99+ MAKEINTRESOURCE(SPLASH_BITMAP), // name or identifier of image
100+ IMAGE_BITMAP, // type of image
101+ 0, // desired width
102+ 0, // desired height
103+ LR_DEFAULTSIZE);
104+ if (hImage == NULL)
105+ {
106+ signalError();
107+ return 1;
108+ }
109+ SendMessage(hWnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hImage);
110+ RECT rect;
111+ GetWindowRect(hWnd, &rect);
112+ int x = (GetSystemMetrics(SM_CXSCREEN) - (rect.right - rect.left)) / 2;
113+ int y = (GetSystemMetrics(SM_CYSCREEN) - (rect.bottom - rect.top)) / 2;
114+ SetWindowPos(hWnd, HWND_TOP, x, y, 0, 0, SWP_NOSIZE);
115+ ShowWindow(hWnd, nCmdShow);
116+ UpdateWindow (hWnd);
117+ }
118+ }
119+
120+ do
121+ {
122+ if (splash || stayAlive)
123+ {
124+ if (!SetTimer (hWnd, ID_TIMER, 1000 /* 1s */, TimerProc))
125+ {
126+ signalError();
127+ return 1;
128+ }
129+ }
130+
131+ debug(getJavaHome());
132+ saveJvmOptions(getJavaHome(), getMainClass(), getLauncherArgs());
133+
134+ if (!executeVm(&dwExitCode))
135+ {
136+ signalError();
137+ return 1;
138+ }
139+
140+ if (!(splash || stayAlive))
141+ {
142+ debug("Exit code:\t0\n");
143+ closeProcessHandles();
144+ closeLogFile();
145+ return 0;
146+ }
147+
148+ MSG msg;
149+ while (GetMessage(&msg, NULL, 0, 0))
150+ {
151+ TranslateMessage(&msg);
152+ DispatchMessage(&msg);
153+ }
154+
155+ if (restartOnCrash && dwExitCode != 0)
156+ {
157+ debug("Exit code:\t%d, restarting the application!\n", dwExitCode);
158+ }
159+
160+ closeProcessHandles();
161+ } while (restartOnCrash && dwExitCode != 0);
162+
163+ debug("Exit code:\t%d\n", dwExitCode);
164+ closeLogFile();
165+ return dwExitCode;
166+}
167+
168+HWND getInstanceWindow()
169+{
170+ char windowTitle[STR];
171+ char instWindowTitle[STR] = {0};
172+ if (loadString(INSTANCE_WINDOW_TITLE, instWindowTitle))
173+ {
174+ HWND handle = FindWindowEx(NULL, NULL, NULL, NULL);
175+ while (handle != NULL)
176+ {
177+ GetWindowText(handle, windowTitle, STR - 1);
178+ if (strstr(windowTitle, instWindowTitle) != NULL)
179+ {
180+ return handle;
181+ }
182+ else
183+ {
184+ handle = FindWindowEx(NULL, handle, NULL, NULL);
185+ }
186+ }
187+ }
188+ return NULL;
189+}
190+
191+BOOL CALLBACK enumwndfn(HWND hwnd, LPARAM lParam)
192+{
193+ DWORD processId;
194+ GetWindowThreadProcessId(hwnd, &processId);
195+ if (processInformation.dwProcessId == processId)
196+ {
197+ LONG styles = GetWindowLong(hwnd, GWL_STYLE);
198+ if ((styles & WS_VISIBLE) != 0)
199+ {
200+ splash = FALSE;
201+ ShowWindow(hWnd, SW_HIDE);
202+ return FALSE;
203+ }
204+ }
205+ return TRUE;
206+}
207+
208+VOID CALLBACK TimerProc(
209+ HWND hwnd, // handle of window for timer messages
210+ UINT uMsg, // WM_TIMER message
211+ UINT idEvent, // timer identifier
212+ DWORD dwTime) // current system time
213+{
214+ if (splash)
215+ {
216+ if (splashTimeout == 0)
217+ {
218+ splash = FALSE;
219+ ShowWindow(hWnd, SW_HIDE);
220+ if (waitForWindow && splashTimeoutErr)
221+ {
222+ KillTimer(hwnd, ID_TIMER);
223+ signalError();
224+ PostQuitMessage(0);
225+ }
226+ }
227+ else
228+ {
229+ splashTimeout--;
230+ if (waitForWindow)
231+ {
232+ EnumWindows(enumwndfn, 0);
233+ }
234+ }
235+ }
236+
237+ GetExitCodeProcess(processInformation.hProcess, &dwExitCode);
238+ if (dwExitCode != STILL_ACTIVE
239+ || !(splash || stayAlive))
240+ {
241+ KillTimer(hWnd, ID_TIMER);
242+ PostQuitMessage(0);
243+ }
244+}
--- /dev/null
+++ b/src/Launch4JStub/head_src/jniguihead_BETA/jniguihead.dev
@@ -0,0 +1,122 @@
1+[Project]
2+FileName=jniguihead.dev
3+Name=jniguihead
4+UnitCount=7
5+Type=0
6+Ver=2
7+ObjFiles=
8+Includes="C:\Program Files (x86)\Java\jdk 1.4\include";"C:\Program Files (x86)\Java\jdk 1.4\include\win32"
9+Libs=
10+PrivateResource=
11+ResourceIncludes=
12+MakeIncludes=
13+Compiler=
14+CppCompiler=
15+Linker=-n_@@_
16+IsCpp=0
17+Icon=
18+ExeOutput=
19+ObjectOutput=..\..\head_jni_BETA
20+OverrideOutput=0
21+OverrideOutputName=jniguihead.exe
22+HostApplication=
23+Folders=
24+CommandLine=
25+UseCustomMakefile=0
26+CustomMakefile=Makefile.win
27+IncludeVersionInfo=0
28+SupportXPThemes=0
29+CompilerSet=0
30+CompilerSettings=000000d000000000000001000
31+LogOutput=
32+LogOutputEnabled=0
33+
34+[Unit1]
35+FileName=jniguihead.c
36+CompileCpp=0
37+Folder=jniguihead_BETA
38+Compile=1
39+Link=1
40+Priority=1000
41+OverrideBuildCmd=0
42+BuildCmd=$(CC) -c jniguihead.c -o ../../head_jni_BETA/jniguihead.o $(CFLAGS)
43+
44+[Unit2]
45+FileName=jniguihead.h
46+CompileCpp=0
47+Folder=jniguihead_BETA
48+Compile=1
49+Link=1
50+Priority=1000
51+OverrideBuildCmd=0
52+BuildCmd=
53+
54+[VersionInfo]
55+Major=0
56+Minor=1
57+Release=1
58+Build=1
59+LanguageID=1033
60+CharsetID=1252
61+CompanyName=
62+FileVersion=0.1.1.1
63+FileDescription=Developed using the Dev-C++ IDE
64+InternalName=
65+LegalCopyright=
66+LegalTrademarks=
67+OriginalFilename=
68+ProductName=
69+ProductVersion=
70+AutoIncBuildNr=0
71+SyncProduct=0
72+
73+[Unit4]
74+FileName=..\head.h
75+CompileCpp=0
76+Folder=jniguihead_BETA
77+Compile=1
78+Link=1
79+Priority=1000
80+OverrideBuildCmd=0
81+BuildCmd=
82+
83+[Unit6]
84+FileName=..\jnihead.c
85+CompileCpp=0
86+Folder=jniguihead_BETA
87+Compile=1
88+Link=1
89+Priority=1000
90+OverrideBuildCmd=0
91+BuildCmd=
92+
93+[Unit3]
94+FileName=..\head.c
95+CompileCpp=0
96+Folder=jniguihead_BETA
97+Compile=1
98+Link=1
99+Priority=1000
100+OverrideBuildCmd=0
101+BuildCmd=$(CC) -c head.c -o ../../head/head.o $(CFLAGS)
102+
103+[Unit5]
104+FileName=..\resource.h
105+CompileCpp=0
106+Folder=jniguihead_BETA
107+Compile=1
108+Link=1
109+Priority=1000
110+OverrideBuildCmd=0
111+BuildCmd=
112+
113+[Unit7]
114+FileName=..\jnihead.h
115+CompileCpp=0
116+Folder=jniguihead_BETA
117+Compile=1
118+Link=1
119+Priority=1000
120+OverrideBuildCmd=0
121+BuildCmd=
122+
--- /dev/null
+++ b/src/Launch4JStub/head_src/jniguihead_BETA/jniguihead.h
@@ -0,0 +1,43 @@
1+/*
2+ Launch4j (http://launch4j.sourceforge.net/)
3+ Cross-platform Java application wrapper for creating Windows native executables.
4+
5+ Copyright (c) 2004, 2007 Grzegorz Kowal
6+
7+ Permission is hereby granted, free of charge, to any person obtaining a copy
8+ of this software and associated documentation files (the "Software"), to deal
9+ in the Software without restriction, including without limitation the rights
10+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+ copies of the Software, and to permit persons to whom the Software is
12+ furnished to do so, subject to the following conditions:
13+
14+ The above copyright notice and this permission notice shall be included in
15+ all copies or substantial portions of the Software.
16+
17+ Except as contained in this notice, the name(s) of the above copyright holders
18+ shall not be used in advertising or otherwise to promote the sale, use or other
19+ dealings in this Software without prior written authorization.
20+
21+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27+ THE SOFTWARE.
28+*/
29+
30+#define ID_TIMER 1
31+#define DEFAULT_SPLASH_TIMEOUT 60 /* 60 seconds */
32+#define MAX_SPLASH_TIMEOUT 60 * 15 /* 15 minutes */
33+
34+HWND getInstanceWindow();
35+
36+BOOL CALLBACK enumwndfn(HWND hwnd, LPARAM lParam);
37+
38+VOID CALLBACK TimerProc(
39+ HWND hwnd, // handle of window for timer messages
40+ UINT uMsg, // WM_TIMER message
41+ UINT idEvent, // timer identifier
42+ DWORD dwTime // current system time
43+);
--- /dev/null
+++ b/src/Launch4JStub/head_src/jnihead.c
@@ -0,0 +1,284 @@
1+/*
2+ Launch4j (http://launch4j.sourceforge.net/)
3+ Cross-platform Java application wrapper for creating Windows native executables.
4+
5+ Copyright (c) 2007 Ryan Rusaw
6+
7+ Permission is hereby granted, free of charge, to any person obtaining a copy
8+ of this software and associated documentation files (the "Software"), to deal
9+ in the Software without restriction, including without limitation the rights
10+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+ copies of the Software, and to permit persons to whom the Software is
12+ furnished to do so, subject to the following conditions:
13+
14+ The above copyright notice and this permission notice shall be included in
15+ all copies or substantial portions of the Software.
16+
17+ Except as contained in this notice, the name(s) of the above copyright holders
18+ shall not be used in advertising or otherwise to promote the sale, use or other
19+ dealings in this Software without prior written authorization.
20+
21+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27+ THE SOFTWARE.
28+*/
29+
30+#include "jnihead.h"
31+
32+/* Java Invocation API stuff */
33+typedef jint (JNICALL CreateJavaVM_t)(JavaVM **pvm, void **env, void *args);
34+JavaVM* g_pJavaVM = NULL;
35+JNIEnv* g_pJNIEnv = NULL;
36+JavaVMInitArgs g_sJavaVMInitArgs;
37+char g_rgcMnClsArgs[MAX_ARGS] = {0};
38+char g_rgcMnCls[_MAX_PATH] = {0};
39+char g_rgcCurrJrePth[_MAX_PATH] = {0};
40+HINSTANCE g_hInstance;
41+const char* g_pcSep = " \t\f\r\n\v";
42+
43+int getArgCount(const char* pcArgStr)
44+{
45+ const char *pCopy;
46+ int iArgCnt= 0;
47+ int bInWtSpc = 1;
48+ for(pCopy = pcArgStr; *pCopy; pCopy++)
49+ {
50+ if (!isspace(*pCopy) && bInWtSpc)
51+ {
52+ iArgCnt++;
53+ }
54+ bInWtSpc = isspace(*pCopy);
55+ }
56+ return iArgCnt;
57+}
58+
59+void saveJvmOptions(const char *jrePath, const char *mainClass, const char *pcOpts)
60+{
61+ strcpy(g_rgcCurrJrePth, jrePath);
62+ strcpy(g_rgcMnCls, mainClass);
63+
64+ char rgcOptCpy[MAX_ARGS] = {0};
65+ int iArgCnt = 0, iCurrArg = 0, iSkipArgCnt = 0;
66+ char *pcCurrOpt;
67+ char **prgcVmArgs = NULL;
68+ strncpy(rgcOptCpy, pcOpts, MAX_ARGS - 1);
69+
70+
71+ iArgCnt = getArgCount(rgcOptCpy);
72+ if (iArgCnt > 0)
73+ {
74+ /* Allocate iArgCnt char pointers */
75+ prgcVmArgs = malloc(iArgCnt * sizeof(char *));
76+ for (pcCurrOpt = strtok(rgcOptCpy, g_pcSep); pcCurrOpt; pcCurrOpt = strtok(NULL, g_pcSep), iCurrArg++)
77+ {
78+ /* Use the allocated pointers to make an array of substrings */
79+ prgcVmArgs[iCurrArg] = pcCurrOpt;
80+ }
81+ /* Allocat iArgCnt JavaVMOptions for the g_sJavaVMInitArgs struct */
82+ g_sJavaVMInitArgs.options = malloc(iArgCnt * sizeof(JavaVMOption));
83+ memset(g_sJavaVMInitArgs.options, 0, iArgCnt * sizeof(JavaVMOption));
84+ char* rgcClsPth = 0;
85+ /* Copy the tokenized array into the allocated JavaVMOption array,
86+ * with some special handling for classpath related arguments */
87+ for (iCurrArg = 0; iCurrArg < iArgCnt; iCurrArg++)
88+ {
89+ if ((strcmp(prgcVmArgs[iCurrArg], "-classpath") == 0) ||
90+ (strcmp(prgcVmArgs[iCurrArg], "-jar") == 0))
91+ {
92+ iCurrArg++;
93+ iSkipArgCnt++;
94+ if (iCurrArg < iArgCnt)
95+ {
96+ int iOffset = *prgcVmArgs[iCurrArg] == '"' ? 1 : 0;
97+ char rgcTmp[MAX_ARGS] = {0};
98+ /* Remove leading and trailing "'s */\
99+ strncpy(rgcTmp, prgcVmArgs[iCurrArg] + iOffset,
100+ strlen(prgcVmArgs[iCurrArg]) - iOffset);
101+ if (rgcTmp[strlen(rgcTmp)-1] == '"')
102+ rgcTmp[strlen(rgcTmp)-1] = '\0';
103+ /* If we haven't defined a classpath yet start one, otherwise
104+ * we just append the this classpath to it */
105+ if (!rgcClsPth)
106+ {
107+ rgcClsPth = malloc(MAX_ARGS * sizeof(char));
108+ memset(rgcClsPth, 0, MAX_ARGS * sizeof(char));
109+ sprintf(rgcClsPth,"-Djava.class.path=%s", rgcTmp);
110+ g_sJavaVMInitArgs.options[iCurrArg - iSkipArgCnt].optionString = rgcClsPth;
111+ }
112+ else
113+ {
114+ iSkipArgCnt++;
115+ strcat(rgcClsPth,";");
116+ strcat(rgcClsPth,rgcTmp);
117+ }
118+
119+ }
120+ }
121+ else
122+ {
123+ g_sJavaVMInitArgs.options[iCurrArg - iSkipArgCnt].optionString
124+ = malloc(strlen(prgcVmArgs[iCurrArg]) + 1);
125+ strcpy(g_sJavaVMInitArgs.options[iCurrArg - iSkipArgCnt].optionString,
126+ prgcVmArgs[iCurrArg]);
127+ }
128+ }
129+ g_sJavaVMInitArgs.nOptions = iArgCnt - iSkipArgCnt;
130+ /* Free the malloc'd memory, we dont want to leak */
131+ free(prgcVmArgs);
132+ }
133+}
134+
135+JNIEnv* createVm()
136+{
137+ int iRetVal;
138+ CreateJavaVM_t *pfnCreateJavaVM;
139+ char rgcLibPth[_MAX_PATH + 18];
140+ // sprintf(rgcLibPth, "%s\\bin\\client\\jvm.dll", g_rgcCurrJrePth); // TODO - could be client or server
141+ sprintf(rgcLibPth, "%s\\bin\\client\\jvm.dll", g_rgcCurrJrePth);
142+
143+ /* Get a handle to the jvm dll */
144+ if ((g_hInstance = LoadLibrary(rgcLibPth)) == NULL)
145+ {
146+ return NULL;
147+ }
148+
149+ /* Get the CreateJavaVM() function */
150+ pfnCreateJavaVM = (CreateJavaVM_t *)GetProcAddress(g_hInstance, "JNI_CreateJavaVM");
151+
152+ if (pfnCreateJavaVM == NULL)
153+ {
154+ return NULL;
155+ }
156+
157+ g_sJavaVMInitArgs.version = JNI_VERSION_1_2;
158+ g_sJavaVMInitArgs.ignoreUnrecognized = JNI_TRUE;
159+ /* Start the VM */
160+ iRetVal = pfnCreateJavaVM(&g_pJavaVM, (void **)&g_pJNIEnv, &g_sJavaVMInitArgs);
161+
162+ if (iRetVal != 0)
163+ {
164+ return NULL;
165+ }
166+
167+ return g_pJNIEnv;
168+}
169+
170+int invokeMainClass(JNIEnv* psJNIEnv)
171+{
172+ jclass jcMnCls;
173+ jmethodID jmMnMthd;
174+ jobjectArray joAppArgs;
175+ jstring jsAppArg;
176+ jthrowable jtExcptn;
177+ char *pcCurrArg;
178+ int iArgCnt= 0, iOption = -1;
179+ char rgcMnClsCpy[MAX_ARGS] = {0};
180+
181+ /* Ensure Java JNI Env is set up */
182+ if(psJNIEnv == NULL)
183+ {
184+ return -1;
185+ }
186+ /* We need a class name */
187+ if (g_rgcMnCls[0] == '\0')
188+ {
189+ return -1;
190+ }
191+ else
192+ {
193+ /* Replace . with / in fully qualified class name */
194+ char *pClsNm;
195+ for(pClsNm = g_rgcMnCls; *pClsNm; pClsNm++)
196+ {
197+ if(*pClsNm == '.')
198+ *pClsNm = '/';
199+ }
200+ }
201+ /* Find the class */
202+ jcMnCls = (*psJNIEnv)->FindClass(psJNIEnv, g_rgcMnCls);
203+ jtExcptn = (*psJNIEnv)->ExceptionOccurred(psJNIEnv);
204+ if (jtExcptn != NULL)
205+ {
206+ (*psJNIEnv)->ExceptionDescribe(psJNIEnv);
207+ return -1;
208+ }
209+ if (jcMnCls == NULL)
210+ {
211+ return -1;
212+ }
213+ /* Get the static main method */
214+ jmMnMthd = (*psJNIEnv)->GetStaticMethodID(psJNIEnv, jcMnCls, "main", "([Ljava/lang/String;)V");
215+ jtExcptn = (*psJNIEnv)->ExceptionOccurred(psJNIEnv);
216+ if (jtExcptn != NULL)
217+ {
218+ (*psJNIEnv)->ExceptionDescribe(psJNIEnv);
219+ }
220+ if (jmMnMthd == NULL)
221+ {
222+ return -1;
223+ }
224+ /* Build the String[] array if we need one */
225+ strncpy(rgcMnClsCpy, g_rgcMnClsArgs, MAX_ARGS);
226+ iArgCnt = getArgCount(rgcMnClsCpy);
227+ joAppArgs = (jobjectArray)(*psJNIEnv)->NewObjectArray(psJNIEnv, iArgCnt,
228+ (*psJNIEnv)->FindClass(psJNIEnv, "java/lang/String"), NULL);
229+ jtExcptn = (*psJNIEnv)->ExceptionOccurred(psJNIEnv);
230+ if (jtExcptn != NULL)
231+ {
232+ (*psJNIEnv)->ExceptionDescribe(psJNIEnv);
233+ return -1;
234+ }
235+ for (pcCurrArg = strtok(rgcMnClsCpy, g_pcSep); pcCurrArg; pcCurrArg = strtok(NULL, g_pcSep))
236+ {
237+ iOption++;
238+ jsAppArg = (*psJNIEnv)->NewStringUTF(psJNIEnv, pcCurrArg);
239+ (*psJNIEnv)->SetObjectArrayElement(psJNIEnv, joAppArgs, iOption, jsAppArg);
240+ jtExcptn = (*psJNIEnv)->ExceptionOccurred(psJNIEnv);
241+ if(jtExcptn != NULL)
242+ {
243+ (*psJNIEnv)->ExceptionDescribe(psJNIEnv);
244+ return -1;
245+ }
246+ }
247+ /* Execute the class */
248+ (*psJNIEnv)->CallStaticVoidMethod(psJNIEnv, jcMnCls, jmMnMthd, joAppArgs);
249+ return 0;
250+}
251+
252+void cleanupVm()
253+{
254+ /* Destroy the VM */
255+ (*g_pJavaVM)->DestroyJavaVM(g_pJavaVM);
256+}
257+
258+BOOL executeVm(DWORD *dwExitCode)
259+{
260+ BOOL result = TRUE;
261+ *dwExitCode = -1;
262+
263+ int iIdx;
264+ /* Use Invocation API */
265+ if (createVm())
266+ {
267+ *dwExitCode = invokeMainClass(g_pJNIEnv);
268+ cleanupVm();
269+ }
270+ else
271+ {
272+ result = FALSE;
273+ }
274+
275+ /* Free the allocated memory */
276+ for (iIdx = 0; iIdx < g_sJavaVMInitArgs.nOptions; iIdx++)
277+ {
278+ free(g_sJavaVMInitArgs.options[iIdx].optionString);
279+ }
280+ free(g_sJavaVMInitArgs.options);
281+
282+ return result;
283+}
284+
--- /dev/null
+++ b/src/Launch4JStub/head_src/jnihead.h
@@ -0,0 +1,41 @@
1+/*
2+ Launch4j (http://launch4j.sourceforge.net/)
3+ Cross-platform Java application wrapper for creating Windows native executables.
4+
5+ Copyright (c) 2007 Ryan Rusaw
6+
7+ Permission is hereby granted, free of charge, to any person obtaining a copy
8+ of this software and associated documentation files (the "Software"), to deal
9+ in the Software without restriction, including without limitation the rights
10+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+ copies of the Software, and to permit persons to whom the Software is
12+ furnished to do so, subject to the following conditions:
13+
14+ The above copyright notice and this permission notice shall be included in
15+ all copies or substantial portions of the Software.
16+
17+ Except as contained in this notice, the name(s) of the above copyright holders
18+ shall not be used in advertising or otherwise to promote the sale, use or other
19+ dealings in this Software without prior written authorization.
20+
21+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27+ THE SOFTWARE.
28+*/
29+
30+#include <jni.h>
31+#include <ctype.h>
32+
33+#include "head.h"
34+
35+int getArgCount(const char* pcArgStr);
36+void saveJvmOptions(const char *jrePath, const char *mainClass, const char *pcOpts);
37+JNIEnv* createVm();
38+int invokeMainClass(JNIEnv* psJNIEnv);
39+void cleanupVm();
40+BOOL executeVm(DWORD *dwExitCode);
41+
--- /dev/null
+++ b/src/Launch4JStub/head_src/resource.h
@@ -0,0 +1,75 @@
1+/*
2+ Launch4j (http://launch4j.sourceforge.net/)
3+ Cross-platform Java application wrapper for creating Windows native executables.
4+
5+ Copyright (c) 2004, 2014 Grzegorz Kowal
6+ Ian Roberts (jdk preference patch)
7+
8+ Permission is hereby granted, free of charge, to any person obtaining a copy
9+ of this software and associated documentation files (the "Software"), to deal
10+ in the Software without restriction, including without limitation the rights
11+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+ copies of the Software, and to permit persons to whom the Software is
13+ furnished to do so, subject to the following conditions:
14+
15+ The above copyright notice and this permission notice shall be included in
16+ all copies or substantial portions of the Software.
17+
18+ Except as contained in this notice, the name(s) of the above copyright holders
19+ shall not be used in advertising or otherwise to promote the sale, use or other
20+ dealings in this Software without prior written authorization.
21+
22+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28+ THE SOFTWARE.
29+*/
30+
31+// ICON
32+#define APP_ICON 1
33+
34+// BITMAP
35+#define SPLASH_BITMAP 1
36+
37+// RCDATA
38+#define JRE_PATH 1
39+#define JAVA_MIN_VER 2
40+#define JAVA_MAX_VER 3
41+#define SHOW_SPLASH 4
42+#define SPLASH_WAITS_FOR_WINDOW 5
43+#define SPLASH_TIMEOUT 6
44+#define SPLASH_TIMEOUT_ERR 7
45+#define CHDIR 8
46+#define SET_PROC_NAME 9
47+#define ERR_TITLE 10
48+#define GUI_HEADER_STAYS_ALIVE 11
49+#define JVM_OPTIONS 12
50+#define CMD_LINE 13
51+#define JAR 14
52+#define MAIN_CLASS 15
53+#define CLASSPATH 16
54+#define WRAPPER 17
55+#define JDK_PREFERENCE 18
56+#define ENV_VARIABLES 19
57+#define PRIORITY_CLASS 20
58+#define DOWNLOAD_URL 21
59+#define SUPPORT_URL 22
60+#define MUTEX_NAME 23
61+#define INSTANCE_WINDOW_TITLE 24
62+#define INITIAL_HEAP_SIZE 25
63+#define INITIAL_HEAP_PERCENT 26
64+#define MAX_HEAP_SIZE 27
65+#define MAX_HEAP_PERCENT 28
66+#define BUNDLED_JRE_64_BIT 29
67+#define RUNTIME_BITS 30
68+#define RESTART_ON_CRASH 31
69+#define BUNDLED_JRE_AS_FALLBACK 32
70+
71+#define STARTUP_ERR 101
72+#define BUNDLED_JRE_ERR 102
73+#define JRE_VERSION_ERR 103
74+#define LAUNCHER_ERR 104
75+#define INSTANCE_ALREADY_EXISTS_MSG 105
Binary files /dev/null and b/src/Launch4JStub/w32api/crt2.o differ
Binary files /dev/null and b/src/Launch4JStub/w32api/libadvapi32.a differ
Binary files /dev/null and b/src/Launch4JStub/w32api/libgcc.a differ
Binary files /dev/null and b/src/Launch4JStub/w32api/libkernel32.a differ
Binary files /dev/null and b/src/Launch4JStub/w32api/libmingw32.a differ
Binary files /dev/null and b/src/Launch4JStub/w32api/libmsvcrt.a differ
Binary files /dev/null and b/src/Launch4JStub/w32api/libshell32.a differ
Binary files /dev/null and b/src/Launch4JStub/w32api/libshfolder.a differ
Binary files /dev/null and b/src/Launch4JStub/w32api/libuser32.a differ
Show on old repository browser