source: release-kits/shared/launch4j/head_src/head.c@ 15024

Last change on this file since 15024 was 15024, checked in by oranfry, 14 years ago

putting launch4j in the shared area

File size: 12.5 KB
Line 
1/*
2 Launch4j (http://launch4j.sourceforge.net/)
3 Cross-platform Java application wrapper for creating Windows native executables.
4
5 Copyright (C) 2004, 2006 Grzegorz Kowal
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
21
22 Compiled with Mingw port of GCC,
23 Bloodshed Dev-C++ IDE (http://www.bloodshed.net/devcpp.html)
24*/
25
26#include "resource.h"
27#include "head.h"
28
29BOOL debug = FALSE;
30BOOL console = FALSE;
31int foundJava = NO_JAVA_FOUND;
32
33struct _stat statBuf;
34PROCESS_INFORMATION pi;
35
36char errTitle[STR] = "Launch4j";
37char javaMinVer[STR] = {0};
38char javaMaxVer[STR] = {0};
39char foundJavaVer[STR] = {0};
40
41char workingDir[_MAX_PATH] = {0};
42char cmd[_MAX_PATH] = {0};
43char args[MAX_ARGS] = {0};
44
45void setConsoleFlag() {
46 console = TRUE;
47}
48
49void titledMsgBox(const char* title, const char* text) {
50 if (console) {
51 printf("%s: %s\n", title, text);
52 } else {
53 MessageBox(NULL, text, title, MB_OK);
54 }
55}
56
57void msgBox(const char* text) {
58 titledMsgBox(errTitle, text);
59}
60
61void showJavaWebPage() {
62 ShellExecute(NULL, "open", "http://java.com/download", NULL, NULL, SW_SHOWNORMAL);
63}
64
65BOOL loadString(HMODULE hLibrary, int resID, char* buffer) {
66 HRSRC hResource;
67 HGLOBAL hResourceLoaded;
68 LPBYTE lpBuffer;
69
70 hResource = FindResourceEx(hLibrary, RT_RCDATA, MAKEINTRESOURCE(resID),
71 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT));
72 if (NULL != hResource) {
73 hResourceLoaded = LoadResource(hLibrary, hResource);
74 if (NULL != hResourceLoaded) {
75 lpBuffer = (LPBYTE) LockResource(hResourceLoaded);
76 if (NULL != lpBuffer) {
77 int x = 0;
78 do {
79 buffer[x] = (char) lpBuffer[x];
80 } while (buffer[x++] != 0);
81 return TRUE;
82 }
83 }
84 }
85 return FALSE;
86}
87
88BOOL loadBoolString(HMODULE hLibrary, int resID) {
89 char boolStr[10] = {0};
90 loadString(hLibrary, resID, boolStr);
91 return strcmp(boolStr, TRUE_STR) == 0;
92}
93
94void regSearch(HKEY hKey, const char* keyName, int searchType) {
95 DWORD x = 0;
96 unsigned long size = BIG_STR;
97 FILETIME time;
98 char buffer[BIG_STR] = {0};
99 while (RegEnumKeyEx(
100 hKey, // handle to key to enumerate
101 x++, // index of subkey to enumerate
102 buffer, // address of buffer for subkey name
103 &size, // address for size of subkey buffer
104 NULL, // reserved
105 NULL, // address of buffer for class string
106 NULL, // address for size of class buffer
107 &time) == ERROR_SUCCESS) {
108 if (strcmp(buffer, javaMinVer) >= 0
109 && (javaMaxVer[0] == 0 || strcmp(buffer, javaMaxVer) <= 0)
110 && strcmp(buffer, foundJavaVer) > 0) {
111 strcpy(foundJavaVer, buffer);
112 foundJava = searchType;
113 }
114 size = BIG_STR;
115 }
116}
117
118BOOL findJavaHome(char* path) {
119 HKEY hKey;
120 const char jre[] = "SOFTWARE\\JavaSoft\\Java Runtime Environment";
121 const char sdk[] = "SOFTWARE\\JavaSoft\\Java Development Kit";
122 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
123 TEXT(jre),
124 0,
125 KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
126 &hKey) == ERROR_SUCCESS) {
127 regSearch(hKey, jre, FOUND_JRE);
128 RegCloseKey(hKey);
129 }
130 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
131 TEXT(sdk),
132 0,
133 KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
134 &hKey) == ERROR_SUCCESS) {
135 regSearch(hKey, sdk, FOUND_SDK);
136 RegCloseKey(hKey);
137 }
138 if (foundJava != NO_JAVA_FOUND) {
139 char keyBuffer[BIG_STR];
140 unsigned long datatype;
141 unsigned long bufferlength = BIG_STR;
142 if (foundJava == FOUND_JRE) {
143 strcpy(keyBuffer, jre);
144 } else {
145 strcpy(keyBuffer, sdk);
146 }
147 strcat(keyBuffer, "\\");
148 strcat(keyBuffer, foundJavaVer);
149 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
150 TEXT(keyBuffer),
151 0,
152 KEY_QUERY_VALUE,
153 &hKey) == ERROR_SUCCESS) {
154 unsigned char buffer[BIG_STR] = {0};
155 if (RegQueryValueEx(hKey, "JavaHome", NULL, &datatype, buffer, &bufferlength)
156 == ERROR_SUCCESS) {
157 int i = 0;
158 do {
159 path[i] = buffer[i];
160 } while (path[i++] != 0);
161 if (foundJava == FOUND_SDK) {
162 strcat(path, "\\jre");
163 }
164 RegCloseKey(hKey);
165 return TRUE;
166 }
167 RegCloseKey(hKey);
168 }
169 }
170 return FALSE;
171}
172
173/*
174 * Extract the executable name, returns path length.
175 */
176int getExePath(char* exePath) {
177 HMODULE hModule = GetModuleHandle(NULL);
178 if (hModule == 0
179 || GetModuleFileName(hModule, exePath, _MAX_PATH) == 0) {
180 return -1;
181 }
182 return strrchr(exePath, '\\') - exePath;
183}
184
185void appendJavaw(char* jrePath) {
186 if (console) {
187 strcat(jrePath, "\\bin\\java.exe");
188 } else {
189 strcat(jrePath, "\\bin\\javaw.exe");
190 }
191}
192
193void appendLauncher(BOOL setProcName, char* exePath, int pathLen, char* cmd) {
194 if (setProcName) {
195 char tmpspec[_MAX_PATH];
196 char tmpfile[_MAX_PATH];
197 strcpy(tmpspec, cmd);
198 strcat(tmpspec, LAUNCH4J_TMP_DIR);
199 tmpspec[strlen(tmpspec) - 1] = 0;
200 if (_stat(tmpspec, &statBuf) == 0) {
201 // remove temp launchers
202 struct _finddata_t c_file;
203 long hFile;
204 strcat(tmpspec, "\\*.exe");
205 strcpy(tmpfile, cmd);
206 strcat(tmpfile, LAUNCH4J_TMP_DIR);
207 char* filename = tmpfile + strlen(tmpfile);
208 if ((hFile = _findfirst(tmpspec, &c_file)) != -1L) {
209 do {
210 strcpy(filename, c_file.name);
211 _unlink(tmpfile);
212 } while (_findnext(hFile, &c_file) == 0);
213 }
214 _findclose(hFile);
215 } else {
216 if (_mkdir(tmpspec) != 0) {
217 appendJavaw(cmd);
218 return;
219 }
220 }
221 char javaw[_MAX_PATH];
222 strcpy(javaw, cmd);
223 appendJavaw(javaw);
224 strcpy(tmpfile, cmd);
225 strcat(tmpfile, LAUNCH4J_TMP_DIR);
226 char* exeFilePart = exePath + pathLen + 1;
227 strcat(tmpfile, exeFilePart);
228 if (CopyFile(javaw, tmpfile, FALSE)) {
229 strcpy(cmd, tmpfile);
230 return;
231 } else if (_stat(javaw, &statBuf) == 0) {
232 long fs = statBuf.st_size;
233 if (_stat(tmpfile, &statBuf) == 0 && fs == statBuf.st_size) {
234 strcpy(cmd, tmpfile);
235 return;
236 }
237 }
238 }
239 appendJavaw(cmd);
240}
241
242BOOL isJrePathOk(char* path) {
243 if (!*path) {
244 return FALSE;
245 }
246 char javaw[_MAX_PATH];
247 strcpy(javaw, path);
248 appendJavaw(javaw);
249 return _stat(javaw, &statBuf) == 0;
250}
251
252BOOL prepare(HMODULE hLibrary, char *lpCmdLine) {
253 char tmp[MAX_ARGS] = {0};
254 GetEnvironmentVariable("launch4j", tmp, STR);
255 debug = _stricmp(tmp, "debug") == 0;
256
257 // Open executable
258 char exePath[_MAX_PATH] = {0};
259 int pathLen = getExePath(exePath);
260 if (pathLen == -1) {
261 msgBox("Cannot determinate exe file name.");
262 return FALSE;
263 }
264 hLibrary = LoadLibrary(exePath);
265 if (hLibrary == NULL) {
266 char msg[BIG_STR];
267 strcpy(msg, "Cannot find file: ");
268 strcat(msg, exePath);
269 msgBox(msg);
270 return FALSE;
271 }
272
273 // Error message box title
274 loadString(hLibrary, ERR_TITLE, errTitle);
275
276 // Working dir
277 char tmp_path[_MAX_PATH] = {0};
278 if (loadString(hLibrary, CHDIR, tmp_path)) {
279 strncpy(workingDir, exePath, pathLen);
280 strcat(workingDir, "\\");
281 strcat(workingDir, tmp_path);
282 _chdir(workingDir);
283 }
284
285 // Custom process name
286 const BOOL setProcName = loadBoolString(hLibrary, SET_PROC_NAME);
287
288 // Use bundled jre or find java
289 if (loadString(hLibrary, JRE_PATH, tmp_path)) {
290 if (tmp_path[0] == '\\' || tmp_path[1] == ':') {
291 // Absolute
292 strcpy(cmd, tmp_path);
293 } else {
294 // Relative
295 strncpy(cmd, exePath, pathLen);
296 strcat(cmd, "\\");
297 strcat(cmd, tmp_path);
298 }
299 }
300 if (!isJrePathOk(cmd)) {
301 if (!loadString(hLibrary, JAVA_MIN_VER, javaMinVer)) {
302 msgBox("Cannot find bundled JRE or javaw.exe is missing.");
303 return FALSE;
304 }
305 loadString(hLibrary, JAVA_MAX_VER, javaMaxVer);
306 if (!findJavaHome(cmd)) {
307 char txt[BIG_STR];
308 strcpy(txt, "Cannot find Java ");
309 strcat(txt, javaMinVer);
310 if (*javaMaxVer) {
311 strcat(txt, " - ");
312 strcat(txt, javaMaxVer);
313 }
314 msgBox(txt);
315 showJavaWebPage();
316 return FALSE;
317 }
318 if (!isJrePathOk(cmd)) {
319 msgBox("Java found, but javaw.exe seems to be missing.");
320 return FALSE;
321 }
322 }
323
324 // Append a path to the Path environment variable
325 char jreBinPath[_MAX_PATH];
326 strcpy(jreBinPath, cmd);
327 strcat(jreBinPath, "\\bin");
328 if (!appendToPathVar(jreBinPath)) {
329 msgBox("Cannot set the Path environment variable.");
330 return FALSE;
331 }
332
333 appendLauncher(setProcName, exePath, pathLen, cmd);
334
335 // JVM args
336 if (loadString(hLibrary, JVM_ARGS, tmp)) {
337 strcat(tmp, " ");
338 } else {
339 *tmp = 0;
340 }
341 // Load additional JVM arguments from ini file
342 strncpy(tmp_path, exePath, strlen(exePath) - 3);
343 strcat(tmp_path, "ini");
344 long hFile;
345 if ((hFile = _open(tmp_path, _O_RDONLY)) != -1) {
346 const int jvmArgsLen = strlen(tmp);
347 char* src = tmp + jvmArgsLen;
348 char* dst = src;
349 const int len = _read(hFile, src, MAX_ARGS - jvmArgsLen - BIG_STR);
350 int i;
351 for (i = 0; i < len; i++) {
352 if (*src == 13 || *src == 10) {
353 if (dst > tmp && *(dst - 1) != ' ') {
354 *dst++ = ' ';
355 }
356 src++;
357 } else {
358 *dst++ = *src++;
359 }
360 }
361 *dst = 0;
362 if (len > 0 && *(dst - 1) != ' ') {
363 strcat(tmp, " ");
364 }
365 _close(hFile);
366 }
367
368 // Expand environment %variables%
369 if (*tmp) {
370 char varName[STR];
371 char varValue[MAX_VAR_SIZE];
372 char *pos = tmp;
373 while (strlen(pos) > 0) {
374 char *start = strchr(pos, '%');
375 if (start != NULL) {
376 char *end = strchr(start + 1, '%');
377 if (end == NULL) {
378 return FALSE;
379 }
380 // Copy content up to %VAR%
381 strncat(args, pos, start - pos);
382 // Insert value of %VAR%
383 varName[0] = 0;
384 strncat(varName, start + 1, end - start - 1);
385 if (strcmp(varName, "EXEDIR") == 0) {
386 strncat(args, exePath, pathLen);
387 } else if (strcmp(varName, "EXEFILE") == 0) {
388 strcat(args, exePath);
389 } else if (GetEnvironmentVariable(varName, varValue, MAX_VAR_SIZE) > 0) {
390 strcat(args, varValue);
391 }
392 pos = end + 1;
393 } else {
394 // Copy remaining content
395 strcat(args, pos);
396 break;
397 }
398 }
399 }
400
401 // Jar
402 strcat(args, "-jar \"");
403 if (loadString(hLibrary, JAR, tmp)) {
404 strncat(args, exePath, pathLen);
405 strcat(args, "\\");
406 strcat(args, tmp);
407 } else {
408 strcat(args, exePath);
409 }
410 strcat(args, "\"");
411
412 // Constant command line args
413 char jarArgs[BIG_STR] = {0};
414 if (loadString(hLibrary, JAR_ARGS, jarArgs)) {
415 strcat(args, " ");
416 strcat(args, jarArgs);
417 }
418
419 // Command line args
420 if (*lpCmdLine) {
421 strcat(args, " ");
422 strcat(args, lpCmdLine);
423 }
424
425 if (debug) {
426 printf("*** Launch4j debug info ***\nWorking dir:\t%s\n", workingDir);
427 printf("Launcher:\t%s\n", cmd);
428 _itoa(strlen(args), tmp, 10); // 10 -- radix
429 printf("Args length:\t%s/32768 chars\n", tmp);
430 printf("Launcher args:\t%s\n\n", args);
431 }
432 return TRUE;
433}
434
435void closeHandles() {
436 CloseHandle(pi.hThread);
437 CloseHandle(pi.hProcess);
438}
439
440/*
441 * Append a path to the Path environment variable
442 */
443BOOL appendToPathVar(char* path) {
444 char chBuf[MAX_VAR_SIZE] = {0};
445
446 const int pathSize = GetEnvironmentVariable("Path", chBuf, MAX_VAR_SIZE);
447 if (MAX_VAR_SIZE - pathSize - 1 < strlen(path)) {
448 return FALSE;
449 }
450 strcat(chBuf, ";");
451 strcat(chBuf, path);
452 return SetEnvironmentVariable("Path", chBuf);
453}
454
455DWORD execute(BOOL wait) {
456 STARTUPINFO si;
457 memset(&pi, 0, sizeof(pi));
458 memset(&si, 0, sizeof(si));
459 si.cb = sizeof(si);
460
461 DWORD dwExitCode = -1;
462 char cmdline[MAX_ARGS];
463 strcpy(cmdline, "\"");
464 strcat(cmdline, cmd);
465 strcat(cmdline, "\" ");
466 strcat(cmdline, args);
467 if (CreateProcess(NULL, cmdline, NULL, NULL,
468 TRUE, 0, NULL, NULL, &si, &pi)) {
469 if (wait) {
470 WaitForSingleObject(pi.hProcess, INFINITE);
471 GetExitCodeProcess(pi.hProcess, &dwExitCode);
472 closeHandles();
473 } else {
474 dwExitCode = 0;
475 }
476 }
477 return dwExitCode;
478}
Note: See TracBrowser for help on using the repository browser.