キャラクターなんとかJの本体
Revision | 4d4debd6a162a4dc9178726db7cc3feb5ee9eb5e (tree) |
---|---|
Time | 2018-12-30 17:43:36 |
Author | seraphy <seraphy@user...> |
Commiter | seraphy |
起動時にJava環境がバンドル位置にもレジストリからも発見できなかった場合、
ユーザーにJAVA_HOMEの場所を問い合わせるランチャにした。
@@ -167,11 +167,11 @@ | ||
167 | 167 | <plugins> |
168 | 168 | <plugin> |
169 | 169 | <!-- Launch4jによるjarファイルのexe化を行う. http://launch4j.sourceforge.net/docs.html |
170 | - プラグインが1.7.24の場合、使用するのはLaunch4j 3.12 である。 | |
170 | + プラグインが1.7.25の場合、使用するのはLaunch4j 3.12 である。 | |
171 | 171 | https://github.com/lukaszlenart/launch4j-maven-plugin/blob/master/pom.xml --> |
172 | 172 | <groupId>com.akathist.maven.plugins.launch4j</groupId> |
173 | 173 | <artifactId>launch4j-maven-plugin</artifactId> |
174 | - <version>1.7.24</version> | |
174 | + <version>1.7.25</version> | |
175 | 175 | <executions> |
176 | 176 | <execution> |
177 | 177 | <id>l4j-gui</id> |
@@ -185,9 +185,28 @@ | ||
185 | 185 | <jar>target/${project.artifactId}.jar</jar> |
186 | 186 | <errTitle>Failed to execute the ${project.artifactId}</errTitle> |
187 | 187 | <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> | |
188 | 207 | <jre> |
189 | 208 | <path>jre</path> |
190 | - <minVersion>1.5.0</minVersion> | |
209 | + <minVersion>1.6.0</minVersion> | |
191 | 210 | <initialHeapSize>64</initialHeapSize> |
192 | 211 | <maxHeapSize>128</maxHeapSize> |
193 | 212 | </jre> |
@@ -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. |
@@ -0,0 +1,2 @@ | ||
1 | +/consolehead.exe | |
2 | +/consolehead.layout |
@@ -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) |
@@ -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 | +} |
@@ -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 | + |
@@ -0,0 +1,2 @@ | ||
1 | +/guihead.exe | |
2 | +/guihead.layout |
@@ -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) |
@@ -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 | +} |
@@ -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 | + |
@@ -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 | +); |
@@ -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 | + |
@@ -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_ |
@@ -0,0 +1,2 @@ | ||
1 | +/jniconsolehead.exe | |
2 | +/jniconsolehead.layout |
@@ -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) |
@@ -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 | +} |
@@ -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 | + |
@@ -0,0 +1,2 @@ | ||
1 | +/jniguihead.exe | |
2 | +/jniguihead.layout |
@@ -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) |
@@ -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 | +} |
@@ -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 | + |
@@ -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 | +); |
@@ -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 | + |
@@ -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 | + |
@@ -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 |