source: release-kits/shared/search4j/head_src/head.c@ 15093

Last change on this file since 15093 was 15093, checked in by oranfry, 16 years ago

importing the search4j tool I wrote for the release kits

File size: 13.4 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 javaHome[_MAX_PATH] = {0};
43char cmd[_MAX_PATH] = {0};
44char args[MAX_ARGS] = {0};
45
46//added by oran - whether to run the jar, print out java home, or compare java version strings
47char subcommand[8] = "run"; //can be "run", "find", "compare" - run means behave like unhacked launch4j
48
49void setConsoleFlag() {
50 console = TRUE;
51}
52
53void titledMsgBox(const char* title, const char* text) {
54 if (console) {
55 printf("%s: %s\n", title, text);
56 } else {
57 MessageBox(NULL, text, title, MB_OK);
58 }
59}
60
61void msgBox(const char* text) {
62 titledMsgBox(errTitle, text);
63}
64
65void showJavaWebPage() {
66 ShellExecute(NULL, "open", "http://java.com/download", NULL, NULL, SW_SHOWNORMAL);
67}
68
69BOOL loadString(HMODULE hLibrary, int resID, char* buffer) {
70 HRSRC hResource;
71 HGLOBAL hResourceLoaded;
72 LPBYTE lpBuffer;
73
74 hResource = FindResourceEx(hLibrary, RT_RCDATA, MAKEINTRESOURCE(resID),
75 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT));
76 if (NULL != hResource) {
77 hResourceLoaded = LoadResource(hLibrary, hResource);
78 if (NULL != hResourceLoaded) {
79 lpBuffer = (LPBYTE) LockResource(hResourceLoaded);
80 if (NULL != lpBuffer) {
81 int x = 0;
82 do {
83 buffer[x] = (char) lpBuffer[x];
84 } while (buffer[x++] != 0);
85 return TRUE;
86 }
87 }
88 }
89 return FALSE;
90}
91
92BOOL loadBoolString(HMODULE hLibrary, int resID) {
93 char boolStr[10] = {0};
94 loadString(hLibrary, resID, boolStr);
95 return strcmp(boolStr, TRUE_STR) == 0;
96}
97
98void regSearch(HKEY hKey, const char* keyName, int searchType) {
99 DWORD x = 0;
100 unsigned long size = BIG_STR;
101 FILETIME time;
102 char buffer[BIG_STR] = {0};
103 while (RegEnumKeyEx(
104 hKey, // handle to key to enumerate
105 x++, // index of subkey to enumerate
106 buffer, // address of buffer for subkey name
107 &size, // address for size of subkey buffer
108 NULL, // reserved
109 NULL, // address of buffer for class string
110 NULL, // address for size of class buffer
111 &time) == ERROR_SUCCESS) {
112 if (strcmp(buffer, javaMinVer) >= 0
113 && (javaMaxVer[0] == 0 || strcmp(buffer, javaMaxVer) <= 0)
114 && strcmp(buffer, foundJavaVer) > 0) {
115 strcpy(foundJavaVer, buffer);
116 foundJava = searchType;
117 }
118 size = BIG_STR;
119 }
120}
121
122BOOL findJavaHome(char* path) {
123 HKEY hKey;
124 const char jre[] = "SOFTWARE\\JavaSoft\\Java Runtime Environment";
125 const char sdk[] = "SOFTWARE\\JavaSoft\\Java Development Kit";
126 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
127 TEXT(jre),
128 0,
129 KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
130 &hKey) == ERROR_SUCCESS) {
131 regSearch(hKey, jre, FOUND_JRE);
132 RegCloseKey(hKey);
133 }
134 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
135 TEXT(sdk),
136 0,
137 KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
138 &hKey) == ERROR_SUCCESS) {
139 regSearch(hKey, sdk, FOUND_SDK);
140 RegCloseKey(hKey);
141 }
142 if (foundJava != NO_JAVA_FOUND) {
143 char keyBuffer[BIG_STR];
144 unsigned long datatype;
145 unsigned long bufferlength = BIG_STR;
146 if (foundJava == FOUND_JRE) {
147 strcpy(keyBuffer, jre);
148 } else {
149 strcpy(keyBuffer, sdk);
150 }
151 strcat(keyBuffer, "\\");
152 strcat(keyBuffer, foundJavaVer);
153 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
154 TEXT(keyBuffer),
155 0,
156 KEY_QUERY_VALUE,
157 &hKey) == ERROR_SUCCESS) {
158 unsigned char buffer[BIG_STR] = {0};
159 if (RegQueryValueEx(hKey, "JavaHome", NULL, &datatype, buffer, &bufferlength)
160 == ERROR_SUCCESS) {
161 int i = 0;
162 do {
163 path[i] = buffer[i];
164 } while (path[i++] != 0);
165 if (foundJava == FOUND_SDK) {
166 strcat(path, "\\jre");
167 }
168 RegCloseKey(hKey);
169 return TRUE;
170 }
171 RegCloseKey(hKey);
172 }
173 }
174 return FALSE;
175}
176
177/*
178 * Extract the executable name, returns path length.
179 */
180int getExePath(char* exePath) {
181 HMODULE hModule = GetModuleHandle(NULL);
182 if (hModule == 0
183 || GetModuleFileName(hModule, exePath, _MAX_PATH) == 0) {
184 return -1;
185 }
186 return strrchr(exePath, '\\') - exePath;
187}
188
189void appendJavaw(char* jrePath) {
190 if (console) {
191 strcat(jrePath, "\\bin\\java.exe");
192 } else {
193 strcat(jrePath, "\\bin\\javaw.exe");
194 }
195}
196
197void appendLauncher(BOOL setProcName, char* exePath, int pathLen, char* cmd) {
198 if (setProcName) {
199 char tmpspec[_MAX_PATH];
200 char tmpfile[_MAX_PATH];
201 strcpy(tmpspec, cmd);
202 strcat(tmpspec, LAUNCH4J_TMP_DIR);
203 tmpspec[strlen(tmpspec) - 1] = 0;
204 if (_stat(tmpspec, &statBuf) == 0) {
205 // remove temp launchers
206 struct _finddata_t c_file;
207 long hFile;
208 strcat(tmpspec, "\\*.exe");
209 strcpy(tmpfile, cmd);
210 strcat(tmpfile, LAUNCH4J_TMP_DIR);
211 char* filename = tmpfile + strlen(tmpfile);
212 if ((hFile = _findfirst(tmpspec, &c_file)) != -1L) {
213 do {
214 strcpy(filename, c_file.name);
215 _unlink(tmpfile);
216 } while (_findnext(hFile, &c_file) == 0);
217 }
218 _findclose(hFile);
219 } else {
220 if (_mkdir(tmpspec) != 0) {
221 appendJavaw(cmd);
222 return;
223 }
224 }
225 char javaw[_MAX_PATH];
226 strcpy(javaw, cmd);
227 appendJavaw(javaw);
228 strcpy(tmpfile, cmd);
229 strcat(tmpfile, LAUNCH4J_TMP_DIR);
230 char* exeFilePart = exePath + pathLen + 1;
231 strcat(tmpfile, exeFilePart);
232 if (CopyFile(javaw, tmpfile, FALSE)) {
233 strcpy(cmd, tmpfile);
234 return;
235 } else if (_stat(javaw, &statBuf) == 0) {
236 long fs = statBuf.st_size;
237 if (_stat(tmpfile, &statBuf) == 0 && fs == statBuf.st_size) {
238 strcpy(cmd, tmpfile);
239 return;
240 }
241 }
242 }
243 appendJavaw(cmd);
244}
245
246BOOL isJrePathOk(char* path) {
247 if (!*path) {
248 return FALSE;
249 }
250 char javaw[_MAX_PATH];
251 strcpy(javaw, path);
252 appendJavaw(javaw);
253 return _stat(javaw, &statBuf) == 0;
254}
255
256//added by oran - added the subcom argument
257BOOL prepare(HMODULE hLibrary, char *lpCmdLine, char *subcom) {
258 char tmp[MAX_ARGS] = {0};
259 GetEnvironmentVariable("launch4j", tmp, STR);
260 debug = _stricmp(tmp, "debug") == 0;
261
262 //added by oran - set the subcommand
263 strcpy( subcommand, subcom );
264
265 // Open executable
266 char exePath[_MAX_PATH] = {0};
267 int pathLen = getExePath(exePath);
268 if (pathLen == -1) {
269 msgBox("Cannot determinate exe file name.");
270 return FALSE;
271 }
272 hLibrary = LoadLibrary(exePath);
273 if (hLibrary == NULL) {
274 char msg[BIG_STR];
275 strcpy(msg, "Cannot find file: ");
276 strcat(msg, exePath);
277 msgBox(msg);
278 return FALSE;
279 }
280
281 // Error message box title
282 loadString(hLibrary, ERR_TITLE, errTitle);
283
284 // Working dir
285 char tmp_path[_MAX_PATH] = {0};
286 if (loadString(hLibrary, CHDIR, tmp_path)) {
287 strncpy(workingDir, exePath, pathLen);
288 strcat(workingDir, "\\");
289 strcat(workingDir, tmp_path);
290 _chdir(workingDir);
291 }
292
293 // Custom process name
294 const BOOL setProcName = loadBoolString(hLibrary, SET_PROC_NAME);
295
296 // Use bundled jre or find java
297 if (loadString(hLibrary, JRE_PATH, tmp_path)) {
298 if (tmp_path[0] == '\\' || tmp_path[1] == ':') {
299 // Absolute
300 strcpy(cmd, tmp_path);
301 } else {
302 // Relative
303 strncpy(cmd, exePath, pathLen);
304 strcat(cmd, "\\");
305 strcat(cmd, tmp_path);
306 }
307 }
308 if (!isJrePathOk(cmd)) {
309 if (!loadString(hLibrary, JAVA_MIN_VER, javaMinVer)) {
310 msgBox("Cannot find bundled JRE or javaw.exe is missing.");
311 return FALSE;
312 }
313 loadString(hLibrary, JAVA_MAX_VER, javaMaxVer);
314 if (!findJavaHome(cmd)) {
315 char txt[BIG_STR];
316 strcpy(txt, "Cannot find Java ");
317 strcat(txt, javaMinVer);
318 if (*javaMaxVer) {
319 strcat(txt, " - ");
320 strcat(txt, javaMaxVer);
321 }
322 //msgBox(txt);
323 //showJavaWebPage();
324 return FALSE;
325 }
326 if (!isJrePathOk(cmd)) {
327 msgBox("Java found, but javaw.exe seems to be missing.");
328 return FALSE;
329 }
330 }
331
332 //before appending the launcher, save the cmd in javaHome
333 strcpy( javaHome, cmd );
334
335 //only affect the PATH if subcommand is run
336 if ( _stricmp( subcommand, "run" ) ) {
337 // Append a path to the Path environment variable
338 char jreBinPath[_MAX_PATH];
339 strcpy(jreBinPath, cmd);
340 strcat(jreBinPath, "\\bin");
341 if (!appendToPathVar(jreBinPath)) {
342 msgBox("Cannot set the Path environment variable.");
343 return FALSE;
344 }
345 }
346
347 appendLauncher(setProcName, exePath, pathLen, cmd);
348
349 // JVM args
350 if (loadString(hLibrary, JVM_ARGS, tmp)) {
351 strcat(tmp, " ");
352 } else {
353 *tmp = 0;
354 }
355 // Load additional JVM arguments from ini file
356 strncpy(tmp_path, exePath, strlen(exePath) - 3);
357 strcat(tmp_path, "ini");
358 long hFile;
359 if ((hFile = _open(tmp_path, _O_RDONLY)) != -1) {
360 const int jvmArgsLen = strlen(tmp);
361 char* src = tmp + jvmArgsLen;
362 char* dst = src;
363 const int len = _read(hFile, src, MAX_ARGS - jvmArgsLen - BIG_STR);
364 int i;
365 for (i = 0; i < len; i++) {
366 if (*src == 13 || *src == 10) {
367 if (dst > tmp && *(dst - 1) != ' ') {
368 *dst++ = ' ';
369 }
370 src++;
371 } else {
372 *dst++ = *src++;
373 }
374 }
375 *dst = 0;
376 if (len > 0 && *(dst - 1) != ' ') {
377 strcat(tmp, " ");
378 }
379 _close(hFile);
380 }
381
382 // Expand environment %variables%
383 if (*tmp) {
384 char varName[STR];
385 char varValue[MAX_VAR_SIZE];
386 char *pos = tmp;
387 while (strlen(pos) > 0) {
388 char *start = strchr(pos, '%');
389 if (start != NULL) {
390 char *end = strchr(start + 1, '%');
391 if (end == NULL) {
392 return FALSE;
393 }
394 // Copy content up to %VAR%
395 strncat(args, pos, start - pos);
396 // Insert value of %VAR%
397 varName[0] = 0;
398 strncat(varName, start + 1, end - start - 1);
399 if (strcmp(varName, "EXEDIR") == 0) {
400 strncat(args, exePath, pathLen);
401 } else if (strcmp(varName, "EXEFILE") == 0) {
402 strcat(args, exePath);
403 } else if (GetEnvironmentVariable(varName, varValue, MAX_VAR_SIZE) > 0) {
404 strcat(args, varValue);
405 }
406 pos = end + 1;
407 } else {
408 // Copy remaining content
409 strcat(args, pos);
410 break;
411 }
412 }
413 }
414
415 // Jar
416 strcat(args, "-jar \"");
417 if (loadString(hLibrary, JAR, tmp)) {
418 strncat(args, exePath, pathLen);
419 strcat(args, "\\");
420 strcat(args, tmp);
421 } else {
422 strcat(args, exePath);
423 }
424 strcat(args, "\"");
425
426 // Constant command line args
427 char jarArgs[BIG_STR] = {0};
428 if (loadString(hLibrary, JAR_ARGS, jarArgs)) {
429 strcat(args, " ");
430 strcat(args, jarArgs);
431 }
432
433 // Command line args
434 if (*lpCmdLine) {
435 strcat(args, " ");
436 strcat(args, lpCmdLine);
437 }
438
439 if (debug) {
440 printf("*** Launch4j debug info ***\nWorking dir:\t%s\n", workingDir);
441 printf("Launcher:\t%s\n", cmd);
442 _itoa(strlen(args), tmp, 10); // 10 -- radix
443 printf("Args length:\t%s/32768 chars\n", tmp);
444 printf("Launcher args:\t%s\n\n", args);
445 }
446 return TRUE;
447}
448
449void closeHandles() {
450 CloseHandle(pi.hThread);
451 CloseHandle(pi.hProcess);
452}
453
454/*
455 * Append a path to the Path environment variable
456 */
457BOOL appendToPathVar(char* path) {
458 char chBuf[MAX_VAR_SIZE] = {0};
459
460 const int pathSize = GetEnvironmentVariable("Path", chBuf, MAX_VAR_SIZE);
461 if (MAX_VAR_SIZE - pathSize - 1 < strlen(path)) {
462 return FALSE;
463 }
464 strcat(chBuf, ";");
465 strcat(chBuf, path);
466 return SetEnvironmentVariable("Path", chBuf);
467}
468
469DWORD execute(BOOL wait) {
470 //added by oran - the original execute function has been wrapped in this if, and a few else ifs added after that
471 if ( _stricmp(subcommand, "run") == 0 ) {
472
473 STARTUPINFO si;
474 memset(&pi, 0, sizeof(pi));
475 memset(&si, 0, sizeof(si));
476 si.cb = sizeof(si);
477
478 DWORD dwExitCode = -1;
479 char cmdline[MAX_ARGS];
480 strcpy(cmdline, "\"");
481 strcat(cmdline, cmd);
482 strcat(cmdline, "\" ");
483 strcat(cmdline, args);
484 if (CreateProcess(NULL, cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
485 if (wait) {
486 WaitForSingleObject(pi.hProcess, INFINITE);
487 GetExitCodeProcess(pi.hProcess, &dwExitCode);
488 closeHandles();
489 } else {
490 dwExitCode = 0;
491 }
492 }
493 return dwExitCode;
494
495 } else if ( _stricmp(subcommand, "find") == 0 ) {
496 printf("%s\n", javaHome);
497 } else if ( _stricmp(subcommand, "compare") == 0 ) {
498 printf("%s\n", foundJavaVer);
499 }
500}
Note: See TracBrowser for help on using the repository browser.