• R/O
  • SSH
  • HTTPS

exewrap: Commit


Commit MetaInfo

Revision20 (tree)
Time2015-07-16 21:32:11
Authorhirukawa_ryo

Log Message

v1.0.4 リファクタリング実施。v1.0.3と大幅に内部実装が変わりました。このバージョンはリリース予定はありません。v1.1.0で機能追加をおこなうための下準備です。

Change Summary

Incremental Difference

--- exewrap/trunk/exewrap/src/exewrap.c (revision 19)
+++ exewrap/trunk/exewrap/src/exewrap.c (revision 20)
@@ -9,66 +9,67 @@
99 #include <jni.h>
1010
1111 #include "include/jvm.h"
12+#include "include/loader.h"
1213 #include "include/icon.h"
1314 #include "include/message.h"
1415
15-char** ParseOption(int argc, char* argv[]);
16-char* GetResource(LPCTSTR name, LPCTSTR type, DWORD* size);
17-void SetResource(LPCTSTR filename, LPCTSTR rscName, LPCTSTR rscType, char* rscData, DWORD rscSize);
18-void CreateExeFile(LPCTSTR filename, char* data, DWORD size);
19-char* GetFileData(LPCTSTR filename, DWORD* size);
16+#define DEFAULT_VERSION "0.0"
17+#define DEFAULT_PRODUCT_VERSION "0.0"
2018
21-void InitResource(LPCTSTR name);
22-DWORD GetResourceSize(LPCTSTR name);
23-jbyte* GetResourceBuffer(LPCTSTR name);
19+void OutputMessage(const char* text);
20+UINT UncaughtException(const char* thread, const char* message, const char* trace);
2421
25-DWORD GetVersionRevision(LPTSTR filename);
26-char* SetVersionInfo(LPCTSTR filename, char* versionNumber, DWORD previousBuild, char* fileDescription, char* copyright, char* company_name, char* product_name, char* product_version, char* original_filename, char* jarfile);
27-void SetApplicationIcon(LPCTSTR filename, LPCTSTR iconfile);
22+static char** parse_opt(int argc, char* argv[]);
23+static DWORD get_version_revision(char* filename);
24+static BOOL create_exe_file(const char* filename, BYTE* image_buf, DWORD image_len, BOOL is_reverse);
25+static DWORD get_target_java_runtime_version(char* version);
26+static char* get_target_java_runtime_version_string(DWORD version, char* buf);
27+static void set_resource(const char* filename, const char* rsc_name, const char* rsc_type, BYTE* rsc_data, DWORD rsc_size);
28+static BYTE* get_jar_buf(const char* jar_file, DWORD* jar_len);
29+static void set_application_icon(const char* filename, const char* icon_file);
30+static char* set_version_info(const char* filename, const char* version_number, DWORD previous_revision, char* file_description, char* copyright, char* company_name, char* product_name, char* product_version, char* original_filename, char* jar_file);
2831
29-DWORD GetTargetJavaRuntimeVersion(char* version);
30-LPTSTR GetTargetJavaRuntimeVersionString(DWORD version);
3132
3233 void UsePack200(LPCTSTR exefile, LPCTSTR jarfile);
3334
34-char defaultVersion[] = "0.0";
35-char defaultProductVersion[] = "0.0";
3635
3736 int main(int argc, char* argv[])
3837 {
39- DWORD targetVersion;
40- char* targetVersionString;
41- char** opt = ParseOption(argc, argv);
42- int architecture_bits = 0;
43- char image_name[32];
44- char* jarfile;
45- char* exefile = NULL;
38+ char** opt = NULL;
39+ char* jar_file = NULL;
40+ char* exe_file = NULL;
41+ int architecture_bits = 0;
42+ char image_name[32];
43+ BYTE* image_buf;
44+ DWORD image_len;
45+ DWORD previous_revision = 0;
46+ DWORD target_version;
47+ char* target_version_string;
48+ BOOL disable_pack200 = FALSE;
49+ BOOL enable_java = FALSE;
50+ BYTE* jar_buf;
51+ DWORD jar_len;
52+ char* version_number;
53+ char* file_description;
54+ char* copyright;
55+ char* company_name;
56+ char* product_name;
57+ char* product_version;
58+ char* original_filename;
59+ char* new_version;
60+
61+ char* buf = NULL;
62+ char* ptr = NULL;
63+ RESOURCE res;
64+ BOOL b;
4665
47- char* exeBuffer;
48- DWORD exeSize;
49- char* jarBuffer;
50- DWORD jarSize;
51- char* classBuffer = NULL;
52- DWORD classSize;
53-
54- DWORD previousRevision = 0;
55- char* versionNumber;
56- char* fileDescription;
57- char* copyright;
58- char* company_name;
59- char* product_name;
60- char* product_version;
61- char* original_filename;
62-
63- BOOL enableJava = FALSE;
64- BOOL disablePack200 = FALSE;
65- char* newVersion;
66-
66+ opt = parse_opt(argc, argv);
67+
6768 if((argc < 2) || ((opt['j'] == NULL) && (opt[0] == NULL)))
6869 {
6970 int bits = GetProcessArchitecture();
7071
71- printf("exewrap 1.0.3 for %s (%d-bit)\r\n"
72+ printf("exewrap 1.0.4 for %s (%d-bit)\r\n"
7273 "Native executable java application wrapper.\r\n"
7374 "Copyright (C) 2005-2015 HIRUKAWA Ryo. All rights reserved.\r\n"
7475 "\r\n"
@@ -95,21 +96,22 @@
9596
9697 return 0;
9798 }
99+
100+ buf = malloc(2048);
98101
102+ jar_file = malloc(1024);
99103 if(opt['j'] && *opt['j'] != '-' && *opt['j'] != '\0')
100104 {
101- jarfile = opt['j'];
105+ strcpy(jar_file, opt['j']);
102106 }
103107 else
104108 {
105- jarfile = opt[0];
109+ strcpy(jar_file, opt[0]);
106110
107- if(lstrlen(jarfile) > 4)
111+ if(strlen(jar_file) > 4)
108112 {
109- char buf[_MAX_PATH];
110-
111- lstrcpy(buf, jarfile + lstrlen(jarfile) - 4);
112- if(lstrcmp(_strupr(buf), ".JAR"))
113+ strcpy(buf, jar_file + strlen(jar_file) - 4);
114+ if(strcmp(_strupr(buf), ".JAR"))
113115 {
114116 printf("You must specify the jar-file.\n");
115117 return 1;
@@ -117,29 +119,23 @@
117119 }
118120 }
119121
120- exefile = (char*)HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
122+ exe_file = malloc(1024);
121123 if(opt['o'] && *opt['o'] != '-' && *opt['o'] != '\0')
122124 {
123- lstrcpy(exefile, opt['o']);
125+ strcpy(exe_file, opt['o']);
124126 }
125127 else
126128 {
127- lstrcpy(exefile, jarfile);
128- exefile[lstrlen(exefile) - 4] = 0;
129- lstrcat(exefile, ".exe");
129+ strcpy(exe_file, jar_file);
130+ exe_file[strlen(exe_file) - 4] = 0;
131+ strcat(exe_file, ".exe");
130132 }
131133
134+ if(GetFullPathName(exe_file, _MAX_PATH, buf, &ptr) == 0)
132135 {
133- char buf[_MAX_PATH];
134- char* p;
135-
136- if(GetFullPathName(exefile, _MAX_PATH, buf, &p) == 0)
137- {
138- printf("Invalid path: %s\n", exefile);
139- }
140- lstrcpy(exefile, buf);
136+ printf("Invalid path: %s\n", exe_file);
141137 }
142-
138+ strcpy(exe_file, buf);
143139
144140 if(opt['A'])
145141 {
@@ -170,40 +166,187 @@
170166 {
171167 sprintf(image_name, "IMAGE_CONSOLE_%d", architecture_bits);
172168 }
173- exeBuffer = GetResource(image_name, RT_RCDATA, &exeSize);
169+
170+ GetResource(image_name, &res);
171+ image_buf = res.buf;
172+ image_len = res.len;
174173
175- previousRevision = GetVersionRevision(exefile);
176- DeleteFile(exefile);
174+ previous_revision = get_version_revision(exe_file);
175+ DeleteFile(exe_file);
177176
178- CreateExeFile(exefile, exeBuffer, exeSize);
177+ b = create_exe_file(exe_file, image_buf, image_len, TRUE);
178+ if (b == FALSE)
179+ {
180+ goto EXIT;
181+ }
179182
180183 if(opt['t'])
181184 {
182- targetVersion = GetTargetJavaRuntimeVersion(opt['t']);
185+ target_version = get_target_java_runtime_version(opt['t']);
183186 }
184187 else
185188 {
186- targetVersion = 0x01050000; //default target version 1.5
189+ target_version = 0x01050000; //default target version 1.5
187190 }
188- targetVersionString = GetTargetJavaRuntimeVersionString(targetVersion);
189- printf("Target: %s (%d.%d.%d.%d)\n", targetVersionString + 4, targetVersion >> 24 & 0xFF, targetVersion >> 16 & 0xFF, targetVersion >> 8 & 0xFF, targetVersion & 0xFF);
190- SetResource(exefile, "TARGET_VERSION", RT_RCDATA, targetVersionString, 4);
191+ target_version_string = get_target_java_runtime_version_string(target_version, buf);
192+ printf("Target: %s (%d.%d.%d.%d)\n", target_version_string + 4, target_version >> 24 & 0xFF, target_version >> 16 & 0xFF, target_version >> 8 & 0xFF, target_version & 0xFF);
193+ set_resource(exe_file, "TARGET_VERSION", RT_RCDATA, target_version_string, 4);
191194
192195 if(opt['2'])
193196 {
194- disablePack200 = TRUE;
197+ disable_pack200 = TRUE;
195198 }
196199
197200 if(opt['L'] && *opt['L'] != '-' && *opt['L'] != '\0')
198201 {
199- SetResource(exefile, "EXTDIRS", RT_RCDATA, opt['L'], lstrlen(opt['L']) + 1);
202+ set_resource(exe_file, "EXTDIRS", RT_RCDATA, opt['L'], (DWORD)strlen(opt['L']) + 1);
200203 }
201204
202- enableJava = CreateJavaVM(NULL, FALSE, NULL) != NULL;
203- if(targetVersion >= 0x01050000 && enableJava && !disablePack200)
205+ enable_java = CreateJavaVM(NULL, FALSE, NULL) != NULL;
206+ if (enable_java)
204207 {
205- GetFileData(jarfile, &jarSize);
206- UsePack200(exefile, jarfile);
208+ LOAD_RESULT result;
209+ jbyteArray buf;
210+ jclass JarProcessor;
211+ jmethodID JarProcessor_init;
212+ jobject jarProcessor;
213+ jmethodID jarProcessor_getMainClass;
214+ jmethodID jarProcessor_getClassPath;
215+ jmethodID jarProcessor_getSplashScreenName;
216+ jmethodID jarProcessor_getSplashScreenImage;
217+ jmethodID jarProcessor_getBytes;
218+ char* main_class;
219+ char* class_path;
220+ char* splash_screen_name;
221+ BYTE* splash_screen_image;
222+ BYTE* bytes;
223+
224+ if (LoadMainClass(argc, argv, NULL, &result) == FALSE)
225+ {
226+ goto EXIT;
227+ }
228+ JarProcessor = result.MainClass;
229+
230+ jar_buf = get_jar_buf(jar_file, &jar_len);
231+ if (jar_buf == NULL)
232+ {
233+ goto EXIT;
234+ }
235+ buf = (*env)->NewByteArray(env, jar_len);
236+ if (buf == NULL)
237+ {
238+ goto EXIT;
239+ }
240+ (*env)->SetByteArrayRegion(env, buf, 0, jar_len, (jbyte*)jar_buf);
241+
242+ JarProcessor_init = (*env)->GetMethodID(env, JarProcessor, "<init>", "([BZ)V");
243+ if (JarProcessor_init == NULL)
244+ {
245+ result.msg_id = MSG_ID_ERR_GET_CONSTRUCTOR;
246+ printf(_(MSG_ID_ERR_GET_CONSTRUCTOR), "exewrap.tool.JarProcessor(byte[], boolean)");
247+ goto EXIT;
248+ }
249+ jarProcessor = (*env)->NewObject(env, JarProcessor, JarProcessor_init, buf, !disable_pack200);
250+ if (jarProcessor == NULL)
251+ {
252+ result.msg_id = MSG_ID_ERR_NEW_OBJECT;
253+ printf(_(MSG_ID_ERR_NEW_OBJECT), "exewrap.tool.JarProcessor(byte[], boolean)");
254+ goto EXIT;
255+ }
256+ jarProcessor_getMainClass = (*env)->GetMethodID(env, JarProcessor, "getMainClass", "()Ljava/lang/String;");
257+ if (jarProcessor_getMainClass == NULL)
258+ {
259+ result.msg_id = MSG_ID_ERR_GET_METHOD;
260+ printf(_(MSG_ID_ERR_GET_METHOD), "exewrap.tool.JarProcessor.getMainClass()");
261+ goto EXIT;
262+ }
263+ jarProcessor_getClassPath = (*env)->GetMethodID(env, JarProcessor, "getClassPath", "()Ljava/lang/String;");
264+ if (jarProcessor_getClassPath == NULL)
265+ {
266+ result.msg_id = MSG_ID_ERR_GET_METHOD;
267+ printf(_(MSG_ID_ERR_GET_METHOD), "exewrap.tool.JarProcessor.getClassPath()");
268+ goto EXIT;
269+ }
270+ jarProcessor_getSplashScreenName = (*env)->GetMethodID(env, JarProcessor, "getSplashScreenName", "()Ljava/lang/String;");
271+ if (jarProcessor_getSplashScreenName == NULL)
272+ {
273+ result.msg_id = MSG_ID_ERR_GET_METHOD;
274+ printf(_(MSG_ID_ERR_GET_METHOD), "exewrap.tool.JarProcessor.getSplashScreenName()");
275+ goto EXIT;
276+ }
277+ jarProcessor_getSplashScreenImage = (*env)->GetMethodID(env, JarProcessor, "getSplashScreenImage", "()[B");
278+ if (jarProcessor_getSplashScreenImage == NULL)
279+ {
280+ result.msg_id = MSG_ID_ERR_GET_METHOD;
281+ printf(_(MSG_ID_ERR_GET_METHOD), "exewrap.tool.JarProcessor.getSplashScreenImage()");
282+ goto EXIT;
283+ }
284+ jarProcessor_getBytes = (*env)->GetMethodID(env, JarProcessor, "getBytes", "()[B");
285+ if (jarProcessor_getBytes == NULL)
286+ {
287+ result.msg_id = MSG_ID_ERR_GET_METHOD;
288+ printf(_(MSG_ID_ERR_GET_METHOD), "exewrap.tool.JarProcessor.getBytes()");
289+ goto EXIT;
290+ }
291+
292+ main_class = GetShiftJIS(env, (*env)->CallObjectMethod(env, jarProcessor, jarProcessor_getMainClass));
293+ if (main_class == NULL)
294+ {
295+
296+ }
297+ set_resource(exe_file, "MAIN_CLASS", RT_RCDATA, main_class, (DWORD)strlen(main_class) + 1);
298+
299+ class_path = GetShiftJIS(env, (*env)->CallObjectMethod(env, jarProcessor, jarProcessor_getClassPath));
300+ if (class_path != NULL)
301+ {
302+ set_resource(exe_file, "CLASS_PATH", RT_RCDATA, class_path, (DWORD)strlen(class_path) + 1);
303+ }
304+
305+ splash_screen_name = GetShiftJIS(env, (*env)->CallObjectMethod(env, jarProcessor, jarProcessor_getSplashScreenName));
306+ if (splash_screen_name != NULL)
307+ {
308+ set_resource(exe_file, "SPLASH_SCREEN_NAME", RT_RCDATA, splash_screen_name, (DWORD)strlen(splash_screen_name) + 1);
309+ }
310+ buf = (*env)->CallObjectMethod(env, jarProcessor, jarProcessor_getSplashScreenImage);
311+ if (buf != NULL)
312+ {
313+ jboolean isCopy = 0;
314+ jint len;
315+ splash_screen_image = (*env)->GetByteArrayElements(env, buf, &isCopy);
316+ len = (*env)->GetArrayLength(env, buf);
317+ set_resource(exe_file, "SPLASH_SCREEN_IMAGE", RT_RCDATA, splash_screen_image, (DWORD)len);
318+ (*env)->ReleaseByteArrayElements(env, buf, splash_screen_image, 0);
319+ }
320+
321+ buf = (*env)->CallObjectMethod(env, jarProcessor, jarProcessor_getBytes);
322+ if (buf != NULL)
323+ {
324+ jboolean isCopy;
325+ jint len;
326+ bytes = (*env)->GetByteArrayElements(env, buf, &isCopy);
327+ len = (*env)->GetArrayLength(env, buf);
328+ set_resource(exe_file, (disable_pack200 ? "JAR" : "PACK_GZ"), RT_RCDATA, bytes, (DWORD)len);
329+ (*env)->ReleaseByteArrayElements(env, buf, bytes, 0);
330+ }
331+ }
332+ else
333+ {
334+ jar_buf = get_jar_buf(jar_file, &jar_len);
335+ if (jar_buf != NULL)
336+ {
337+ set_resource(exe_file, "JAR", RT_RCDATA, jar_buf, jar_len);
338+ }
339+ printf("Pack200: disable / JavaVM (%d-bit) not found.\r\n", GetProcessArchitecture());
340+ }
341+ /*
342+ if(target_version >= 0x01050000 && enable_java && !disable_pack200)
343+ {
344+ jar_buf = get_jar_buf(jar_file, &jar_len);
345+ if (jar_buf == NULL)
346+ {
347+ goto EXIT;
348+ }
349+ UsePack200(exe_file, jar_file);
207350 classBuffer = GetResource("PACK_LOADER", RT_RCDATA, &classSize);
208351 SetResource(exefile, "PACK_LOADER", RT_RCDATA, classBuffer, classSize);
209352 printf("Pack200: enable\r\n");
@@ -228,42 +371,43 @@
228371 printf("Pack200: disable\r\n");
229372 }
230373 }
374+ */
231375
232376 if(opt['e'] && *opt['e'] != '-' && *opt['e'] != '\0')
233377 {
234- SetResource(exefile, "EXTFLAGS", RT_RCDATA, opt['e'], lstrlen(opt['e']) + 1);
378+ set_resource(exe_file, "EXTFLAGS", RT_RCDATA, opt['e'], (DWORD)strlen(opt['e']) + 1);
235379 }
236380
237381 if(opt['a'] && *opt['a'] != '\0')
238382 {
239- SetResource(exefile, "VMARGS", RT_RCDATA, opt['a'], lstrlen(opt['a']) + 1);
383+ set_resource(exe_file, "VMARGS", RT_RCDATA, opt['a'], (DWORD)strlen(opt['a']) + 1);
240384 }
241385
242386 if(opt['i'] && *opt['i'] != '-' && *opt['i'] != '\0')
243387 {
244- SetApplicationIcon(exefile, opt['i']);
388+ set_application_icon(exe_file, opt['i']);
245389 }
246390
247391 if(opt['v'] && *opt['v'] != '-' && *opt['v'] != '\0')
248392 {
249- versionNumber = opt['v'];
393+ version_number = opt['v'];
250394 }
251395 else
252396 {
253- versionNumber = defaultVersion;
397+ version_number = DEFAULT_VERSION;
254398 }
255399
256400 if(opt['d'] && *opt['d'] != '-' && *opt['d'] != '\0')
257401 {
258- fileDescription = opt['d'];
402+ file_description = opt['d'];
259403 if(opt['s'])
260404 {
261- SetResource(exefile, "SVCDESC", RT_RCDATA, opt['d'], lstrlen(opt['d']) + 1);
405+ set_resource(exe_file, "SVCDESC", RT_RCDATA, opt['d'], (DWORD)strlen(opt['d']) + 1);
262406 }
263407 }
264408 else
265409 {
266- fileDescription = (char*)"";
410+ file_description = (char*)"";
267411 }
268412
269413 if(opt['c'] && *opt['c'] != '-' && *opt['c'] != '\0')
@@ -299,234 +443,149 @@
299443 }
300444 else
301445 {
302- product_version = defaultProductVersion;
446+ product_version = DEFAULT_PRODUCT_VERSION;
303447 }
304448
305- original_filename = strrchr(exefile, '\\') + 1;
306- newVersion = SetVersionInfo(exefile, versionNumber, previousRevision, fileDescription, copyright, company_name, product_name, product_version, original_filename, jarfile);
307- printf("%s (%d-bit) version %s\r\n", strrchr(exefile, '\\') + 1, architecture_bits, newVersion);
449+ original_filename = strrchr(exe_file, '\\') + 1;
450+ new_version = set_version_info(exe_file, version_number, previous_revision, file_description, copyright, company_name, product_name, product_version, original_filename, jar_file);
451+ printf("%s (%d-bit) version %s\r\n", strrchr(exe_file, '\\') + 1, architecture_bits, new_version);
308452
309- return 0;
310-}
311-
312-DWORD GetVersionRevision(char* filename)
313-{
314- /* GetFileVersionInfoSize, GetFileVersionInfo を使うと内部で LoadLibrary が使用されるらしく
315- * その後のリソース書き込みがうまくいかなくなるようです。なので、自力で EXEファイルから
316- * リビジョンナンバーを取り出すように変更しました。
317- */
318- DWORD revision = 0;
319- HANDLE hFile;
320- char HEADER[] = "VS_VERSION_INFO";
321- int len;
322- char* buf;
323- DWORD size;
324- unsigned int i;
325- int j;
326-
327- buf = (char*)HeapAlloc(GetProcessHeap(), 0, 8192);
328-
329- if((hFile = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
453+EXIT:
454+ if (env != NULL)
330455 {
331- return 0;
332- }
333-
334- SetFilePointer(hFile, -1 * 8192, 0, FILE_END);
335- ReadFile(hFile, buf, 8192, &size, NULL);
336- CloseHandle(hFile);
337-
338- len = lstrlen(HEADER);
339- for(i = 0; i < size - len; i++)
340- {
341- for(j = 0; j < len; j++)
456+ if ((*env)->ExceptionCheck(env) == JNI_TRUE)
342457 {
343- if(buf[i + j * 2] != HEADER[j]) break;
458+ (*env)->ExceptionDescribe(env);
459+ (*env)->ExceptionClear(env);
344460 }
345- if(j == lstrlen(HEADER))
346- {
347- revision = ((buf[i + 47] << 8) & 0xFF00) | ((buf[i + 46] ) & 0x00FF);
348- }
461+ DetachJavaVM();
349462 }
350- HeapFree(GetProcessHeap(), 0, buf);
351- return revision;
463+ if (jvm != NULL)
464+ {
465+ DestroyJavaVM();
466+ }
467+ ExitProcess(0);
352468 }
353469
354-char* SetVersionInfo(LPCTSTR filename, char* versionNumber, DWORD previousRevision, char* fileDescription, char* copyright, char* company_name, char* product_name, char* product_version, char* original_filename, char* jarfile)
470+
471+void UsePack200(LPCTSTR exefile, LPCTSTR jarfile)
355472 {
356- int i;
357- int SIZE_VERSION = 48;
358- int SIZE_TEXT = 256;
359- int ADDR_COMPANY_NAME = 0x00B8;
360- int ADDR_FILE_DESCRIPTION = 0x01E4;
361- int ADDR_FILE_VERSION = 0x0308;
362- int ADDR_INTERNAL_NAME = 0x0358;
363- int ADDR_COPYRIGHT = 0x0480;
364- int ADDR_ORIGINAL_FILENAME = 0x05AC;
365- int ADDR_PRODUCT_NAME = 0x06D0;
366- int ADDR_PRODUCT_VERSION = 0x07F8;
367- char* internalName;
368- char file_version[48];
369- char buffer[260];
370- char* tmp;
371- char* versioninfoBuffer = NULL;
372- DWORD versioninfoSize;
373- short file_version_major;
374- short file_version_minor;
375- short file_version_build;
376- short file_version_revision;
377- short product_version_major;
378- short product_version_minor;
379- short product_version_build;
380- short product_version_revision;
381- char* newVersion;
473+ /*
474+ DWORD size;
475+ char* buf;
476+ jclass optimizerClass;
477+ jmethodID optimizerInit;
478+ jobject optimizer;
479+ jmethodID getRelativeClassPath;
480+ jmethodID getClassesPackGz;
481+ jmethodID getResourcesGz;
482+ jmethodID getSplashPath;
483+ jmethodID getSplashImage;
484+ jbyteArray relativeClassPath;
485+ jbyteArray classesPackGz;
486+ jbyteArray resourcesGz;
487+ jbyteArray splashPath;
488+ jbyteArray splashImage;
382489
383- if(strrchr(jarfile, '\\') != NULL)
490+ buf = GetResource("JAR_OPTIMIZER", RT_RCDATA, &size);
491+
492+ optimizerClass = (*env)->DefineClass(env, "JarOptimizer", NULL, (jbyte*)buf, size);
493+ if(optimizerClass == NULL)
384494 {
385- internalName = strrchr(jarfile, '\\') + 1;
495+ return;
386496 }
387- else
497+ optimizerInit = (*env)->GetMethodID(env, optimizerClass, "<init>", "(Ljava/lang/String;)V");
498+ if(optimizerInit == NULL)
388499 {
389- internalName = jarfile;
500+ return;
390501 }
391-
392- lstrcpy(buffer, versionNumber);
393- lstrcat(buffer, ".0.0.0.0");
394- file_version_major = atoi(strtok(buffer, "."));
395- file_version_minor = atoi(strtok(NULL, "."));
396- file_version_build = atoi(strtok(NULL, "."));
397- file_version_revision = atoi(strtok(NULL, "."));
398-
399- lstrcpy(buffer, product_version);
400- lstrcat(buffer, ".0.0.0.0");
401- product_version_major = atoi(strtok(buffer, "."));
402- product_version_minor = atoi(strtok(NULL, "."));
403- product_version_build = atoi(strtok(NULL, "."));
404- product_version_revision = atoi(strtok(NULL, "."));
405-
406- // revison が明示的に指定されていなかった場合、既存ファイルから取得した値に 1 を加算して revision とする。
407- lstrcpy(buffer, versionNumber);
408- if(strtok(buffer, ".") != NULL)
502+
503+ optimizer = (*env)->NewObject(env, optimizerClass, optimizerInit, GetJString(env, jarfile));
504+ if(optimizer == NULL)
409505 {
410- if(strtok(NULL, ".") != NULL)
411- {
412- if(strtok(NULL, ".") != NULL)
413- {
414- if(strtok(NULL, ".") != NULL)
415- {
416- previousRevision = file_version_revision - 1;
417- }
418- }
419- }
506+ (*env)->ExceptionDescribe(env);
507+ (*env)->ExceptionClear(env);
508+ return;
420509 }
421-
422- file_version_revision = (short)previousRevision + 1;
423- // build 加算判定ここまで。
424- sprintf(file_version, "%d.%d.%d.%d", file_version_major, file_version_minor, file_version_build, file_version_revision);
425-
426- tmp = GetResource("VERSION_INFO", RT_RCDATA, &versioninfoSize);
427- versioninfoBuffer = (char*)HeapAlloc(GetProcessHeap(), 0, versioninfoSize);
428- CopyMemory(versioninfoBuffer, tmp, versioninfoSize);
429-
430- //FILEVERSION
431- versioninfoBuffer[48] = file_version_minor & 0xFF;
432- versioninfoBuffer[49] = (file_version_minor >> 8) & 0xFF;
433- versioninfoBuffer[50] = file_version_major & 0xFF;
434- versioninfoBuffer[51] = (file_version_major >> 8) & 0xFF;
435- versioninfoBuffer[52] = file_version_revision & 0xFF;
436- versioninfoBuffer[53] = (file_version_revision >> 8) & 0xFF;
437- versioninfoBuffer[54] = file_version_build & 0xFF;
438- versioninfoBuffer[55] = (file_version_build >> 8) & 0xFF;
439- //PRODUCTVERSION
440- versioninfoBuffer[56] = product_version_minor & 0xFF;
441- versioninfoBuffer[57] = (product_version_minor >> 8) & 0xFF;
442- versioninfoBuffer[58] = product_version_major & 0xFF;
443- versioninfoBuffer[59] = (product_version_major >> 8) & 0xFF;
444- versioninfoBuffer[60] = product_version_revision & 0xFF;
445- versioninfoBuffer[61] = (product_version_revision >> 8) & 0xFF;
446- versioninfoBuffer[62] = product_version_build & 0xFF;
447- versioninfoBuffer[63] = (product_version_build >> 8) & 0xFF;
448-
449- SecureZeroMemory(buffer, sizeof(char) * 260);
450- MultiByteToWideChar(CP_ACP, 0, company_name, lstrlen(company_name), (WCHAR*)buffer, 128);
451- for(i = 0; i < SIZE_TEXT; i++)
510+ getRelativeClassPath = (*env)->GetMethodID(env, optimizerClass, "getRelativeClassPath", "()[B");
511+ if(getRelativeClassPath == NULL)
452512 {
453- versioninfoBuffer[ADDR_COMPANY_NAME + i] = buffer[i];
513+ return;
454514 }
455-
456- SecureZeroMemory(buffer, sizeof(char) * 260);
457- MultiByteToWideChar(CP_ACP, 0, fileDescription, lstrlen(fileDescription), (WCHAR*)buffer, 128);
458- for(i = 0; i < SIZE_TEXT; i++)
515+ getClassesPackGz = (*env)->GetMethodID(env, optimizerClass, "getClassesPackGz", "()[B");
516+ if(getClassesPackGz == NULL)
459517 {
460- versioninfoBuffer[ADDR_FILE_DESCRIPTION + i] = buffer[i];
518+ return;
461519 }
462-
463- SecureZeroMemory(buffer, sizeof(char) * 260);
464- MultiByteToWideChar(CP_ACP, 0, file_version, lstrlen(file_version), (WCHAR*)buffer, 128);
465- for(i = 0; i < SIZE_VERSION; i++)
520+ getResourcesGz = (*env)->GetMethodID(env, optimizerClass, "getResourcesGz", "()[B");
521+ if(getResourcesGz == NULL)
466522 {
467- versioninfoBuffer[ADDR_FILE_VERSION + i] = buffer[i];
523+ return;
468524 }
469-
470- SecureZeroMemory(buffer, sizeof(char) * 260);
471- MultiByteToWideChar(CP_ACP, 0, internalName, lstrlen(internalName), (WCHAR*)buffer, 128);
472- for(i = 0; i < SIZE_TEXT; i++)
525+ getSplashPath = (*env)->GetMethodID(env, optimizerClass, "getSplashPath", "()[B");
526+ if(getSplashPath == NULL)
473527 {
474- versioninfoBuffer[ADDR_INTERNAL_NAME + i] = buffer[i];
528+ return;
475529 }
476-
477- SecureZeroMemory(buffer, sizeof(char) * 260);
478- MultiByteToWideChar(CP_ACP, 0, copyright, lstrlen(copyright), (WCHAR*)buffer, 128);
479- for(i = 0; i < SIZE_TEXT; i++)
530+ getSplashImage = (*env)->GetMethodID(env, optimizerClass, "getSplashImage", "()[B");
531+ if(getSplashImage == NULL)
480532 {
481- versioninfoBuffer[ADDR_COPYRIGHT + i] = buffer[i];
533+ return;
482534 }
483-
484- SecureZeroMemory(buffer, sizeof(char) * 260);
485- MultiByteToWideChar(CP_ACP, 0, original_filename, lstrlen(original_filename), (WCHAR*)buffer, 128);
486- for(i = 0; i < SIZE_TEXT; i++)
535+ relativeClassPath = (jbyteArray)((*env)->CallObjectMethod(env, optimizer, getRelativeClassPath));
536+ if(relativeClassPath != NULL)
487537 {
488- versioninfoBuffer[ADDR_ORIGINAL_FILENAME + i] = buffer[i];
538+ size = (*env)->GetArrayLength(env, relativeClassPath);
539+ buf = (char*)((*env)->GetByteArrayElements(env, relativeClassPath, NULL));
540+ SetResource(exefile, "RELATIVE_CLASSPATH", RT_RCDATA, buf, size);
489541 }
490-
491- SecureZeroMemory(buffer, sizeof(char) * 260);
492- MultiByteToWideChar(CP_ACP, 0, product_name, lstrlen(product_name), (WCHAR*)buffer, 128);
493- for(i = 0; i < SIZE_TEXT; i++)
542+ classesPackGz = (jbyteArray)((*env)->CallObjectMethod(env, optimizer, getClassesPackGz));
543+ if(classesPackGz != NULL)
494544 {
495- versioninfoBuffer[ADDR_PRODUCT_NAME + i] = buffer[i];
545+ size = (*env)->GetArrayLength(env, classesPackGz);
546+ buf = (char*)((*env)->GetByteArrayElements(env, classesPackGz, NULL));
547+ SetResource(exefile, "CLASSES_PACK_GZ", RT_RCDATA, buf, size);
496548 }
497-
498- SecureZeroMemory(buffer, sizeof(char) * 260);
499- MultiByteToWideChar(CP_ACP, 0, product_version, lstrlen(product_version), (WCHAR*)buffer, 128);
500- for(i = 0; i < SIZE_VERSION; i++)
549+ resourcesGz = (jbyteArray)((*env)->CallObjectMethod(env, optimizer, getResourcesGz));
550+ if(resourcesGz != NULL)
501551 {
502- versioninfoBuffer[ADDR_PRODUCT_VERSION + i] = buffer[i];
552+ size = (*env)->GetArrayLength(env, resourcesGz);
553+ buf = (char*)((*env)->GetByteArrayElements(env, resourcesGz, NULL));
554+ SetResource(exefile, "RESOURCES_GZ", RT_RCDATA, buf, size);
503555 }
504-
505- SetResource(filename, (LPCTSTR)VS_VERSION_INFO, RT_VERSION, versioninfoBuffer, versioninfoSize);
506-
507- newVersion = (char*)HeapAlloc(GetProcessHeap(), 0, 128);
508- sprintf(newVersion, "%d.%d.%d.%d", file_version_major, file_version_minor, file_version_build, file_version_revision);
556+ splashPath = (jbyteArray)((*env)->CallObjectMethod(env, optimizer, getSplashPath));
557+ if(splashPath != NULL)
558+ {
559+ size = (*env)->GetArrayLength(env, splashPath);
560+ buf = (char*)((*env)->GetByteArrayElements(env, splashPath, NULL));
561+ SetResource(exefile, "SPLASH_PATH", RT_RCDATA, buf, size);
562+ }
563+ splashImage = (jbyteArray)((*env)->CallObjectMethod(env, optimizer, getSplashImage));
564+ if(splashImage != NULL)
565+ {
566+ size = (*env)->GetArrayLength(env, splashImage);
567+ buf = (char*)((*env)->GetByteArrayElements(env, splashImage, NULL));
568+ SetResource(exefile, "SPLASH_IMAGE", RT_RCDATA, buf, size);
569+ }
570+ */
571+}
509572
510- HeapFree(GetProcessHeap(), 0, versioninfoBuffer);
511573
512- return newVersion;
513-}
514-
515-char** ParseOption(int argc, char* argv[])
574+static char** parse_opt(int argc, char* argv[])
516575 {
517576 char** opt = (char**)HeapAlloc(GetProcessHeap(), 0, 256 * 8);
518-
577+
519578 SecureZeroMemory(opt, 256 * 8);
520579
521- if((argc > 1) && (*argv[1] != '-'))
580+ if ((argc > 1) && (*argv[1] != '-'))
522581 {
523582 opt[0] = argv[1];
524583 }
525- while(*++argv)
584+ while (*++argv)
526585 {
527- if(*argv[0] == '-')
586+ if (*argv[0] == '-')
528587 {
529- if(argv[1] == NULL)
588+ if (argv[1] == NULL)
530589 {
531590 opt[*(argv[0] + 1)] = (char*)"";
532591 }
@@ -537,7 +596,7 @@
537596 }
538597 }
539598 argv--;
540- if((opt[0] == NULL) && (*argv[0] != '-'))
599+ if ((opt[0] == NULL) && (*argv[0] != '-'))
541600 {
542601 opt[0] = argv[0];
543602 }
@@ -545,201 +604,114 @@
545604 return opt;
546605 }
547606
548-char* GetResource(LPCTSTR name, LPCTSTR type, DWORD* size)
607+
608+static DWORD get_version_revision(char* filename)
549609 {
550- HRSRC hrsrc;
610+ /* GetFileVersionInfoSize, GetFileVersionInfo を使うと内部で LoadLibrary が使用されるらしく
611+ * その後のリソース書き込みがうまくいかなくなるようです。なので、自力で EXEファイルから
612+ * リビジョンナンバーを取り出すように変更しました。
613+ */
614+ DWORD revision = 0;
615+ HANDLE hFile;
616+ char HEADER[] = "VS_VERSION_INFO";
617+ size_t len;
618+ BYTE* buf = NULL;
619+ DWORD size;
620+ unsigned int i;
621+ size_t j;
551622
552- if((hrsrc = FindResource(NULL, name, type)) == NULL)
623+ buf = (BYTE*)malloc(8192);
624+
625+ hFile = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
626+ if (hFile == INVALID_HANDLE_VALUE)
553627 {
554- printf("Fail to FindResource: %s\n", name);
555- ExitProcess(0);
628+ goto EXIT;
556629 }
557- *size = SizeofResource(NULL, hrsrc);
558- return (char*)LockResource(LoadResource(NULL, hrsrc));
559-}
560630
561-void SetResource(LPCTSTR filename, LPCTSTR rscName, LPCTSTR rscType, char* rscData, DWORD rscSize)
562-{
563- HANDLE hRes;
564- BOOL ret1;
565- BOOL ret2;
566- int i;
631+ SetFilePointer(hFile, -1 * 8192, 0, FILE_END);
632+ ReadFile(hFile, buf, 8192, &size, NULL);
633+ CloseHandle(hFile);
567634
568- for (i = 0; i < 100; i++)
635+ len = strlen(HEADER);
636+ for (i = 0; i < size - len; i++)
569637 {
570- ret1 = FALSE;
571- ret2 = FALSE;
572- hRes = BeginUpdateResource(filename, FALSE);
573- if (hRes != NULL)
638+ for (j = 0; j < len; j++)
574639 {
575- ret1 = UpdateResource(hRes, rscType, rscName, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), rscData, rscSize);
576- ret2 = EndUpdateResource(hRes, FALSE);
640+ if (buf[i + j * 2] != HEADER[j]) break;
577641 }
578- if(ret1 && ret2)
642+ if (j == strlen(HEADER))
579643 {
580- break;
644+ revision = ((buf[i + 47] << 8) & 0xFF00) | ((buf[i + 46]) & 0x00FF);
581645 }
582- Sleep(100);
583646 }
584- if(ret1 == FALSE || ret2 == FALSE)
647+
648+EXIT:
649+ if (buf != NULL)
585650 {
586- printf("Failed to update resource: %s: %s\n", filename, rscName);
587- ExitProcess(0);
651+ free(buf);
588652 }
589- CloseHandle(hRes);
653+ return revision;
590654 }
591655
592-void CreateExeFile(LPCTSTR filename, char* data, DWORD size)
656+
657+static BOOL create_exe_file(const char* filename, BYTE* image_buf, DWORD image_len, BOOL is_reverse)
593658 {
594659 HANDLE hFile;
595- DWORD writeSize;
660+ BYTE* buf = NULL;
661+ DWORD write_size;
596662
597- if((hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
663+ hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
664+ if (hFile == INVALID_HANDLE_VALUE)
598665 {
599- if((hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
666+ hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
667+ if (hFile == INVALID_HANDLE_VALUE)
600668 {
601669 printf("Failed to create file: %s\n", filename);
602- ExitProcess(0);
670+ return FALSE;
603671 }
604672 }
605673
606- while(size > 0)
674+ if (is_reverse)
607675 {
608- if(WriteFile(hFile, data, size, &writeSize, NULL) == 0)
676+ DWORD i;
677+ buf = (BYTE*)malloc(image_len);
678+ for (i = 0; i < image_len; i++)
609679 {
610- printf("Failed to write: %s\n", filename);
611- ExitProcess(0);
680+ buf[i] = ~image_buf[image_len - 1 - i];
612681 }
613- data += writeSize;
614- size -= writeSize;
682+ image_buf = buf;
615683 }
616- CloseHandle(hFile);
617-}
618-
619-char* GetFileData(LPCTSTR filename, DWORD* size)
620-{
621- HANDLE hFile;
622- char* buf;
623- char* p;
624- DWORD r;
625- DWORD readSize;
626-
627- if((hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
684+ else
628685 {
629- printf("Failed to read file: %s\n", filename);
630- ExitProcess(0);
686+ buf = image_buf;
631687 }
632- *size = GetFileSize(hFile, NULL);
633- p = buf = (char*)HeapAlloc(GetProcessHeap(), 0, *size);
634688
635- r = *size;
636- while(r > 0)
689+ while (image_len > 0)
637690 {
638- if(ReadFile(hFile, p, r, &readSize, NULL) == 0)
691+ if (WriteFile(hFile, image_buf, image_len, &write_size, NULL) == 0)
639692 {
640- printf("Failed to read: %s\n", filename);
641- HeapFree(GetProcessHeap(), 0, buf);
642- ExitProcess(0);
693+ printf("Failed to write: %s\n", filename);
694+ return FALSE;
643695 }
644- p += readSize;
645- r -= readSize;
696+ image_buf += write_size;
697+ image_len -= write_size;
646698 }
647699 CloseHandle(hFile);
648700
649- return buf;
650-}
651-
652-void SetApplicationIcon(LPCTSTR filename, LPCTSTR iconfile)
653-{
654- void *pvFile;
655- DWORD nSize;
656- int f, z;
657- ICONDIR id, *pid;
658- GRPICONDIR *pgid;
659- HANDLE hResource;
660- BOOL ret1;
661- BOOL ret2;
662- BOOL ret3;
663- int i;
664-
665- //Delete default icon.
666- for(z = 0; z < 99; z++)
701+EXIT:
702+ if (is_reverse)
667703 {
668- hResource = BeginUpdateResource(filename, FALSE);
669- ret1 = UpdateResource(hResource, RT_ICON, MAKEINTRESOURCE(z + 1), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0);
670- EndUpdateResource(hResource, FALSE);
671- if(ret1 == FALSE)
704+ if (buf != NULL)
672705 {
673- break;
706+ free(buf);
674707 }
675708 }
676709
677- //Delete default icon group.
678- {
679- hResource = BeginUpdateResource(filename, FALSE);
680- UpdateResource(hResource, RT_GROUP_ICON, MAKEINTRESOURCE(1), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0);
681- EndUpdateResource(hResource, FALSE);
682- }
683-
684- if(!lstrlen(iconfile))
685- {
686- return;
687- }
688- if((f = _lopen(iconfile, OF_READ)) == -1)
689- {
690- return;
691- }
692-
693- for(i = 0; i < 100; i++)
694- {
695- ret1 = FALSE;
696- ret2 = FALSE;
697- ret3 = FALSE;
698- hResource = BeginUpdateResource(filename, FALSE);
699-
700- _lread(f, &id, sizeof(id));
701- _llseek(f, 0, SEEK_SET);
702- pid = (ICONDIR *)HeapAlloc(GetProcessHeap(), 0, sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * (id.idCount - 1));
703- pgid = (GRPICONDIR *)HeapAlloc(GetProcessHeap(), 0, sizeof(GRPICONDIR) + sizeof(GRPICONDIRENTRY) * (id.idCount - 1));
704- _lread(f, pid, sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * (id.idCount - 1));
705- memcpy(pgid, pid, sizeof(GRPICONDIR));
706-
707- for(z = 0; z < id.idCount; z++)
708- {
709- pgid->idEntries[z].common = pid->idEntries[z].common;
710- pgid->idEntries[z].nID = z + 1;
711- nSize = pid->idEntries[z].common.dwBytesInRes;
712- pvFile = HeapAlloc(GetProcessHeap(), 0, nSize);
713- if(!pvFile)
714- {
715- _lclose(f);
716- return;
717- }
718- _llseek(f, pid->idEntries[z].dwImageOffset, SEEK_SET);
719- _lread(f, pvFile, nSize);
720- ret1 = UpdateResource(hResource, RT_ICON, MAKEINTRESOURCE(z + 1), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), pvFile, nSize);
721- HeapFree(GetProcessHeap(), 0, pvFile);
722- }
723- nSize = sizeof(GRPICONDIR) + sizeof(GRPICONDIRENTRY) * (id.idCount - 1);
724- ret2 = UpdateResource(hResource, RT_GROUP_ICON, MAKEINTRESOURCE(1), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), pgid, nSize);
725- _lclose(f);
726-
727- ret3 = EndUpdateResource(hResource, FALSE);
728- if(ret1 && ret2 && ret3)
729- {
730- break;
731- }
732- Sleep(100);
733- }
734- if(ret1 == FALSE || ret2 == FALSE || ret3 == FALSE)
735- {
736- printf("Failed to set icon\n");
737- return;
738- }
739- CloseHandle(hResource);
710+ return TRUE;
740711 }
741712
742-DWORD GetTargetJavaRuntimeVersion(char* version)
713+
714+static DWORD get_target_java_runtime_version(char* version)
743715 {
744716 char* p = version;
745717 DWORD major = 0;
@@ -746,17 +718,17 @@
746718 DWORD minor = 0;
747719 DWORD build = 0;
748720 DWORD revision = 0;
749-
750- if(p != NULL)
721+
722+ if (p != NULL)
751723 {
752724 major = atoi(p);
753- if((p = strstr(p, ".")) != NULL)
725+ if ((p = strstr(p, ".")) != NULL)
754726 {
755727 minor = atoi(++p);
756- if((p = strstr(p, ".")) != NULL)
728+ if ((p = strstr(p, ".")) != NULL)
757729 {
758730 build = atoi(++p);
759- if((p = strstr(p, ".")) != NULL)
731+ if ((p = strstr(p, ".")) != NULL)
760732 {
761733 revision = atoi(++p);
762734 }
@@ -767,20 +739,20 @@
767739 return 0x00000000;
768740 }
769741
770-LPTSTR GetTargetJavaRuntimeVersionString(DWORD version)
742+
743+static char* get_target_java_runtime_version_string(DWORD version, char* buf)
771744 {
772745 DWORD major = version >> 24 & 0xFF;
773746 DWORD minor = version >> 16 & 0xFF;
774747 DWORD build = version >> 8 & 0xFF;
775748 DWORD revision = version & 0xFF;
776- LPTSTR buf = (LPTSTR)HeapAlloc(GetProcessHeap(), 0, 64);
777749
778750 *(DWORD*)buf = version;
779751
780752 //1.5, 1.6
781- if(major == 1 && (minor == 5 || minor == 6))
753+ if (major == 1 && (minor == 5 || minor == 6))
782754 {
783- if(revision == 0)
755+ if (revision == 0)
784756 {
785757 sprintf(buf + 4, "Java %d.%d", minor, build);
786758 }
@@ -792,11 +764,11 @@
792764 }
793765
794766 //1.2, 1.3, 1.4
795- if(major == 1 && (minor == 2 || minor == 3 || minor == 4))
767+ if (major == 1 && (minor == 2 || minor == 3 || minor == 4))
796768 {
797- if(revision == 0)
769+ if (revision == 0)
798770 {
799- if(build == 0)
771+ if (build == 0)
800772 {
801773 sprintf(buf + 4, "Java2 %d.%d", major, minor);
802774 }
@@ -813,11 +785,11 @@
813785 }
814786
815787 //1.0, 1.1
816- if(major == 1 && (minor == 0 || minor == 1))
788+ if (major == 1 && (minor == 0 || minor == 1))
817789 {
818- if(revision == 0)
790+ if (revision == 0)
819791 {
820- if(build == 0)
792+ if (build == 0)
821793 {
822794 sprintf(buf + 4, "Java %d.%d", major, minor);
823795 }
@@ -834,7 +806,7 @@
834806 }
835807
836808 //other
837- if(revision == 0)
809+ if (revision == 0)
838810 {
839811 sprintf(buf + 4, "Java %d.%d.%d", major, minor, build);
840812 }
@@ -845,102 +817,335 @@
845817 return buf;
846818 }
847819
848-void UsePack200(LPCTSTR exefile, LPCTSTR jarfile)
820+
821+static void set_resource(const char* filename, const char* rsc_name, const char* rsc_type, BYTE* rsc_data, DWORD rsc_size)
849822 {
850- DWORD size;
851- char* buf;
852- jclass optimizerClass;
853- jmethodID optimizerInit;
854- jobject optimizer;
855- jmethodID getRelativeClassPath;
856- jmethodID getClassesPackGz;
857- jmethodID getResourcesGz;
858- jmethodID getSplashPath;
859- jmethodID getSplashImage;
860- jbyteArray relativeClassPath;
861- jbyteArray classesPackGz;
862- jbyteArray resourcesGz;
863- jbyteArray splashPath;
864- jbyteArray splashImage;
823+ HANDLE hRes;
824+ BOOL ret1;
825+ BOOL ret2;
826+ int i;
865827
866- buf = GetResource("JAR_OPTIMIZER", RT_RCDATA, &size);
828+ for (i = 0; i < 100; i++)
829+ {
830+ ret1 = FALSE;
831+ ret2 = FALSE;
832+ hRes = BeginUpdateResource(filename, FALSE);
833+ if (hRes != NULL)
834+ {
835+ ret1 = UpdateResource(hRes, rsc_type, rsc_name, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), rsc_data, rsc_size);
836+ ret2 = EndUpdateResource(hRes, FALSE);
837+ }
838+ if (ret1 && ret2)
839+ {
840+ break;
841+ }
842+ Sleep(100);
843+ }
844+ if (ret1 == FALSE || ret2 == FALSE)
845+ {
846+ printf("Failed to update resource: %s: %s\n", filename, rsc_name);
847+ ExitProcess(0);
848+ }
849+ CloseHandle(hRes);
850+}
867851
868- optimizerClass = (*env)->DefineClass(env, "JarOptimizer", NULL, (jbyte*)buf, size);
869- if(optimizerClass == NULL)
852+
853+static BYTE* get_jar_buf(const char* jar_file, DWORD* jar_len)
854+{
855+ HANDLE hFile;
856+ char* buf;
857+ char* p;
858+ DWORD r;
859+ DWORD read_size;
860+
861+ hFile = CreateFile(jar_file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
862+ if (hFile == INVALID_HANDLE_VALUE)
870863 {
871- return;
864+ printf("Failed to read file: %s\n", jar_file);
865+ buf = NULL;
866+ goto EXIT;
872867 }
873- optimizerInit = (*env)->GetMethodID(env, optimizerClass, "<init>", "(Ljava/lang/String;)V");
874- if(optimizerInit == NULL)
868+ *jar_len = GetFileSize(hFile, NULL);
869+ p = buf = (BYTE*)malloc(*jar_len);
870+
871+ r = *jar_len;
872+ while (r > 0)
875873 {
876- return;
874+ if (ReadFile(hFile, p, r, &read_size, NULL) == 0)
875+ {
876+ printf("Failed to read: %s\n", jar_file);
877+ free(buf);
878+ buf = NULL;
879+ goto EXIT;
880+ }
881+ p += read_size;
882+ r -= read_size;
877883 }
884+ CloseHandle(hFile);
878885
879- optimizer = (*env)->NewObject(env, optimizerClass, optimizerInit, GetJString(env, jarfile));
880- if(optimizer == NULL)
886+EXIT:
887+ return buf;
888+}
889+
890+
891+static void set_application_icon(const char* filename, const char* icon_file)
892+{
893+ void* pvFile;
894+ DWORD nSize;
895+ int f, z;
896+ ICONDIR id, *pid;
897+ GRPICONDIR *pgid;
898+ HANDLE hResource;
899+ BOOL ret1;
900+ BOOL ret2;
901+ BOOL ret3;
902+ int i;
903+
904+ //Delete default icon.
905+ for (z = 0; z < 99; z++)
881906 {
882- (*env)->ExceptionDescribe(env);
883- (*env)->ExceptionClear(env);
884- return;
907+ hResource = BeginUpdateResource(filename, FALSE);
908+ ret1 = UpdateResource(hResource, RT_ICON, MAKEINTRESOURCE(z + 1), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0);
909+ EndUpdateResource(hResource, FALSE);
910+ if (ret1 == FALSE)
911+ {
912+ break;
913+ }
885914 }
886- getRelativeClassPath = (*env)->GetMethodID(env, optimizerClass, "getRelativeClassPath", "()[B");
887- if(getRelativeClassPath == NULL)
915+
916+ //Delete default icon group.
888917 {
889- return;
918+ hResource = BeginUpdateResource(filename, FALSE);
919+ UpdateResource(hResource, RT_GROUP_ICON, MAKEINTRESOURCE(1), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0);
920+ EndUpdateResource(hResource, FALSE);
890921 }
891- getClassesPackGz = (*env)->GetMethodID(env, optimizerClass, "getClassesPackGz", "()[B");
892- if(getClassesPackGz == NULL)
922+
923+ if (!strlen(icon_file))
893924 {
894925 return;
895926 }
896- getResourcesGz = (*env)->GetMethodID(env, optimizerClass, "getResourcesGz", "()[B");
897- if(getResourcesGz == NULL)
927+ if ((f = _lopen(icon_file, OF_READ)) == -1)
898928 {
899929 return;
900930 }
901- getSplashPath = (*env)->GetMethodID(env, optimizerClass, "getSplashPath", "()[B");
902- if(getSplashPath == NULL)
931+
932+ for (i = 0; i < 100; i++)
903933 {
904- return;
934+ ret1 = FALSE;
935+ ret2 = FALSE;
936+ ret3 = FALSE;
937+ hResource = BeginUpdateResource(filename, FALSE);
938+
939+ _lread(f, &id, sizeof(id));
940+ _llseek(f, 0, SEEK_SET);
941+ pid = (ICONDIR *)HeapAlloc(GetProcessHeap(), 0, sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * (id.idCount - 1));
942+ pgid = (GRPICONDIR *)HeapAlloc(GetProcessHeap(), 0, sizeof(GRPICONDIR) + sizeof(GRPICONDIRENTRY) * (id.idCount - 1));
943+ _lread(f, pid, sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * (id.idCount - 1));
944+ memcpy(pgid, pid, sizeof(GRPICONDIR));
945+
946+ for (z = 0; z < id.idCount; z++)
947+ {
948+ pgid->idEntries[z].common = pid->idEntries[z].common;
949+ pgid->idEntries[z].nID = z + 1;
950+ nSize = pid->idEntries[z].common.dwBytesInRes;
951+ pvFile = HeapAlloc(GetProcessHeap(), 0, nSize);
952+ if (!pvFile)
953+ {
954+ _lclose(f);
955+ return;
956+ }
957+ _llseek(f, pid->idEntries[z].dwImageOffset, SEEK_SET);
958+ _lread(f, pvFile, nSize);
959+ ret1 = UpdateResource(hResource, RT_ICON, MAKEINTRESOURCE(z + 1), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), pvFile, nSize);
960+ HeapFree(GetProcessHeap(), 0, pvFile);
961+ }
962+ nSize = sizeof(GRPICONDIR) + sizeof(GRPICONDIRENTRY) * (id.idCount - 1);
963+ ret2 = UpdateResource(hResource, RT_GROUP_ICON, MAKEINTRESOURCE(1), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), pgid, nSize);
964+ _lclose(f);
965+
966+ ret3 = EndUpdateResource(hResource, FALSE);
967+ if (ret1 && ret2 && ret3)
968+ {
969+ break;
970+ }
971+ Sleep(100);
905972 }
906- getSplashImage = (*env)->GetMethodID(env, optimizerClass, "getSplashImage", "()[B");
907- if(getSplashImage == NULL)
973+ if (ret1 == FALSE || ret2 == FALSE || ret3 == FALSE)
908974 {
975+ printf("Failed to set icon\n");
909976 return;
910977 }
911- relativeClassPath = (jbyteArray)((*env)->CallObjectMethod(env, optimizer, getRelativeClassPath));
912- if(relativeClassPath != NULL)
978+ CloseHandle(hResource);
979+}
980+
981+
982+static char* set_version_info(const char* filename, const char* version_number, DWORD previous_revision, char* file_description, char* copyright, char* company_name, char* product_name, char* product_version, char* original_filename, char* jar_file)
983+{
984+ int i;
985+ int SIZE_VERSION = 48;
986+ int SIZE_TEXT = 256;
987+ int ADDR_COMPANY_NAME = 0x00B8;
988+ int ADDR_FILE_DESCRIPTION = 0x01E4;
989+ int ADDR_FILE_VERSION = 0x0308;
990+ int ADDR_INTERNAL_NAME = 0x0358;
991+ int ADDR_COPYRIGHT = 0x0480;
992+ int ADDR_ORIGINAL_FILENAME = 0x05AC;
993+ int ADDR_PRODUCT_NAME = 0x06D0;
994+ int ADDR_PRODUCT_VERSION = 0x07F8;
995+ char* internal_name;
996+ char file_version[48];
997+ char buffer[260];
998+ BYTE* version_info_buf = NULL;
999+ DWORD version_info_len;
1000+ short file_version_major;
1001+ short file_version_minor;
1002+ short file_version_build;
1003+ short file_version_revision;
1004+ short product_version_major;
1005+ short product_version_minor;
1006+ short product_version_build;
1007+ short product_version_revision;
1008+ char* new_version;
1009+ RESOURCE res;
1010+
1011+ if (strrchr(jar_file, '\\') != NULL)
9131012 {
914- size = (*env)->GetArrayLength(env, relativeClassPath);
915- buf = (char*)((*env)->GetByteArrayElements(env, relativeClassPath, NULL));
916- SetResource(exefile, "RELATIVE_CLASSPATH", RT_RCDATA, buf, size);
1013+ internal_name = strrchr(jar_file, '\\') + 1;
9171014 }
918- classesPackGz = (jbyteArray)((*env)->CallObjectMethod(env, optimizer, getClassesPackGz));
919- if(classesPackGz != NULL)
1015+ else
9201016 {
921- size = (*env)->GetArrayLength(env, classesPackGz);
922- buf = (char*)((*env)->GetByteArrayElements(env, classesPackGz, NULL));
923- SetResource(exefile, "CLASSES_PACK_GZ", RT_RCDATA, buf, size);
1017+ internal_name = jar_file;
9241018 }
925- resourcesGz = (jbyteArray)((*env)->CallObjectMethod(env, optimizer, getResourcesGz));
926- if(resourcesGz != NULL)
1019+
1020+ strcpy(buffer, version_number);
1021+ strcat(buffer, ".0.0.0.0");
1022+ file_version_major = atoi(strtok(buffer, "."));
1023+ file_version_minor = atoi(strtok(NULL, "."));
1024+ file_version_build = atoi(strtok(NULL, "."));
1025+ file_version_revision = atoi(strtok(NULL, "."));
1026+
1027+ strcpy(buffer, product_version);
1028+ strcat(buffer, ".0.0.0.0");
1029+ product_version_major = atoi(strtok(buffer, "."));
1030+ product_version_minor = atoi(strtok(NULL, "."));
1031+ product_version_build = atoi(strtok(NULL, "."));
1032+ product_version_revision = atoi(strtok(NULL, "."));
1033+
1034+ // revison が明示的に指定されていなかった場合、既存ファイルから取得した値に 1 を加算して revision とする。
1035+ strcpy(buffer, version_number);
1036+ if (strtok(buffer, ".") != NULL)
9271037 {
928- size = (*env)->GetArrayLength(env, resourcesGz);
929- buf = (char*)((*env)->GetByteArrayElements(env, resourcesGz, NULL));
930- SetResource(exefile, "RESOURCES_GZ", RT_RCDATA, buf, size);
1038+ if (strtok(NULL, ".") != NULL)
1039+ {
1040+ if (strtok(NULL, ".") != NULL)
1041+ {
1042+ if (strtok(NULL, ".") != NULL)
1043+ {
1044+ previous_revision = file_version_revision - 1;
1045+ }
1046+ }
1047+ }
9311048 }
932- splashPath = (jbyteArray)((*env)->CallObjectMethod(env, optimizer, getSplashPath));
933- if(splashPath != NULL)
1049+
1050+ file_version_revision = (short)previous_revision + 1;
1051+ // build 加算判定ここまで。
1052+ sprintf(file_version, "%d.%d.%d.%d", file_version_major, file_version_minor, file_version_build, file_version_revision);
1053+
1054+ GetResource("VERSION_INFO", &res);
1055+ version_info_len = res.len;
1056+ version_info_buf = (BYTE*)malloc(res.len);
1057+ memcpy(version_info_buf, res.buf, res.len);
1058+
1059+ //FILEVERSION
1060+ version_info_buf[48] = file_version_minor & 0xFF;
1061+ version_info_buf[49] = (file_version_minor >> 8) & 0xFF;
1062+ version_info_buf[50] = file_version_major & 0xFF;
1063+ version_info_buf[51] = (file_version_major >> 8) & 0xFF;
1064+ version_info_buf[52] = file_version_revision & 0xFF;
1065+ version_info_buf[53] = (file_version_revision >> 8) & 0xFF;
1066+ version_info_buf[54] = file_version_build & 0xFF;
1067+ version_info_buf[55] = (file_version_build >> 8) & 0xFF;
1068+ //PRODUCTVERSION
1069+ version_info_buf[56] = product_version_minor & 0xFF;
1070+ version_info_buf[57] = (product_version_minor >> 8) & 0xFF;
1071+ version_info_buf[58] = product_version_major & 0xFF;
1072+ version_info_buf[59] = (product_version_major >> 8) & 0xFF;
1073+ version_info_buf[60] = product_version_revision & 0xFF;
1074+ version_info_buf[61] = (product_version_revision >> 8) & 0xFF;
1075+ version_info_buf[62] = product_version_build & 0xFF;
1076+ version_info_buf[63] = (product_version_build >> 8) & 0xFF;
1077+
1078+ SecureZeroMemory(buffer, sizeof(char) * 260);
1079+ MultiByteToWideChar(CP_ACP, 0, company_name, (int)strlen(company_name), (WCHAR*)buffer, 128);
1080+ for (i = 0; i < SIZE_TEXT; i++)
9341081 {
935- size = (*env)->GetArrayLength(env, splashPath);
936- buf = (char*)((*env)->GetByteArrayElements(env, splashPath, NULL));
937- SetResource(exefile, "SPLASH_PATH", RT_RCDATA, buf, size);
1082+ version_info_buf[ADDR_COMPANY_NAME + i] = buffer[i];
9381083 }
939- splashImage = (jbyteArray)((*env)->CallObjectMethod(env, optimizer, getSplashImage));
940- if(splashImage != NULL)
1084+
1085+ SecureZeroMemory(buffer, sizeof(char) * 260);
1086+ MultiByteToWideChar(CP_ACP, 0, file_description, (int)strlen(file_description), (WCHAR*)buffer, 128);
1087+ for (i = 0; i < SIZE_TEXT; i++)
9411088 {
942- size = (*env)->GetArrayLength(env, splashImage);
943- buf = (char*)((*env)->GetByteArrayElements(env, splashImage, NULL));
944- SetResource(exefile, "SPLASH_IMAGE", RT_RCDATA, buf, size);
1089+ version_info_buf[ADDR_FILE_DESCRIPTION + i] = buffer[i];
9451090 }
1091+
1092+ SecureZeroMemory(buffer, sizeof(char) * 260);
1093+ MultiByteToWideChar(CP_ACP, 0, file_version, (int)strlen(file_version), (WCHAR*)buffer, 128);
1094+ for (i = 0; i < SIZE_VERSION; i++)
1095+ {
1096+ version_info_buf[ADDR_FILE_VERSION + i] = buffer[i];
1097+ }
1098+
1099+ SecureZeroMemory(buffer, sizeof(char) * 260);
1100+ MultiByteToWideChar(CP_ACP, 0, internal_name, (int)strlen(internal_name), (WCHAR*)buffer, 128);
1101+ for (i = 0; i < SIZE_TEXT; i++)
1102+ {
1103+ version_info_buf[ADDR_INTERNAL_NAME + i] = buffer[i];
1104+ }
1105+
1106+ SecureZeroMemory(buffer, sizeof(char) * 260);
1107+ MultiByteToWideChar(CP_ACP, 0, copyright, (int)strlen(copyright), (WCHAR*)buffer, 128);
1108+ for (i = 0; i < SIZE_TEXT; i++)
1109+ {
1110+ version_info_buf[ADDR_COPYRIGHT + i] = buffer[i];
1111+ }
1112+
1113+ SecureZeroMemory(buffer, sizeof(char) * 260);
1114+ MultiByteToWideChar(CP_ACP, 0, original_filename, (int)strlen(original_filename), (WCHAR*)buffer, 128);
1115+ for (i = 0; i < SIZE_TEXT; i++)
1116+ {
1117+ version_info_buf[ADDR_ORIGINAL_FILENAME + i] = buffer[i];
1118+ }
1119+
1120+ SecureZeroMemory(buffer, sizeof(char) * 260);
1121+ MultiByteToWideChar(CP_ACP, 0, product_name, (int)strlen(product_name), (WCHAR*)buffer, 128);
1122+ for (i = 0; i < SIZE_TEXT; i++)
1123+ {
1124+ version_info_buf[ADDR_PRODUCT_NAME + i] = buffer[i];
1125+ }
1126+
1127+ SecureZeroMemory(buffer, sizeof(char) * 260);
1128+ MultiByteToWideChar(CP_ACP, 0, product_version, (int)strlen(product_version), (WCHAR*)buffer, 128);
1129+ for (i = 0; i < SIZE_VERSION; i++)
1130+ {
1131+ version_info_buf[ADDR_PRODUCT_VERSION + i] = buffer[i];
1132+ }
1133+
1134+ set_resource(filename, (LPCTSTR)VS_VERSION_INFO, RT_VERSION, version_info_buf, version_info_len);
1135+
1136+ new_version = (char*)malloc(128);
1137+ sprintf(new_version, "%d.%d.%d.%d", file_version_major, file_version_minor, file_version_build, file_version_revision);
1138+
1139+ free(version_info_buf);
1140+
1141+ return new_version;
9461142 }
1143+
1144+void OutputMessage(const char* text)
1145+{
1146+}
1147+
1148+UINT UncaughtException(const char* thread, const char* message, const char* trace)
1149+{
1150+ return 0;
1151+}
--- exewrap/trunk/exewrap/src/message.c (revision 19)
+++ exewrap/trunk/exewrap/src/message.c (revision 20)
@@ -73,6 +73,12 @@
7373 "Failed to create the Java Virtual Machine. Failed to load jvm.dll.\n"
7474 "%d-bit Java Virtual Machine required.";
7575
76+ msg[MSG_ID_COUNT * MSG_LANG_ID_EN + MSG_ID_ERR_UNCAUGHT_EXCEPTION] =
77+ "Uncaught exception occured.\n";
78+
79+ msg[MSG_ID_COUNT * MSG_LANG_ID_EN + MSG_ID_ERR_RESOURCE_NOT_FOUND] =
80+ "Resource not found: %s";
81+
7682 msg[MSG_ID_COUNT * MSG_LANG_ID_EN + MSG_ID_ERR_TARGET_VERSION] =
7783 "Java %s or higher is required to run this program.";
7884
@@ -79,6 +85,9 @@
7985 msg[MSG_ID_COUNT * MSG_LANG_ID_EN + MSG_ID_ERR_DEFINE_CLASS] =
8086 "Class not found: %s";
8187
88+ msg[MSG_ID_COUNT * MSG_LANG_ID_EN + MSG_ID_ERR_GET_CONSTRUCTOR] =
89+ "Constructor not found: %s";
90+
8291 msg[MSG_ID_COUNT * MSG_LANG_ID_EN + MSG_ID_ERR_GET_METHOD] =
8392 "Method not found: %s";
8493
@@ -104,18 +113,21 @@
104113 "The service could not be started. Requires to define a method within main class: public static void stop()";
105114
106115 msg[MSG_ID_COUNT * MSG_LANG_ID_EN + MSG_ID_ERR_SERVICE_ABORT] =
107- "The %s service was terminated abnormally.";
116+ "%s service was terminated abnormally.";
108117
109- msg[MSG_ID_COUNT * MSG_LANG_ID_JA + MSG_ID_SUCCESS_SERVICE_INSTALL] =
118+ msg[MSG_ID_COUNT * MSG_LANG_ID_EN + MSG_ID_ERR_SERVICE_NOT_STOPPED] =
119+ "%s service can't be deleted because it is not stopped.";
120+
121+ msg[MSG_ID_COUNT * MSG_LANG_ID_EN + MSG_ID_SUCCESS_SERVICE_INSTALL] =
110122 "%s service installed.";
111123
112- msg[MSG_ID_COUNT * MSG_LANG_ID_JA + MSG_ID_SUCCESS_SERVICE_REMOVE] =
124+ msg[MSG_ID_COUNT * MSG_LANG_ID_EN + MSG_ID_SUCCESS_SERVICE_REMOVE] =
113125 "%s service was removed.";
114126
115- msg[MSG_ID_COUNT * MSG_LANG_ID_JA + MSG_ID_SERVICE_STARTING] =
127+ msg[MSG_ID_COUNT * MSG_LANG_ID_EN + MSG_ID_SERVICE_STARTING] =
116128 "%s service is starting.";
117129
118- msg[MSG_ID_COUNT * MSG_LANG_ID_JA + MSG_ID_SERVICE_STOPING] =
130+ msg[MSG_ID_COUNT * MSG_LANG_ID_EN + MSG_ID_SERVICE_STOPING] =
119131 "%s service is stopping.";
120132
121133 msg[MSG_ID_COUNT * MSG_LANG_ID_EN + MSG_ID_SUCCESS_SERVICE_START] =
@@ -158,6 +170,12 @@
158170 "JavaVMを作成できませんでした。jvm.dllをロードできませんでした。\n"
159171 "このプログラムの実行には %d-bit JavaVM が必要です。";
160172
173+ msg[MSG_ID_COUNT * MSG_LANG_ID_JA + MSG_ID_ERR_UNCAUGHT_EXCEPTION] =
174+ "補足されない例外が発生しました。.\n";
175+
176+ msg[MSG_ID_COUNT * MSG_LANG_ID_JA + MSG_ID_ERR_RESOURCE_NOT_FOUND] =
177+ "リソースが見つかりません: %s";
178+
161179 msg[MSG_ID_COUNT * MSG_LANG_ID_JA + MSG_ID_ERR_TARGET_VERSION] =
162180 "このプログラムの実行には Java %s 以上が必要です。";
163181
@@ -164,6 +182,9 @@
164182 msg[MSG_ID_COUNT * MSG_LANG_ID_JA + MSG_ID_ERR_DEFINE_CLASS] =
165183 "クラスが見つかりません: %s";
166184
185+ msg[MSG_ID_COUNT * MSG_LANG_ID_JA + MSG_ID_ERR_GET_CONSTRUCTOR] =
186+ "コンストラクターが見つかりません: %s";
187+
167188 msg[MSG_ID_COUNT * MSG_LANG_ID_JA + MSG_ID_ERR_GET_METHOD] =
168189 "メソッドが見つかりません: %s";
169190
@@ -191,6 +212,9 @@
191212 msg[MSG_ID_COUNT * MSG_LANG_ID_JA + MSG_ID_ERR_SERVICE_ABORT] =
192213 "%s サービスは異常終了しました。";
193214
215+ msg[MSG_ID_COUNT * MSG_LANG_ID_JA + MSG_ID_ERR_SERVICE_NOT_STOPPED] =
216+ "%s サービスが停止していないため、削除できません。";
217+
194218 msg[MSG_ID_COUNT * MSG_LANG_ID_JA + MSG_ID_SUCCESS_SERVICE_INSTALL] =
195219 "%s サービスをインストールしました。";
196220
--- exewrap/trunk/exewrap/src/bindres.c (revision 19)
+++ exewrap/trunk/exewrap/src/bindres.c (revision 20)
@@ -11,10 +11,11 @@
1111
1212 int main(int argc, char* argv[])
1313 {
14+ int is_reverse = 0;
1415 char* rscName;
1516 char* rscFileName;
1617 DWORD rscSize;
17- char* rscData;
18+ BYTE* rscData;
1819 char* filepath;
1920 char* filename;
2021 HANDLE hRscFile;
@@ -23,32 +24,38 @@
2324 DWORD readSize;
2425 BOOL ret1;
2526 BOOL ret2;
26- int i;
27+ DWORD i;
2728 HANDLE hRes;
29+
2830
29- if(argc < 4)
31+ if(argc < 4 || (strcmp(argv[1], "-r") == 0 && argc < 5))
3032 {
31- printf("Usage: %s <filename> <resource-name> <resource-file>\n", argv[0]);
33+ printf("Usage: %s [-r] <filename> <resource-name> <resource-file>\n", argv[0]);
3234 return -1;
3335 }
36+
37+ if(strcmp(argv[1], "-r") == 0)
38+ {
39+ is_reverse = 1;
40+ }
3441
35- filepath = (char*)HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
36- filepath[0] = '\0';
42+ filepath = (char*)malloc(MAX_PATH);
43+ GetFullPathName(argv[1 + is_reverse], MAX_PATH, filepath, &filename);
3744
38- rscName = argv[2];
39- rscFileName = argv[3];
45+ rscName = argv[2 + is_reverse];
46+ rscFileName = argv[3 + is_reverse];
4047
41- if((hRscFile = CreateFile(rscFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
48+ hRscFile = CreateFile(rscFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
49+ if(hRscFile == INVALID_HANDLE_VALUE)
4250 {
4351 printf("Failed to open: %s\n", rscFileName);
4452 return -2;
4553 }
4654 rscSize = GetFileSize(hRscFile, NULL);
47- rscData = (char*)HeapAlloc(GetProcessHeap(), 0, rscSize);
55+ rscData = (BYTE*)HeapAlloc(GetProcessHeap(), 0, rscSize);
4856
4957 p = rscData;
5058 r = rscSize;
51- GetFullPathName(argv[1], MAX_PATH, filepath, &filename);
5259
5360 while(r > 0)
5461 {
@@ -62,6 +69,17 @@
6269 }
6370 CloseHandle(hRscFile);
6471
72+ if(is_reverse)
73+ {
74+ BYTE* tmp = (BYTE*)HeapAlloc(GetProcessHeap(), 0, rscSize);
75+ CopyMemory(tmp, rscData, rscSize);
76+ for (i = 0; i < rscSize; i++)
77+ {
78+ rscData[i] = ~tmp[rscSize - 1 - i];
79+ }
80+ HeapFree(GetProcessHeap(), 0, tmp);
81+ }
82+
6583 for(i = 0; i < 100; i++)
6684 {
6785 ret1 = FALSE;
@@ -84,5 +102,7 @@
84102 return -4;
85103 }
86104 CloseHandle(hRes);
105+
106+ HeapFree(GetProcessHeap(), 0, rscData);
87107 return 0;
88108 }
--- exewrap/trunk/exewrap/src/image_gui.c (revision 19)
+++ exewrap/trunk/exewrap/src/image_gui.c (revision 20)
@@ -17,630 +17,246 @@
1717 #include <jni.h>
1818
1919 #include "include/jvm.h"
20+#include "include/loader.h"
2021 #include "include/notify.h"
2122 #include "include/message.h"
2223
23-static char** GetArgs(int* argc);
24-static LPSTR _W2A(LPCWSTR s);
24+void OutputMessage(const char* text);
25+UINT UncaughtException(const char* thread, const char* message, const char* trace);
2526
26-DWORD WINAPI CallMainMethod(void* arglist);
27-char** arg_split(char* buffer, int* p_argc);
27+static char** get_args(int* argc);
28+static char* _w2a(LPCWSTR s);
2829
29-void InitResource(LPCTSTR name);
30-DWORD GetResourceSize(LPCTSTR name);
31-jbyte* GetResourceBuffer(LPCTSTR name);
32-void OutputError(LPCTSTR text);
33-void OutputMessage(LPCTSTR text);
34-LPSTR GetModuleMutexName();
35-
36-typedef void (*SplashInit_t)(void);
37-typedef int (*SplashLoadMemory_t)(void* pdata, int size);
38-SplashInit_t SplashInit;
30+typedef void(*SplashInit_t)(void);
31+typedef int(*SplashLoadMemory_t)(void* pdata, int size);
32+SplashInit_t SplashInit;
3933 SplashLoadMemory_t SplashLoadMemory;
34+HMODULE splashscreendll;
4035
41-void JNICALL JNI_UncaughtException(JNIEnv *env, jobject clazz, jstring message, jstring trace);
4236
43-HMODULE splashscreendll;
44-
45-TCHAR cache[] = "12345678901234567890123456789012";
46-jbyte* buffer = NULL;
47-DWORD size = 0;
48-
49-jclass mainClass = NULL;
50-jmethodID mainMethod = NULL;
51-
52-static char** GetArgs(int* argc)
53-{
54- LPWSTR lpCmdLineW;
55- LPWSTR* argvW;
56- LPSTR* argvA;
57- int i;
58- int ret = 0;
59-
60- lpCmdLineW = GetCommandLineW();
61- argvW = CommandLineToArgvW(lpCmdLineW, argc);
62- argvA = (LPSTR*)HeapAlloc(GetProcessHeap(), 0, (*argc + 1) * sizeof(LPSTR));
63- for (i = 0; i < *argc; i++)
64- {
65- argvA[i] = _W2A(argvW[i]);
66- }
67- argvA[*argc] = NULL;
68-
69- return argvA;
70-}
71-
72-static LPSTR _W2A(LPCWSTR s)
73-{
74- LPSTR buf;
75- int ret;
76-
77- ret = WideCharToMultiByte(CP_ACP, 0, s, -1, NULL, 0, NULL, NULL);
78- if (ret <= 0)
79- {
80- return NULL;
81- }
82- buf = (LPSTR)HeapAlloc(GetProcessHeap(), 0, ret + 1);
83- ret = WideCharToMultiByte(CP_ACP, 0, s, -1, buf, (ret + 1), NULL, NULL);
84- if (ret == 0)
85- {
86- HeapFree(GetProcessHeap(), 0, buf);
87- return NULL;
88- }
89- buf[ret] = '\0';
90-
91- return buf;
92-}
93-
9437 INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow)
9538 {
96- int argc;
97- char** argv = GetArgs(&argc);
98- int exit_code = 0;
99- int i;
100- BOOL useServerVM = FALSE;
101- int err;
102- LPTSTR ext_flags = NULL;
103- LPTSTR relative_classpath = NULL;
104- LPTSTR relative_extdirs = "lib";
105- HANDLE synchronize_mutex_handle = NULL;
106- int splash_size;
107- void* splash_data = NULL;
108- LPTSTR vm_args_opt = NULL;
109- DWORD version;
110- LPTSTR targetVersionString;
111- DWORD targetVersion;
112- char* message = NULL;
113- jclass urlConnectionClass;
114- jclass urlStreamHandlerClass;
115- jclass fileLogStreamClass;
116- jmethodID fileLogStreamInit;
117- char moduleFileName[MAX_PATH];
118- jobjectArray args;
39+ int argc;
40+ char** argv;
41+ int err;
42+ char* relative_classpath;
43+ char* relative_extdirs;
44+ BOOL use_server_vm;
45+ HANDLE synchronize_mutex_handle = NULL;
46+ char* ext_flags;
47+ BYTE* splash_screen_image = NULL;
48+ char* splash_screen_name = NULL;
49+ char* vm_args_opt;
50+ char utilities[128];
51+ RESOURCE res;
52+ LOAD_RESULT result;
11953
120- message = (char*)HeapAlloc(GetProcessHeap(), 0, 1024);
54+ argv = get_args(&argc);
55+ result.msg = malloc(2048);
12156
122- if(GetResourceSize("RELATIVE_CLASSPATH") > 0)
123- {
124- relative_classpath = (LPTSTR)GetResourceBuffer("RELATIVE_CLASSPATH");
125- }
126- if(GetResourceSize("EXTDIRS") > 0)
127- {
128- relative_extdirs = (LPTSTR)GetResourceBuffer("EXTDIRS");
129- }
130- if(GetResourceSize("EXTFLAGS") > 0)
131- {
132- ext_flags = _strupr((LPTSTR)GetResourceBuffer("EXTFLAGS"));
133- }
134- if(ext_flags != NULL && strstr(ext_flags, "SERVER") != NULL)
135- {
136- useServerVM = TRUE;
137- }
57+ relative_classpath = (char*)GetResource("CLASS_PATH", NULL);
58+ relative_extdirs = (char*)GetResource("EXTDIRS", NULL);
59+ ext_flags = (char*)GetResource("EXTFLAGS", NULL);
60+ use_server_vm = (ext_flags != NULL && strstr(ext_flags, "SERVER") != NULL);
61+ InitializePath(relative_classpath, relative_extdirs, use_server_vm);
13862
139- InitializePath(relative_classpath, relative_extdirs, useServerVM);
140-
141- if(ext_flags != NULL && strstr(ext_flags, "SHARE") != NULL)
63+ if (ext_flags != NULL && strstr(ext_flags, "SHARE") != NULL)
14264 {
143- synchronize_mutex_handle = notify_exec(CallMainMethod, argc, argv);
144- if(synchronize_mutex_handle == NULL)
65+ synchronize_mutex_handle = NotifyExec(RemoteCallMainMethod, argc, argv);
66+ if (synchronize_mutex_handle == NULL)
14567 {
146- exit_code = 0;
68+ result.msg_id = 0;
14769 goto EXIT;
14870 }
14971 }
150-
151- if(ext_flags != NULL && strstr(ext_flags, "SINGLE") != NULL)
72+ if (ext_flags != NULL && strstr(ext_flags, "SINGLE") != NULL)
15273 {
153- if(CreateMutex(NULL, TRUE, GetModuleObjectName("SINGLE")), GetLastError() == ERROR_ALREADY_EXISTS)
74+ if (CreateMutex(NULL, TRUE, GetModuleObjectName("SINGLE")), GetLastError() == ERROR_ALREADY_EXISTS)
15475 {
155- exit_code = 0;
76+ result.msg_id = 0;
15677 goto EXIT;
15778 }
15879 }
159-
80+
16081 // Display Splash Screen
161- splash_size = GetResourceSize("SPLASH_IMAGE");
162- if(splash_size > 0)
82+ if (GetResource("SPLASH_SCREEN_IMAGE", &res) != NULL)
16383 {
164- if((splash_data = GetResourceBuffer("SPLASH_IMAGE")) != NULL)
84+ splashscreendll = LoadLibrary("splashscreen.dll");
85+ if (splashscreendll != NULL)
16586 {
166- if((splashscreendll = LoadLibrary("splashscreen.dll")) != NULL)
87+ SplashInit = (SplashInit_t)GetProcAddress(splashscreendll, "SplashInit");
88+ if (SplashInit != NULL)
16789 {
168- SplashInit = (SplashInit_t)GetProcAddress(splashscreendll, "SplashInit");
16990 SplashLoadMemory = (SplashLoadMemory_t)GetProcAddress(splashscreendll, "SplashLoadMemory");
170- if(SplashInit != NULL && SplashLoadMemory != NULL)
91+ if (SplashLoadMemory != NULL)
17192 {
17293 SplashInit();
173- SplashLoadMemory(splash_data, splash_size);
94+ SplashLoadMemory(res.buf, res.len);
17495 }
17596 }
17697 }
17798 }
17899
179- if(GetResourceSize("VMARGS") > 0)
100+ vm_args_opt = (char*)GetResource("VMARGS", NULL);
101+ CreateJavaVM(vm_args_opt, use_server_vm, &err);
102+ if (err != JNI_OK)
180103 {
181- vm_args_opt = (LPTSTR)GetResourceBuffer("VMARGS");
182- }
183- CreateJavaVM(vm_args_opt, useServerVM, &err);
184- switch(err) {
185- case JNI_OK:
186- break;
187- case JNI_ERR: /* unknown error */
188- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_UNKNOWN));
189- exit_code = MSG_ID_ERR_CREATE_JVM_UNKNOWN;
104+ OutputMessage(GetJniErrorMessage(err, &result.msg_id, result.msg));
190105 goto EXIT;
191- case JNI_EDETACHED: /* thread detached from the VM */
192- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_EDETACHED));
193- exit_code = MSG_ID_ERR_CREATE_JVM_EDETACHED;
194- goto EXIT;
195- case JNI_EVERSION: /* JNI version error */
196- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_EVERSION));
197- exit_code = MSG_ID_ERR_CREATE_JVM_EVERSION;
198- goto EXIT;
199- case JNI_ENOMEM: /* not enough memory */
200- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_ENOMEM));
201- exit_code = MSG_ID_ERR_CREATE_JVM_ENOMEM;
202- goto EXIT;
203- case JNI_EEXIST: /* VM already created */
204- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_EEXIST));
205- exit_code = MSG_ID_ERR_CREATE_JVM_EEXIST;
206- goto EXIT;
207- case JNI_EINVAL: /* invalid arguments */
208- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_EINVAL));
209- exit_code = MSG_ID_ERR_CREATE_JVM_EINVAL;
210- goto EXIT;
211- case JVM_ELOADLIB:
212- sprintf(message, _(MSG_ID_ERR_CREATE_JVM_ELOADLIB), GetProcessArchitecture());
213- OutputMessage(message);
214- exit_code = MSG_ID_ERR_CREATE_JVM_ELOADLIB;
215- goto EXIT;
216- default:
217- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_UNKNOWN));
218- exit_code = MSG_ID_ERR_CREATE_JVM_UNKNOWN;
219- goto EXIT;
220106 }
221-
222- version = GetJavaRuntimeVersion();
223- targetVersionString = (LPTSTR)GetResourceBuffer("TARGET_VERSION");
224- targetVersion = *(DWORD*)targetVersionString;
225- if(targetVersion > version)
107+
108+ if(GetResource("TARGET_VERSION", &res) != NULL)
226109 {
227- sprintf(message, _(MSG_ID_ERR_TARGET_VERSION), targetVersionString + 4);
228- OutputMessage(message);
229- exit_code = MSG_ID_ERR_TARGET_VERSION;
230- goto EXIT;
231- }
232-
233- // URLConnection
234- urlConnectionClass = (*env)->DefineClass(env, "URLConnection", NULL, GetResourceBuffer("URL_CONNECTION"), GetResourceSize("URL_CONNECTION"));
235- if(urlConnectionClass == NULL)
236- {
237- sprintf(message, _(MSG_ID_ERR_DEFINE_CLASS), "URLConnection");
238- OutputMessage(message);
239- exit_code = MSG_ID_ERR_DEFINE_CLASS;
240- goto EXIT;
241- }
242- // URLStreamHandler
243- urlStreamHandlerClass = (*env)->DefineClass(env, "URLStreamHandler", NULL, GetResourceBuffer("URL_STREAM_HANDLER"), GetResourceSize("URL_STREAM_HANDLER"));
244- if(urlStreamHandlerClass == NULL)
245- {
246- sprintf(message, _(MSG_ID_ERR_DEFINE_CLASS), "URLStreamHandler");
247- OutputMessage(message);
248- exit_code = MSG_ID_ERR_DEFINE_CLASS;
249- goto EXIT;
250- }
251-
252- // FileLogStream
253- if(ext_flags == NULL || strstr(ext_flags, "NOLOG") == NULL)
254- {
255- if((fileLogStreamClass = (*env)->DefineClass(env, "FileLogStream", NULL, GetResourceBuffer("FILELOG_STREAM"), GetResourceSize("FILELOG_STREAM"))) != NULL)
110+ DWORD version = GetJavaRuntimeVersion();
111+ DWORD targetVersion = *(DWORD*)res.buf;
112+ if (targetVersion > version)
256113 {
257- if((fileLogStreamInit = (*env)->GetStaticMethodID(env, fileLogStreamClass, "initialize", "(Ljava/lang/String;)V"))!= NULL)
258- {
259- GetModuleFileName(NULL, moduleFileName, MAX_PATH);
260- (*env)->CallStaticVoidMethod(env, fileLogStreamClass, fileLogStreamInit, GetJString(env, moduleFileName));
261- if((*env)->ExceptionCheck(env))
262- {
263- (*env)->ExceptionClear(env);
264- }
265- }
266- }
267- }
268- // UncaughtHandler (version 1.5.0 or higher only)
269- if(version >= 0x01050000) {
270- jclass uncaughtHandlerClass;
271- jmethodID uncaughtHandlerInit;
272-
273- if((uncaughtHandlerClass = (*env)->DefineClass(env, "UncaughtHandler", NULL, GetResourceBuffer("UNCAUGHT_HANDLER"), GetResourceSize("UNCAUGHT_HANDLER"))) != NULL)
274- {
275- if((uncaughtHandlerInit = (*env)->GetStaticMethodID(env, uncaughtHandlerClass, "initialize", "()V"))!= NULL)
276- {
277- JNINativeMethod nm;
278-
279- (*env)->CallStaticVoidMethod(env, uncaughtHandlerClass, uncaughtHandlerInit);
280- nm.name = (char*)"UncaughtException";
281- nm.signature = (char*)"(Ljava/lang/String;Ljava/lang/String;)V";
282- nm.fnPtr = (void*)JNI_UncaughtException;
283-
284- if(((*env)->RegisterNatives(env, uncaughtHandlerClass, &nm, 1)) != 0)
285- {
286- sprintf(message, _(MSG_ID_ERR_REGISTER_NATIVE), "UncaughtException");
287- OutputMessage(message);
288- exit_code = MSG_ID_ERR_REGISTER_NATIVE;
289- goto EXIT;
290- }
291- }
292- }
293- }
294-
295- // Loader
296- if(GetResourceBuffer("PACK_LOADER") != NULL) {
297- // PackLoader
298- jclass packLoaderClass;
299- jmethodID packLoaderInit;
300- jobject packLoader;
301- jbyteArray classesPackGz = NULL;
302- jbyteArray resourcesGz = NULL;
303- jbyteArray splashPath = NULL;
304- jbyteArray splashImage = NULL;
305- jmethodID packLoaderInitializeMethod;
306-
307- packLoaderClass = (*env)->DefineClass(env, "PackLoader", NULL, GetResourceBuffer("PACK_LOADER"), GetResourceSize("PACK_LOADER"));
308- if(packLoaderClass == NULL)
309- {
310- sprintf(message, _(MSG_ID_ERR_DEFINE_CLASS), "PackLoader");
311- OutputMessage(message);
312- exit_code = MSG_ID_ERR_DEFINE_CLASS;
114+ char* targetVersionString = (char*)res.buf + 4;
115+ result.msg_id = MSG_ID_ERR_TARGET_VERSION;
116+ sprintf(result.msg, _(MSG_ID_ERR_TARGET_VERSION), targetVersionString + 4);
117+ OutputMessage(result.msg);
313118 goto EXIT;
314119 }
315- packLoaderInit = (*env)->GetMethodID(env, packLoaderClass, "<init>", "()V");
316- if(packLoaderInit == NULL)
317- {
318- sprintf(message, _(MSG_ID_ERR_GET_METHOD), "PackLoader#init()");
319- OutputMessage(message);
320- exit_code = MSG_ID_ERR_GET_METHOD;
321- goto EXIT;
322- }
323- packLoader = (*env)->NewObject(env, packLoaderClass, packLoaderInit);
324- if(packLoader == NULL)
325- {
326- sprintf(message, _(MSG_ID_ERR_NEW_OBJECT), "PackLoader");
327- OutputMessage(message);
328- exit_code = MSG_ID_ERR_NEW_OBJECT;
329- goto EXIT;
330- }
331- if(GetResourceBuffer("CLASSES_PACK_GZ") != NULL)
332- {
333- classesPackGz = (*env)->NewByteArray(env, GetResourceSize("CLASSES_PACK_GZ"));
334- (*env)->SetByteArrayRegion(env, classesPackGz, 0, GetResourceSize("CLASSES_PACK_GZ"), GetResourceBuffer("CLASSES_PACK_GZ"));
335- }
336- if(GetResourceBuffer("RESOURCES_GZ") != NULL)
337- {
338- resourcesGz = (*env)->NewByteArray(env, GetResourceSize("RESOURCES_GZ"));
339- (*env)->SetByteArrayRegion(env, resourcesGz, 0, GetResourceSize("RESOURCES_GZ"), GetResourceBuffer("RESOURCES_GZ"));
340- }
341- if(GetResourceBuffer("SPLASH_PATH") != NULL)
342- {
343- splashPath = (*env)->NewByteArray(env, GetResourceSize("SPLASH_PATH"));
344- (*env)->SetByteArrayRegion(env, splashPath, 0, GetResourceSize("SPLASH_PATH"), GetResourceBuffer("SPLASH_PATH"));
345- }
346- if(GetResourceBuffer("SPLATH_IMAGE") != NULL)
347- {
348- splashImage = (*env)->NewByteArray(env, GetResourceSize("SPLASH_IMAGE"));
349- (*env)->SetByteArrayRegion(env, splashImage, 0, GetResourceSize("SPLASH_IMAGE"), GetResourceBuffer("SPLASH_IMAGE"));
350- }
351- packLoaderInitializeMethod = (*env)->GetMethodID(env, packLoaderClass, "initialize", "([B[B[B[B)Ljava/lang/Class;");
352- if(packLoaderInitializeMethod == NULL)
353- {
354- sprintf(message, _(MSG_ID_ERR_GET_METHOD), "PackLoader#initialize(byte[], byte[], byte[], byte[])");
355- OutputMessage(message);
356- exit_code = MSG_ID_ERR_GET_METHOD;
357- goto EXIT;
358- }
359- mainClass = (jclass)((*env)->CallObjectMethod(env, packLoader, packLoaderInitializeMethod, classesPackGz, resourcesGz, splashPath, splashImage));
360120 }
361- else if(GetResourceBuffer("CLASSIC_LOADER") != NULL)
362- {
363- // ClassicLoader
364- jclass classicLoaderClass;
365- jmethodID classicLoaderInit;
366- jobject classicLoader;
367- jbyteArray jar;
368- jmethodID classicLoaderInitializeMethod;
369121
370- classicLoaderClass = (*env)->DefineClass(env, "ClassicLoader", NULL, GetResourceBuffer("CLASSIC_LOADER"), GetResourceSize("CLASSIC_LOADER"));
371- if(classicLoaderClass == NULL)
372- {
373- sprintf(message, _(MSG_ID_ERR_DEFINE_CLASS), "ClassicLoader");
374- OutputMessage(message);
375- exit_code = MSG_ID_ERR_DEFINE_CLASS;
376- goto EXIT;
377- }
378- classicLoaderInit = (*env)->GetMethodID(env, classicLoaderClass, "<init>", "()V");
379- if(classicLoaderInit == NULL)
380- {
381- sprintf(message, _(MSG_ID_ERR_GET_METHOD), "ClassicLoader#init()");
382- OutputMessage(message);
383- exit_code = MSG_ID_ERR_GET_METHOD;
384- goto EXIT;
385- }
386- classicLoader = (*env)->NewObject(env, classicLoaderClass, classicLoaderInit);
387- if(classicLoader == NULL)
388- {
389- sprintf(message, _(MSG_ID_ERR_NEW_OBJECT), "ClassicLoader");
390- OutputMessage(message);
391- exit_code = MSG_ID_ERR_NEW_OBJECT;
392- goto EXIT;
393- }
394- jar = (*env)->NewByteArray(env, GetResourceSize("JAR"));
395- (*env)->SetByteArrayRegion(env, jar, 0, GetResourceSize("JAR"), GetResourceBuffer("JAR"));
396- classicLoaderInitializeMethod = (*env)->GetMethodID(env, classicLoaderClass, "initialize", "([B)Ljava/lang/Class;");
397- if(classicLoaderInitializeMethod == NULL)
398- {
399- sprintf(message, _(MSG_ID_ERR_GET_METHOD), "ClassicLoader#initialize(byte[])");
400- OutputMessage(message);
401- exit_code = MSG_ID_ERR_GET_METHOD;
402- goto EXIT;
403- }
404- mainClass = (jclass)((*env)->CallObjectMethod(env, classicLoader, classicLoaderInitializeMethod, jar));
405- }
406- else
122+ utilities[0] = '\0';
123+ if (ext_flags == NULL || strstr(ext_flags, "IGNORE_UNCAUGHT_EXCEPTION") == NULL)
407124 {
408- OutputMessage(_(MSG_ID_ERR_FIND_CLASSLOADER));
409- exit_code = MSG_ID_ERR_FIND_CLASSLOADER;
410- goto EXIT;
125+ strcat(utilities, UTIL_UNCAUGHT_EXCEPTION_HANDLER);
411126 }
412-
413- // Main-Class
414- if(mainClass == NULL)
127+ if (ext_flags == NULL || strstr(ext_flags, "NOLOG") == NULL)
415128 {
416- sprintf(message, "%s\r\n", _(MSG_ID_ERR_LOAD_MAIN_CLASS));
417- OutputError(message);
418- exit_code = MSG_ID_ERR_LOAD_MAIN_CLASS;
419- goto EXIT;
129+ strcat(utilities, UTIL_FILE_LOG_STREAM);
420130 }
421- mainMethod = (*env)->GetStaticMethodID(env, mainClass, "main", "([Ljava/lang/String;)V");
422- if(mainMethod == NULL)
131+ if(LoadMainClass(argc, argv, utilities, &result) == FALSE)
423132 {
424- OutputMessage(_(MSG_ID_ERR_FIND_MAIN_METHOD));
425- exit_code = MSG_ID_ERR_FIND_MAIN_METHOD;
133+ OutputMessage(result.msg);
426134 goto EXIT;
427135 }
428- args = (*env)->NewObjectArray(env, argc - 1, (*env)->FindClass(env, "java/lang/String"), NULL);
429- for(i = 1; i < argc; i++)
136+
137+ if (GetResource("SPLASH_SCREEN_IMAGE", &res) != NULL)
430138 {
431- (*env)->SetObjectArrayElement(env, args, (i - 1), GetJString(env, argv[i]));
139+ BYTE* splash_screen_image_buf = res.buf;
140+ DWORD splash_screen_image_len = res.len;
141+ char* splash_screen_name = GetResource("SPLASH_SCREEN_NAME", NULL);
142+
143+ SetSplashScreenResource(splash_screen_name, splash_screen_image_buf, splash_screen_image_len);
432144 }
433-
434- if(synchronize_mutex_handle != NULL)
145+
146+ if (synchronize_mutex_handle != NULL)
435147 {
436148 ReleaseMutex(synchronize_mutex_handle);
437149 CloseHandle(synchronize_mutex_handle);
438150 synchronize_mutex_handle = NULL;
439151 }
152+ (*env)->CallStaticVoidMethod(env, result.MainClass, result.MainClass_main, result.MainClass_main_args);
440153
441- (*env)->CallStaticVoidMethod(env, mainClass, mainMethod, args);
442-
443- if((*env)->ExceptionCheck(env) == JNI_TRUE)
154+ if ((*env)->ExceptionCheck(env) == JNI_TRUE)
444155 {
445- OutputError(NULL);
446- exit_code = 1;
447- goto EXIT;
156+ jthrowable throwable = (*env)->ExceptionOccurred(env);
157+ if (throwable != NULL)
158+ {
159+ ToString(env, throwable, result.msg);
160+ OutputMessage(result.msg);
161+ (*env)->DeleteLocalRef(env, throwable);
162+ }
448163 }
164+ (*env)->ExceptionClear(env);
449165
450166 EXIT:
451- if(synchronize_mutex_handle != NULL)
167+ if (synchronize_mutex_handle != NULL)
452168 {
453169 ReleaseMutex(synchronize_mutex_handle);
454170 CloseHandle(synchronize_mutex_handle);
455171 }
456- if(message != NULL)
172+ if (result.msg != NULL)
457173 {
458- HeapFree(GetProcessHeap(), 0, message);
174+ free(result.msg);
459175 }
460- if(env != NULL)
176+ if (env != NULL)
461177 {
462178 DetachJavaVM();
463179 }
464- if(jvm != NULL)
180+ if (jvm != NULL)
465181 {
466182 DestroyJavaVM();
467183 }
468-
469- notify_close();
470184
471- return exit_code;
185+ NotifyClose();
186+
187+ return result.msg_id;
472188 }
473189
474-DWORD WINAPI CallMainMethod(void* _shared_memory_handle)
190+
191+void OutputMessage(const char* text)
475192 {
476- HANDLE shared_memory_handle = (HANDLE)_shared_memory_handle;
477- char* arglist;
478- char* buf;
479- int argc;
480- char** argv = NULL;
481- int i;
482- LPSTR shared_memory_read_event_name;
483- HANDLE shared_memory_read_event_handle;
484- LPBYTE lpShared = (LPBYTE)MapViewOfFile(shared_memory_handle, FILE_MAP_READ, 0, 0, 0);
485- JNIEnv* env;
486- jobjectArray args;
193+ char buffer[MAX_PATH];
194+ char* filename;
487195
488- arglist = (char*)(lpShared + sizeof(DWORD) + sizeof(DWORD));
489- buf = (char*)HeapAlloc(GetProcessHeap(), 0, lstrlen(arglist) + 1);
490- lstrcpy(buf, (char*)arglist);
491- UnmapViewOfFile(lpShared);
492-
493- argv = arg_split(buf, &argc);
494- HeapFree(GetProcessHeap(), 0, buf);
495-
496- env = AttachJavaVM();
497- if(env != NULL)
196+ if (text == NULL)
498197 {
499- args = (*env)->NewObjectArray(env, argc - 1, (*env)->FindClass(env, "java/lang/String"), NULL);
500- for (i = 1; i < argc; i++)
501- {
502- (*env)->SetObjectArrayElement(env, args, (i - 1), GetJString(env, argv[i]));
503- }
198+ return;
504199 }
505200
506- shared_memory_read_event_name = GetModuleObjectName("SHARED_MEMORY_READ");
507- shared_memory_read_event_handle = OpenEvent(EVENT_MODIFY_STATE, FALSE, shared_memory_read_event_name);
508- if (shared_memory_read_event_handle != NULL)
509- {
510- SetEvent(shared_memory_read_event_handle);
511- CloseHandle(shared_memory_read_event_handle);
512- }
513- HeapFree(GetProcessHeap(), 0, shared_memory_read_event_name);
201+ GetModuleFileName(NULL, buffer, MAX_PATH);
202+ filename = strrchr(buffer, '\\') + 1;
514203
515- if(env == NULL)
516- {
517- goto EXIT;
518- }
204+ MessageBox(NULL, text, filename, MB_ICONEXCLAMATION | MB_APPLMODAL | MB_OK | MB_SETFOREGROUND);
205+}
519206
520- (*env)->CallStaticVoidMethod(env, mainClass, mainMethod, args);
521- if((*env)->ExceptionCheck(env) == JNI_TRUE)
522- {
523- OutputError(NULL);
524- }
525- DetachJavaVM();
526207
527-EXIT:
528- if(argv != NULL)
529- {
530- HeapFree(GetProcessHeap(), 0, argv);
531- }
208+UINT UncaughtException(const char* thread, const char* message, const char* trace)
209+{
210+ char* buf;
211+
212+ buf = malloc(16 * 1024);
213+ sprintf(buf, "Exception in thread \"%s\" %s", thread, trace);
214+ OutputMessage(buf);
215+ free(buf);
532216
533- return 0;
217+ return MSG_ID_ERR_UNCAUGHT_EXCEPTION;
534218 }
535219
536-char** arg_split(char* buffer, int* p_argc)
537-{
538- int i;
539- int buf_len = lstrlen(buffer);
540- char** argv;
541220
542- *p_argc = 0;
543- for(i = 0; i < buf_len; i++) {
544- *p_argc += (buffer[i] == '\n')?1:0;
545- }
546- argv = (char**)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (*p_argc) * sizeof(char*));
547- for(i = 0; i < *p_argc; i++)
548- {
549- argv[i] = strtok(i?NULL:buffer, "\n");
550- }
551- return argv;
552-}
553-
554-void InitResource(LPCTSTR name)
221+static char** get_args(int* argc)
555222 {
556- HRSRC hrsrc;
223+ LPWSTR lpCmdLineW;
224+ LPWSTR* argvW;
225+ LPSTR* argvA;
226+ int i;
227+ int ret = 0;
557228
558- if((hrsrc = FindResource(NULL, name, RT_RCDATA)) == NULL)
229+ lpCmdLineW = GetCommandLineW();
230+ argvW = CommandLineToArgvW(lpCmdLineW, argc);
231+ argvA = (LPSTR*)HeapAlloc(GetProcessHeap(), 0, (*argc + 1) * sizeof(LPSTR));
232+ for (i = 0; i < *argc; i++)
559233 {
560- size = 0;
561- buffer = NULL;
562- return;
234+ argvA[i] = _w2a(argvW[i]);
563235 }
564- size = SizeofResource(NULL, hrsrc);
565- buffer = (jbyte*)LockResource(LoadResource(NULL, hrsrc));
566- lstrcpy(cache, name);
567-}
236+ argvA[*argc] = NULL;
568237
569-DWORD GetResourceSize(LPCTSTR name)
570-{
571- if(lstrcmp(name, cache) != 0)
572- {
573- InitResource(name);
574- }
575- return size;
238+ return argvA;
576239 }
577240
578-jbyte* GetResourceBuffer(LPCTSTR name)
579-{
580- if(lstrcmp(name, cache) != 0)
581- {
582- InitResource(name);
583- }
584- return buffer;
585-}
586241
587-void OutputError(const char* text)
242+static char* _w2a(LPCWSTR s)
588243 {
589244 char* buf;
590- jthrowable throwable;
591- char* message;
245+ int ret;
592246
593- buf = (char*)HeapAlloc(GetProcessHeap(), 0, 8192);
594-
595- if((*env)->ExceptionCheck(env) != JNI_TRUE) {
596- OutputMessage(text);
597- goto EXIT;
598- }
599-
600- throwable = (*env)->ExceptionOccurred(env);
601- (*env)->ExceptionDescribe(env);
602- (*env)->ExceptionClear(env);
603-
604- message = GetShiftJIS(env, (jstring)(*env)->CallObjectMethod(env, throwable,
605- (*env)->GetMethodID(env, (*env)->FindClass(env, "java/lang/Throwable"), "toString", "()Ljava/lang/String;"))
606- );
607- if(text != NULL)
247+ ret = WideCharToMultiByte(CP_ACP, 0, s, -1, NULL, 0, NULL, NULL);
248+ if (ret <= 0)
608249 {
609- lstrcpy(buf, text);
610- lstrcat(buf, "\r\n");
611- lstrcat(buf, message);
612- OutputMessage(buf);
250+ return NULL;
613251 }
614- else
252+ buf = (LPSTR)HeapAlloc(GetProcessHeap(), 0, ret + 1);
253+ ret = WideCharToMultiByte(CP_ACP, 0, s, -1, buf, (ret + 1), NULL, NULL);
254+ if (ret == 0)
615255 {
616- OutputMessage(message);
617- }
618-
619-EXIT:
620- if(message != NULL)
621- {
622- HeapFree(GetProcessHeap(), 0, message);
623- }
624- if(buf != NULL)
625- {
626256 HeapFree(GetProcessHeap(), 0, buf);
257+ return NULL;
627258 }
628-}
259+ buf[ret] = '\0';
629260
630-void OutputMessage(const char* text)
631-{
632- char* filename;
633- char buffer[MAX_PATH];
634-
635- GetModuleFileName(NULL, buffer, MAX_PATH);
636- filename = strrchr(buffer, '\\') + 1;
637-
638- MessageBox(NULL, text, filename, MB_ICONEXCLAMATION | MB_APPLMODAL | MB_OK | MB_SETFOREGROUND);
261+ return buf;
639262 }
640-
641-void JNICALL JNI_UncaughtException(JNIEnv *env, jobject clazz, jstring message, jstring trace)
642-{
643- OutputMessage(GetShiftJIS(env, message));
644-
645- ExitProcess(0);
646-}
--- exewrap/trunk/exewrap/src/Makefile (revision 19)
+++ exewrap/trunk/exewrap/src/Makefile (revision 20)
@@ -5,6 +5,7 @@
55 LINK = link.exe
66 RC = RC.exe
77 JAVAC = javac.exe
8+JAR = jar.exe
89
910 !if ([@cl.exe 2>&1| @findstr "x64" > nul] == 0)
1011 ARCHITECTURE=x64
@@ -40,22 +41,14 @@
4041 Make.bat
4142
4243 EXEWRAP_X86 : $(BIN)\exewrap.exe
43-
4444 EXEWRAP_X64 : $(BIN)\exewrap.exe
4545
46-IMAGE_X86 : $(OBJ)\image_console.img $(OBJ)\image_gui.img $(OBJ)\image_service.img
46+IMAGE_X86 : $(OBJ)\image_console.exe $(OBJ)\image_gui.exe $(OBJ)\image_service.exe
47+IMAGE_X64 : $(OBJ)\image_console.exe $(OBJ)\image_gui.exe $(OBJ)\image_service.exe
4748
48-IMAGE_X64 : $(OBJ)\image_console.img $(OBJ)\image_gui.img $(OBJ)\image_service.img
49-
5049 CLEAN :
51- -@erase /Q $(OBJ)\..\x86\*
52- -@erase /Q $(OBJ)\..\x86
53- -@erase /Q $(OBJ)\..\x64\*
54- -@erase /Q $(OBJ)\..\x64
55- -@erase /Q $(BIN)\..\x86\*
56- -@erase /Q $(BIN)\..\x86
57- -@erase /Q $(BIN)\..\x64\*
58- -@erase /Q $(BIN)\..\x64
50+ @if exist $(OBJ)\..\x86 RMDIR /S /Q $(OBJ)\..\x86
51+ @if exist $(OBJ)\..\x64 RMDIR /S /Q $(OBJ)\..\x64
5952
6053 $(BIN) :
6154 @if not exist $(BIN)/$(NULL) mkdir $(BIN)
@@ -63,18 +56,26 @@
6356 $(OBJ) :
6457 @if not exist $(OBJ)/$(NULL) mkdir $(OBJ)
6558
66-$(BIN)\exewrap.exe : $(BIN) $(OBJ) $(OBJ)\exewrap.obj $(OBJ)\message.obj $(OBJ)\jvm.obj $(OBJ)\image_console.img $(OBJ)\image_gui.img $(OBJ)\image_service.img $(OBJ)\exewrap.res $(OBJ)\ClassicLoader.class $(OBJ)\PackLoader.class $(OBJ)\JarOptimizer.class
67- $(LINK) $(LDFLAGS) /SUBSYSTEM:CONSOLE /MANIFEST:EMBED /OUT:$(BIN)\exewrap.exe $(OBJ)\exewrap.obj $(OBJ)\message.obj $(OBJ)\jvm.obj $(OBJ)\exewrap.res $(LIBS)
68- $(OBJ)\bindres.exe $(BIN)\exewrap.exe VERSION_INFO resources\versioninfo.bin
69- $(OBJ)\bindres.exe $(BIN)\exewrap.exe IMAGE_CONSOLE_32 $(OBJ)\..\x86\image_console.img
70- $(OBJ)\bindres.exe $(BIN)\exewrap.exe IMAGE_CONSOLE_64 $(OBJ)\..\x64\image_console.img
71- $(OBJ)\bindres.exe $(BIN)\exewrap.exe IMAGE_GUI_32 $(OBJ)\..\x86\image_gui.img
72- $(OBJ)\bindres.exe $(BIN)\exewrap.exe IMAGE_GUI_64 $(OBJ)\..\x64\image_gui.img
73- $(OBJ)\bindres.exe $(BIN)\exewrap.exe IMAGE_SERVICE_32 $(OBJ)\..\x86\image_service.img
74- $(OBJ)\bindres.exe $(BIN)\exewrap.exe IMAGE_SERVICE_64 $(OBJ)\..\x64\image_service.img
75- $(OBJ)\bindres.exe $(BIN)\exewrap.exe CLASSIC_LOADER $(OBJ)\ClassicLoader.class
76- $(OBJ)\bindres.exe $(BIN)\exewrap.exe PACK_LOADER $(OBJ)\PackLoader.class
77- $(OBJ)\bindres.exe $(BIN)\exewrap.exe JAR_OPTIMIZER $(OBJ)\JarOptimizer.class
59+$(BIN)\exewrap.exe : $(BIN) $(OBJ) $(OBJ)\exewrap.res $(OBJ)\exewrap.obj \
60+ $(OBJ)\jvm.obj $(OBJ)\loader.obj $(OBJ)\message.obj $(OBJ)\eventlog.obj \
61+ $(OBJ)\image_console.exe $(OBJ)\image_gui.exe $(OBJ)\image_service.exe \
62+ $(OBJ)\bindres.exe $(OBJ)\exewrap\core\ByteBufferInputStream.class $(OBJ)\exewrap\core\ExewrapClassLoader.class $(OBJ)\tool.jar
63+ $(LINK) $(LDFLAGS) /SUBSYSTEM:CONSOLE /MANIFEST:EMBED /OUT:$(BIN)\exewrap.exe $(OBJ)\exewrap.res $(OBJ)\exewrap.obj \
64+ $(OBJ)\jvm.obj $(OBJ)\loader.obj $(OBJ)\message.obj $(OBJ)\eventlog.obj $(LIBS)
65+ $(OBJ)\bindres.exe $(BIN)\exewrap.exe VERSION_INFO resources\versioninfo.bin
66+ $(OBJ)\bindres.exe -r $(BIN)\exewrap.exe IMAGE_CONSOLE_32 $(OBJ)\..\x86\image_console.exe
67+ $(OBJ)\bindres.exe -r $(BIN)\exewrap.exe IMAGE_CONSOLE_64 $(OBJ)\..\x64\image_console.exe
68+ $(OBJ)\bindres.exe -r $(BIN)\exewrap.exe IMAGE_GUI_32 $(OBJ)\..\x86\image_gui.exe
69+ $(OBJ)\bindres.exe -r $(BIN)\exewrap.exe IMAGE_GUI_64 $(OBJ)\..\x64\image_gui.exe
70+ $(OBJ)\bindres.exe -r $(BIN)\exewrap.exe IMAGE_SERVICE_32 $(OBJ)\..\x86\image_service.exe
71+ $(OBJ)\bindres.exe -r $(BIN)\exewrap.exe IMAGE_SERVICE_64 $(OBJ)\..\x64\image_service.exe
72+ $(OBJ)\bindres.exe $(BIN)\exewrap.exe BYTE_BUFFER_INPUT_STREAM $(OBJ)\exewrap\core\ByteBufferInputStream.class
73+ $(OBJ)\bindres.exe $(BIN)\exewrap.exe PACK_INPUT_STREAM $(OBJ)\exewrap\core\PackInputStream.class
74+ $(OBJ)\bindres.exe $(BIN)\exewrap.exe URL_CONNECTION $(OBJ)\exewrap\core\URLConnection.class
75+ $(OBJ)\bindres.exe $(BIN)\exewrap.exe URL_STREAM_HANDLER $(OBJ)\exewrap\core\URLStreamHandler.class
76+ $(OBJ)\bindres.exe $(BIN)\exewrap.exe EXEWRAP_CLASS_LOADER $(OBJ)\exewrap\core\ExewrapClassLoader.class
77+ $(OBJ)\bindres.exe $(BIN)\exewrap.exe UTIL_JAR $(OBJ)\util.jar
78+ $(OBJ)\bindres.exe $(BIN)\exewrap.exe JAR $(OBJ)\tool.jar
7879
7980 $(OBJ)\exewrap.obj : $(OBJ) exewrap.c
8081 $(CC) $(CFLAGS) $(INC) /Fo$(OBJ)\exewrap.obj exewrap.c
@@ -82,37 +83,56 @@
8283 $(OBJ)\exewrap.res : $(OBJ) resources\exewrap.rc
8384 $(RC) $(RCFLAGS) /fo$(OBJ)\exewrap.res resources\exewrap.rc
8485
85-$(OBJ)\image_console.img : $(OBJ) $(OBJ)\image_console.obj $(OBJ)\image_console.res $(OBJ)\notify.obj $(OBJ)\message.obj $(OBJ)\jvm.obj $(OBJ)\bindres.exe $(OBJ)\URLConnection.class $(OBJ)\URLStreamHandler.class
86- $(LINK) $(LDFLAGS) /SUBSYSTEM:CONSOLE /MANIFEST:EMBED /OUT:$(OBJ)\image_console.img $(OBJ)\image_console.obj $(OBJ)\image_console.res $(OBJ)\notify.obj $(OBJ)\message.obj $(OBJ)\jvm.obj $(LIBS)
87- $(OBJ)\bindres.exe $(OBJ)\image_console.img URL_CONNECTION $(OBJ)\URLConnection.class
88- $(OBJ)\bindres.exe $(OBJ)\image_console.img URL_STREAM_HANDLER $(OBJ)\URLStreamHandler.class
86+$(OBJ)\image_console.exe : $(OBJ) $(OBJ)\image_console.res $(OBJ)\image_console.obj \
87+ $(OBJ)\jvm.obj $(OBJ)\loader.obj $(OBJ)\message.obj $(OBJ)\notify.obj $(OBJ)\eventlog.obj \
88+ $(OBJ)\bindres.exe $(OBJ)\exewrap\core\ByteBufferInputStream.class $(OBJ)\exewrap\core\PackInputStream.class $(OBJ)\exewrap\core\ExewrapClassLoader.class $(OBJ)\exewrap\core\URLConnection.class $(OBJ)\exewrap\core\URLStreamHandler.class $(OBJ)\util.jar
89+ $(LINK) $(LDFLAGS) /SUBSYSTEM:CONSOLE /MANIFEST:EMBED /OUT:$(OBJ)\image_console.exe $(OBJ)\image_console.obj \
90+ $(OBJ)\jvm.obj $(OBJ)\loader.obj $(OBJ)\message.obj $(OBJ)\notify.obj $(OBJ)\eventlog.obj $(LIBS)
91+ $(OBJ)\bindres.exe $(OBJ)\image_console.exe BYTE_BUFFER_INPUT_STREAM $(OBJ)\exewrap\core\ByteBufferInputStream.class
92+ $(OBJ)\bindres.exe $(OBJ)\image_console.exe PACK_INPUT_STREAM $(OBJ)\exewrap\core\PackInputStream.class
93+ $(OBJ)\bindres.exe $(OBJ)\image_console.exe URL_CONNECTION $(OBJ)\exewrap\core\URLConnection.class
94+ $(OBJ)\bindres.exe $(OBJ)\image_console.exe URL_STREAM_HANDLER $(OBJ)\exewrap\core\URLStreamHandler.class
95+ $(OBJ)\bindres.exe $(OBJ)\image_console.exe EXEWRAP_CLASS_LOADER $(OBJ)\exewrap\core\ExewrapClassLoader.class
96+ $(OBJ)\bindres.exe $(OBJ)\image_console.exe UTIL_JAR $(OBJ)\util.jar
97+# $(OBJ)\bindres.exe $(OBJ)\image_console.exe PACK_GZ ..\helloworld.pack.gz
8998
9099 $(OBJ)\image_console.obj : $(OBJ) image_console.c
91100 $(CC) $(CFLAGS) $(INC) /Fo$(OBJ)\image_console.obj image_console.c
92101
93-$(OBJ)\image_console.res : $(OBJ) resources\image_console.rc
102+$(OBJ)\image_console.res : $(OBJ) resources\image_console.rc resources\eventlog.bin
94103 $(RC) $(RCFLAGS) /fo$(OBJ)\image_console.res resources\image_console.rc
104+
105+$(OBJ)\image_gui.exe : $(OBJ) $(OBJ)\image_gui.res $(OBJ)\image_gui.obj \
106+ $(OBJ)\jvm.obj $(OBJ)\loader.obj $(OBJ)\message.obj $(OBJ)\notify.obj $(OBJ)\eventlog.obj \
107+ $(OBJ)\bindres.exe $(OBJ)\exewrap\core\ByteBufferInputStream.class $(OBJ)\exewrap\core\PackInputStream.class $(OBJ)\exewrap\core\ExewrapClassLoader.class $(OBJ)\exewrap\core\URLConnection.class $(OBJ)\exewrap\core\URLStreamHandler.class $(OBJ)\util.jar
108+ $(LINK) $(LDFLAGS) /SUBSYSTEM:WINDOWS /MANIFEST:EMBED /OUT:$(OBJ)\image_gui.exe $(OBJ)\image_gui.res $(OBJ)\image_gui.obj \
109+ $(OBJ)\jvm.obj $(OBJ)\loader.obj $(OBJ)\message.obj $(OBJ)\notify.obj $(OBJ)\eventlog.obj $(LIBS)
110+ $(OBJ)\bindres.exe $(OBJ)\image_gui.exe BYTE_BUFFER_INPUT_STREAM $(OBJ)\exewrap\core\ByteBufferInputStream.class
111+ $(OBJ)\bindres.exe $(OBJ)\image_gui.exe PACK_INPUT_STREAM $(OBJ)\exewrap\core\PackInputStream.class
112+ $(OBJ)\bindres.exe $(OBJ)\image_gui.exe URL_CONNECTION $(OBJ)\exewrap\core\URLConnection.class
113+ $(OBJ)\bindres.exe $(OBJ)\image_gui.exe URL_STREAM_HANDLER $(OBJ)\exewrap\core\URLStreamHandler.class
114+ $(OBJ)\bindres.exe $(OBJ)\image_gui.exe EXEWRAP_CLASS_LOADER $(OBJ)\exewrap\core\ExewrapClassLoader.class
115+ $(OBJ)\bindres.exe $(OBJ)\image_gui.exe UTIL_JAR $(OBJ)\util.jar
116+ $(OBJ)\bindres.exe $(OBJ)\image_gui.exe JAR ..\samples\Sample04.jar
95117
96-$(OBJ)\image_gui.img : $(OBJ) $(OBJ)\image_gui.obj $(OBJ)\image_gui.res $(OBJ)\notify.obj $(OBJ)\message.obj $(OBJ)\jvm.obj $(OBJ)\bindres.exe $(OBJ)\FileLogStream.class $(OBJ)\UncaughtHandler.class $(OBJ)\URLConnection.class $(OBJ)\URLStreamHandler.class
97- $(LINK) $(LDFLAGS) /SUBSYSTEM:WINDOWS /MANIFEST:EMBED /OUT:$(OBJ)\image_gui.img $(OBJ)\image_gui.obj $(OBJ)\image_gui.res $(OBJ)\notify.obj $(OBJ)\message.obj $(OBJ)\jvm.obj $(LIBS)
98- $(OBJ)\bindres.exe $(OBJ)\image_gui.img FILELOG_STREAM $(OBJ)\FileLogStream.class
99- $(OBJ)\bindres.exe $(OBJ)\image_gui.img UNCAUGHT_HANDLER $(OBJ)\UncaughtHandler.class
100- $(OBJ)\bindres.exe $(OBJ)\image_gui.img URL_CONNECTION $(OBJ)\URLConnection.class
101- $(OBJ)\bindres.exe $(OBJ)\image_gui.img URL_STREAM_HANDLER $(OBJ)\URLStreamHandler.class
102-
103118 $(OBJ)\image_gui.obj : $(OBJ) image_gui.c
104119 $(CC) $(CFLAGS) $(INC) /Fo$(OBJ)\image_gui.obj image_gui.c
105120
106-$(OBJ)\image_gui.res : $(OBJ) resources\image_gui.rc
121+$(OBJ)\image_gui.res : $(OBJ) resources\image_gui.rc resources\eventlog.bin
107122 $(RC) $(RCFLAGS) /fo$(OBJ)\image_gui.res resources\image_gui.rc
108123
109-$(OBJ)\image_service.img : $(OBJ) $(OBJ)\image_service.obj $(OBJ)\image_service.res $(OBJ)\service.obj $(OBJ)\eventlog.obj $(OBJ)\message.obj $(OBJ)\jvm.obj $(OBJ)\bindres.exe $(OBJ)\EventLogStream.class $(OBJ)\EventLogHandler.class $(OBJ)\UncaughtHandler.class $(OBJ)\URLConnection.class $(OBJ)\URLStreamHandler.class
110- $(LINK) $(LDFLAGS) /SUBSYSTEM:CONSOLE /MANIFEST:EMBED /OUT:$(OBJ)\image_service.img $(OBJ)\image_service.obj $(OBJ)\image_service.res $(OBJ)\service.obj $(OBJ)\eventlog.obj $(OBJ)\message.obj $(OBJ)\jvm.obj $(LIBS)
111- $(OBJ)\bindres.exe $(OBJ)\image_service.img EVENTLOG_STREAM $(OBJ)\EventLogStream.class
112- $(OBJ)\bindres.exe $(OBJ)\image_service.img EVENTLOG_HANDLER $(OBJ)\EventLogHandler.class
113- $(OBJ)\bindres.exe $(OBJ)\image_service.img UNCAUGHT_HANDLER $(OBJ)\UncaughtHandler.class
114- $(OBJ)\bindres.exe $(OBJ)\image_service.img URL_CONNECTION $(OBJ)\URLConnection.class
115- $(OBJ)\bindres.exe $(OBJ)\image_service.img URL_STREAM_HANDLER $(OBJ)\URLStreamHandler.class
124+$(OBJ)\image_service.exe : $(OBJ) $(OBJ)\image_service.res $(OBJ)\image_service.obj \
125+ $(OBJ)\jvm.obj $(OBJ)\loader.obj $(OBJ)\message.obj $(OBJ)\eventlog.obj \
126+ $(OBJ)\bindres.exe $(OBJ)\exewrap\core\ByteBufferInputStream.class $(OBJ)\exewrap\core\PackInputStream.class $(OBJ)\exewrap\core\ExewrapClassLoader.class $(OBJ)\exewrap\core\URLConnection.class $(OBJ)\exewrap\core\URLStreamHandler.class $(OBJ)\util.jar
127+ $(LINK) $(LDFLAGS) /SUBSYSTEM:CONSOLE /MANIFEST:EMBED /OUT:$(OBJ)\image_service.exe $(OBJ)\image_service.res $(OBJ)\image_service.obj \
128+ $(OBJ)\jvm.obj $(OBJ)\loader.obj $(OBJ)\message.obj $(OBJ)\eventlog.obj $(LIBS)
129+ $(OBJ)\bindres.exe $(OBJ)\image_service.exe BYTE_BUFFER_INPUT_STREAM $(OBJ)\exewrap\core\ByteBufferInputStream.class
130+ $(OBJ)\bindres.exe $(OBJ)\image_service.exe PACK_INPUT_STREAM $(OBJ)\exewrap\core\PackInputStream.class
131+ $(OBJ)\bindres.exe $(OBJ)\image_service.exe URL_CONNECTION $(OBJ)\exewrap\core\URLConnection.class
132+ $(OBJ)\bindres.exe $(OBJ)\image_service.exe URL_STREAM_HANDLER $(OBJ)\exewrap\core\URLStreamHandler.class
133+ $(OBJ)\bindres.exe $(OBJ)\image_service.exe EXEWRAP_CLASS_LOADER $(OBJ)\exewrap\core\ExewrapClassLoader.class
134+ $(OBJ)\bindres.exe $(OBJ)\image_service.exe UTIL_JAR $(OBJ)\util.jar
135+ $(OBJ)\bindres.exe $(OBJ)\image_service.exe JAR ..\samples\ServiceSample.jar
116136
117137 $(OBJ)\image_service.obj : $(OBJ) image_service.c
118138 $(CC) $(CFLAGS) $(INC) /Fo$(OBJ)\image_service.obj image_service.c
@@ -120,9 +140,6 @@
120140 $(OBJ)\image_service.res : $(OBJ) resources\image_service.rc resources\eventlog.bin
121141 $(RC) $(RCFLAGS) /fo$(OBJ)\image_service.res resources\image_service.rc
122142
123-$(OBJ)\service.obj : $(OBJ) service.c
124- $(CC) $(CFLAGS) $(INC) /Fo$(OBJ)\service.obj service.c
125-
126143 $(OBJ)\eventlog.obj : $(OBJ) eventlog.c
127144 $(CC) $(CFLAGS) $(INC) /Fo$(OBJ)\eventlog.obj eventlog.c
128145
@@ -132,6 +149,9 @@
132149 $(OBJ)\message.obj : $(OBJ) message.c
133150 $(CC) $(CFLAGS) $(INC) /Fo$(OBJ)\message.obj message.c
134151
152+$(OBJ)\loader.obj : $(OBJ) loader.c
153+ $(CC) $(CFLAGS) $(INC) /Fo$(OBJ)\loader.obj loader.c
154+
135155 $(OBJ)\jvm.obj : $(OBJ) jvm.c
136156 $(CC) $(CFLAGS) $(INC) /Fo$(OBJ)\jvm.obj jvm.c
137157
@@ -141,30 +161,52 @@
141161 $(OBJ)\bindres.obj : $(OBJ) bindres.c
142162 $(CC) $(CFLAGS) $(INC) /Fo$(OBJ)\bindres.obj bindres.c
143163
144-$(OBJ)\JarOptimizer.class : java\JarOptimizer.java
145- $(JAVAC) -Xlint:none -source 1.5 -target 1.5 -sourcepath java -d $(OBJ) java\JarOptimizer.java
164+###
165+### Java
166+###
146167
147-$(OBJ)\PackLoader.class : java\PackLoader.java
148- $(JAVAC) -Xlint:none -source 1.2 -target 1.5 -sourcepath java -d $(OBJ) java\PackLoader.java
168+### exewrap.core
149169
150-$(OBJ)\ClassicLoader.class : java\ClassicLoader.java
151- $(JAVAC) -Xlint:none -source 1.2 -target 1.2 -sourcepath java -d $(OBJ) java\ClassicLoader.java
170+$(OBJ)\exewrap\core\ExewrapClassLoader.class : $(OBJ) java\exewrap\core\ExewrapClassLoader.java
171+ $(JAVAC) -Xlint:none -source 1.5 -target 1.5 -sourcepath java -d $(OBJ) java\exewrap\core\ExewrapClassLoader.java
152172
153-$(OBJ)\FileLogStream.class : java\FileLogStream.java
154- $(JAVAC) -Xlint:none -source 1.2 -target 1.2 -sourcepath java -d $(OBJ) java\FileLogStream.java
173+$(OBJ)\exewrap\core\PackInputStream.class : $(OBJ) java\exewrap\core\PackInputStream.java
174+ $(JAVAC) -Xlint:none -source 1.5 -target 1.5 -sourcepath java -d $(OBJ) java\exewrap\core\PackInputStream.java
155175
156-$(OBJ)\EventLogStream.class : java\EventLogStream.java
157- $(JAVAC) -Xlint:none -source 1.2 -target 1.2 -sourcepath java -d $(OBJ) java\EventLogStream.java
176+$(OBJ)\exewrap\core\ByteBufferInputStream.class : $(OBJ) java\exewrap\core\ByteBufferInputStream.java
177+ $(JAVAC) -Xlint:none -source 1.5 -target 1.5 -sourcepath java -d $(OBJ) java\exewrap\core\ByteBufferInputStream.java
158178
159-$(OBJ)\EventLogHandler.class : java\EventLogHandler.java
160- $(JAVAC) -Xlint:none -source 1.4 -target 1.4 -sourcepath java -d $(OBJ) java\EventLogHandler.java
179+$(OBJ)\exewrap\core\URLConnection.class : $(OBJ) java\exewrap\core\URLConnection.java
180+ $(JAVAC) -Xlint:none -source 1.5 -target 1.5 -sourcepath java -d $(OBJ) java\exewrap\core\URLConnection.java
161181
162-$(OBJ)\UncaughtHandler.class : java\UncaughtHandler.java
163- $(JAVAC) -Xlint:none -source 1.2 -target 1.2 -sourcepath java -d $(OBJ) java\UncaughtHandler.java
182+$(OBJ)\exewrap\core\URLStreamHandler.class : $(OBJ) java\exewrap\core\URLStreamHandler.java
183+ $(JAVAC) -Xlint:none -source 1.5 -target 1.5 -sourcepath java -d $(OBJ) java\exewrap\core\URLStreamHandler.java
164184
165-$(OBJ)\URLConnection.class : java\URLConnection.java
166- $(JAVAC) -Xlint:none -source 1.2 -target 1.2 -sourcepath java -d $(OBJ) java\URLConnection.java
185+### exewrap.util
167186
168-$(OBJ)\URLStreamHandler.class : java\URLStreamHandler.java
169- $(JAVAC) -Xlint:none -source 1.2 -target 1.2 -sourcepath java -d $(OBJ) java\URLStreamHandler.java
187+$(OBJ)\util.jar : $(OBJ) $(OBJ)\exewrap\util\EventLogHandler.class $(OBJ)\exewrap\util\EventLogStream.class $(OBJ)\exewrap\util\FileLogStream.class $(OBJ)\exewrap\util\UncaughtExceptionHandler.class
188+ $(JAR) cvf $(OBJ)\util.jar -C $(OBJ) exewrap\util
170189
190+$(OBJ)\exewrap\util\EventLogHandler.class : $(OBJ) java\exewrap\util\EventLogHandler.java
191+ $(JAVAC) -Xlint:none -source 1.5 -target 1.5 -sourcepath java -d $(OBJ) java\exewrap\util\EventLogHandler.java
192+
193+$(OBJ)\exewrap\util\EventLogStream.class : $(OBJ) java\exewrap\util\EventLogStream.java
194+ $(JAVAC) -Xlint:none -source 1.5 -target 1.5 -sourcepath java -d $(OBJ) java\exewrap\util\EventLogStream.java
195+
196+$(OBJ)\exewrap\util\FileLogStream.class : $(OBJ) java\exewrap\util\FileLogStream.java
197+ $(JAVAC) -Xlint:none -source 1.5 -target 1.5 -sourcepath java -d $(OBJ) java\exewrap\util\FileLogStream.java
198+
199+$(OBJ)\exewrap\util\UncaughtExceptionHandler.class : $(OBJ) java\exewrap\util\UncaughtExceptionHandler.java
200+ $(JAVAC) -Xlint:none -source 1.5 -target 1.5 -sourcepath java -d $(OBJ) java\exewrap\util\UncaughtExceptionHandler.java
201+
202+### exewrap.tool
203+
204+$(OBJ)\tool.jar : $(OBJ) $(OBJ)\exewrap\tool\JarProcessor.class $(OBJ)\exewrap\tool\PackOutputStream.class
205+ $(JAR) cvfe $(OBJ)\tool.jar exewrap.tool.JarProcessor -C $(OBJ) exewrap\tool
206+
207+$(OBJ)\exewrap\tool\PackOutputStream.class : $(OBJ) java\exewrap\tool\PackOutputStream.java
208+ $(JAVAC) -Xlint:none -source 1.5 -target 1.5 -sourcepath java -d $(OBJ) java\exewrap\tool\PackOutputStream.java
209+
210+$(OBJ)\exewrap\tool\JarProcessor.class : $(OBJ) java\exewrap\tool\JarProcessor.java
211+ $(JAVAC) -Xlint:none -source 1.5 -target 1.5 -sourcepath java -d $(OBJ) java\exewrap\tool\JarProcessor.java
212+
--- exewrap/trunk/exewrap/src/jvm.c (revision 19)
+++ exewrap/trunk/exewrap/src/jvm.c (revision 20)
@@ -465,7 +465,7 @@
465465
466466 if(relative_classpath != NULL)
467467 {
468- while((token = strtok(relative_classpath, ";")) != NULL)
468+ while((token = strtok(relative_classpath, " ")) != NULL)
469469 {
470470 if(strstr(token, ":") == NULL)
471471 {
@@ -670,9 +670,17 @@
670670
671671 char* GetModuleVersion(char* buf)
672672 {
673- HRSRC hrsrc = FindResource(NULL, (char*)VS_VERSION_INFO, RT_VERSION);
674- VS_FIXEDFILEINFO* verInfo = (VS_FIXEDFILEINFO*)((char*)LockResource(LoadResource(NULL, hrsrc)) + 40);
673+ HRSRC hrsrc;
674+ VS_FIXEDFILEINFO* verInfo;
675675
676+ hrsrc = FindResource(NULL, (char*)VS_VERSION_INFO, RT_VERSION);
677+ if (hrsrc == NULL)
678+ {
679+ *buf = '\0';
680+ return buf;
681+ }
682+
683+ verInfo = (VS_FIXEDFILEINFO*)((char*)LockResource(LoadResource(NULL, hrsrc)) + 40);
676684 sprintf(buf, "%d.%d.%d.%d",
677685 verInfo->dwFileVersionMS >> 16,
678686 verInfo->dwFileVersionMS & 0xFFFF,
--- exewrap/trunk/exewrap/src/java/exewrap/core/URLConnection.java (revision 0)
+++ exewrap/trunk/exewrap/src/java/exewrap/core/URLConnection.java (revision 20)
@@ -0,0 +1,31 @@
1+package exewrap.core;
2+
3+import java.io.ByteArrayInputStream;
4+import java.io.IOException;
5+import java.io.InputStream;
6+import java.net.URL;
7+
8+public class URLConnection extends java.net.URLConnection {
9+
10+ private byte[] buf;
11+ private InputStream in;
12+
13+ protected URLConnection(URL url, byte[] buf) {
14+ super(url);
15+ this.buf = buf;
16+ }
17+
18+ public void connect() throws IOException {
19+ if(this.in != null) {
20+ try { this.in.close(); } catch(Exception ex) {}
21+ }
22+ this.in = new ByteArrayInputStream(this.buf);
23+ }
24+
25+ public InputStream getInputStream() throws IOException {
26+ if(this.in == null) {
27+ connect();
28+ }
29+ return this.in;
30+ }
31+}
--- exewrap/trunk/exewrap/src/java/exewrap/core/ExewrapClassLoader.java (revision 0)
+++ exewrap/trunk/exewrap/src/java/exewrap/core/ExewrapClassLoader.java (revision 20)
@@ -0,0 +1,171 @@
1+package exewrap.core;
2+
3+import java.io.ByteArrayOutputStream;
4+import java.io.IOException;
5+import java.lang.reflect.Field;
6+import java.net.MalformedURLException;
7+import java.net.URL;
8+import java.util.HashMap;
9+import java.util.LinkedList;
10+import java.util.Map;
11+import java.util.Queue;
12+import java.util.jar.Attributes.Name;
13+import java.util.jar.JarEntry;
14+import java.util.jar.JarInputStream;
15+import java.util.jar.Manifest;
16+
17+public class ExewrapClassLoader extends ClassLoader {
18+
19+ private Map<String, byte[]> classes = new HashMap<String, byte[]>();
20+ private Map<String, byte[]> resources = new HashMap<String, byte[]>();
21+ private Queue<JarInputStream> inputs = new LinkedList<JarInputStream>();
22+ private JarInputStream in;
23+ private String mainClassName;
24+ private URL context;
25+
26+ public ExewrapClassLoader(ClassLoader parent, JarInputStream[] inputs) throws MalformedURLException {
27+ super(parent);
28+ for(JarInputStream in : inputs) {
29+ Manifest manifest = in.getManifest();
30+ if(manifest != null) {
31+ this.mainClassName = manifest.getMainAttributes().getValue(Name.MAIN_CLASS);
32+ }
33+ this.inputs.offer(in);
34+ }
35+ this.in = this.inputs.poll();
36+
37+ String path = System.getProperty("java.application.path");
38+ if(path == null) {
39+ path = "";
40+ }
41+ String name = System.getProperty("java.application.name");
42+ if(name == null) {
43+ name = "";
44+ }
45+
46+ this.context = new URL("jar:file:/" + path.replace('\\', '/') + '/' + name + "!/");
47+ }
48+
49+ public void registerSystemClassLoader() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
50+ Field scl = ClassLoader.class.getDeclaredField("scl");
51+ scl.setAccessible(true);
52+ scl.set(null, this);
53+ }
54+
55+ public void loadUtilities(String utilities) throws ClassNotFoundException {
56+ if(utilities == null) {
57+ return;
58+ }
59+ if(utilities.contains("UncaughtExceptionHandler;")) {
60+ Class.forName("exewrap.util.UncaughtExceptionHandler", true, this);
61+ }
62+ if(utilities.contains("FileLogStream;")) {
63+ Class.forName("exewrap.util.FileLogStream", true, this);
64+ }
65+ if(utilities.contains("EventLogStream;")) {
66+ Class.forName("exewrap.util.EventLogStream", true, this);
67+ }
68+ if(utilities.contains("EventLogHandler;")) {
69+ Class.forName("exewrap.util.EventLogHandler", true, this);
70+ }
71+ }
72+
73+ public Class<?> getMainClass(String mainClassName) throws ClassNotFoundException {
74+ if(mainClassName != null) {
75+ return loadClass(mainClassName);
76+ }
77+ if(this.mainClassName != null) {
78+ return loadClass(this.mainClassName);
79+ }
80+ return null;
81+ }
82+
83+ public void setSplashScreenResource(String name, byte[] image) {
84+ this.resources.put(name, image);
85+ }
86+
87+ protected Class<?> findClass(String name) throws ClassNotFoundException {
88+ String entryName = name.replace('.', '/') + ".class";
89+ byte[] bytes = this.classes.remove(entryName);
90+ if(bytes == null) {
91+ try {
92+ bytes = find(entryName);
93+ } catch(IOException ex) {
94+ throw new ClassNotFoundException(name, ex);
95+ }
96+ }
97+ if(bytes == null) {
98+ throw new ClassNotFoundException(name);
99+ }
100+
101+ if(name.indexOf('.') >= 0) {
102+ String packageName = name.substring(0, name.lastIndexOf('.'));
103+ if(getPackage(packageName) == null) {
104+ definePackage(packageName, null, null, null, null, null, null, null);
105+ }
106+ }
107+ return defineClass(name, bytes, 0, bytes.length);
108+ }
109+
110+ protected URL findResource(String name) {
111+ byte[] bytes = this.resources.get(name);
112+ if(bytes == null) {
113+ try {
114+ bytes = find(name);
115+ } catch (IOException ex) {
116+ throw new RuntimeException(ex);
117+ }
118+ }
119+ if(bytes == null) {
120+ return null;
121+ }
122+
123+ try {
124+ return new URL(this.context, name, new URLStreamHandler(bytes));
125+ } catch (MalformedURLException e) {
126+ e.printStackTrace();
127+ return null;
128+ }
129+ }
130+
131+ private byte[] find(String name) throws IOException {
132+ while(this.in != null) {
133+ JarEntry jarEntry;
134+ while((jarEntry = this.in.getNextJarEntry()) != null) {
135+ byte[] bytes = readJarEntryBytes(in);
136+ this.resources.put(jarEntry.getName(), bytes);
137+ if(jarEntry.getName().endsWith(".class")) {
138+ if(jarEntry.getName().equals(name)) {
139+ return bytes;
140+ } else {
141+ this.classes.put(jarEntry.getName(), bytes);
142+ }
143+ } else {
144+ if(jarEntry.getName().equals(name)) {
145+ return bytes;
146+ }
147+ }
148+ in.closeEntry();
149+ }
150+ this.in.close();
151+ this.in = this.inputs.poll();
152+ }
153+ return null;
154+ }
155+
156+ private byte[] readJarEntryBytes(JarInputStream in) throws IOException {
157+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
158+ byte[] bytes = new byte[65536];
159+ int len = 0;
160+ while(len != -1) {
161+ len = in.read(bytes);
162+ if(len > 0) {
163+ buf.write(bytes, 0, len);
164+ }
165+ }
166+ return buf.toByteArray();
167+ }
168+
169+ public static native void WriteEventLog(int type, String message);
170+ public static native void UncaughtException(String thread, String message, String trace);
171+}
--- exewrap/trunk/exewrap/src/java/exewrap/core/ByteBufferInputStream.java (revision 0)
+++ exewrap/trunk/exewrap/src/java/exewrap/core/ByteBufferInputStream.java (revision 20)
@@ -0,0 +1,30 @@
1+package exewrap.core;
2+
3+import java.io.IOException;
4+import java.io.InputStream;
5+import java.nio.ByteBuffer;
6+
7+public class ByteBufferInputStream extends InputStream {
8+
9+ private ByteBuffer buf;
10+
11+ public ByteBufferInputStream(ByteBuffer buf) {
12+ this.buf = buf;
13+ }
14+
15+ public int read() throws IOException {
16+ if(!buf.hasRemaining()) {
17+ return -1;
18+ }
19+ return buf.get() & 0xFF;
20+ }
21+
22+ public int read(byte[] bytes, int off, int len) throws IOException {
23+ if (!buf.hasRemaining()) {
24+ return -1;
25+ }
26+ len = Math.min(len, buf.remaining());
27+ buf.get(bytes, off, len);
28+ return len;
29+ }
30+}
--- exewrap/trunk/exewrap/src/java/exewrap/core/PackInputStream.java (revision 0)
+++ exewrap/trunk/exewrap/src/java/exewrap/core/PackInputStream.java (revision 20)
@@ -0,0 +1,117 @@
1+package exewrap.core;
2+
3+import java.io.IOException;
4+import java.io.InputStream;
5+import java.io.PipedInputStream;
6+import java.io.PipedOutputStream;
7+import java.util.jar.JarOutputStream;
8+import java.util.jar.Pack200;
9+
10+public class PackInputStream extends InputStream implements Runnable {
11+
12+ private static final int PIPE_SIZE = 512 * 1024;
13+ private InputStream in;
14+ private PipedInputStream pipeIn;
15+ private JarOutputStream jarOut;
16+ private IOException exception;
17+
18+ public PackInputStream(InputStream in) {
19+ this.in = in;
20+ }
21+
22+ public void run() {
23+ try {
24+ Pack200.newUnpacker().unpack(PackInputStream.this.in, this.jarOut);
25+ } catch(IOException e) {
26+ if(PackInputStream.this.exception == null) {
27+ PackInputStream.this.exception = e;
28+ }
29+ }
30+ try {
31+ if(this.jarOut != null) {
32+ this.jarOut.finish();
33+ }
34+ } catch(IOException e) {
35+ if(PackInputStream.this.exception == null) {
36+ PackInputStream.this.exception = e;
37+ }
38+ }
39+ try {
40+ if(this.jarOut != null) {
41+ this.jarOut.close();
42+ }
43+ } catch(IOException e) {
44+ if(PackInputStream.this.exception == null) {
45+ PackInputStream.this.exception = e;
46+ }
47+ }
48+ }
49+
50+ private void init() throws IOException {
51+ PipedOutputStream pipeOut = new PipedOutputStream();
52+ this.jarOut = new JarOutputStream(pipeOut);
53+ this.pipeIn = new PipedInputStream(pipeOut, PIPE_SIZE);
54+
55+ new Thread(this).start();
56+ }
57+
58+ public int available() throws IOException {
59+ if(this.exception != null) {
60+ throw this.exception;
61+ }
62+
63+ if(this.pipeIn == null) {
64+ init();
65+ }
66+ return this.pipeIn.available();
67+ }
68+
69+ public long skip(long n) throws IOException {
70+ if(this.exception != null) {
71+ throw this.exception;
72+ }
73+
74+ if(this.pipeIn == null) {
75+ init();
76+ }
77+ return this.pipeIn.skip(n);
78+ }
79+
80+ public int read() throws IOException {
81+ if(this.exception != null) {
82+ throw this.exception;
83+ }
84+
85+ if(this.pipeIn == null) {
86+ init();
87+ }
88+ return this.pipeIn.read();
89+ }
90+
91+ public int read(byte[] b) throws IOException {
92+ if(this.exception != null) {
93+ throw this.exception;
94+ }
95+
96+ if(this.pipeIn == null) {
97+ init();
98+ }
99+ return this.pipeIn.read(b);
100+ }
101+
102+ public int read(byte[] b, int off, int len) throws IOException {
103+ if(this.exception != null) {
104+ throw this.exception;
105+ }
106+
107+ if(this.pipeIn == null) {
108+ init();
109+ }
110+ return this.pipeIn.read(b, off, len);
111+ }
112+
113+ public void close() throws IOException {
114+ this.pipeIn.close();
115+ this.in.close();
116+ }
117+}
--- exewrap/trunk/exewrap/src/java/exewrap/core/URLStreamHandler.java (revision 0)
+++ exewrap/trunk/exewrap/src/java/exewrap/core/URLStreamHandler.java (revision 20)
@@ -0,0 +1,17 @@
1+package exewrap.core;
2+
3+import java.io.IOException;
4+import java.net.URL;
5+
6+public class URLStreamHandler extends java.net.URLStreamHandler {
7+
8+ private byte[] buf;
9+
10+ public URLStreamHandler(byte[] buf) {
11+ this.buf = buf;
12+ }
13+
14+ protected java.net.URLConnection openConnection(URL url) throws IOException {
15+ return new URLConnection(url, this.buf);
16+ }
17+}
--- exewrap/trunk/exewrap/src/java/exewrap/tool/PackOutputStream.java (revision 0)
+++ exewrap/trunk/exewrap/src/java/exewrap/tool/PackOutputStream.java (revision 20)
@@ -0,0 +1,158 @@
1+package exewrap.tool;
2+
3+import java.io.IOException;
4+import java.io.OutputStream;
5+import java.io.PipedInputStream;
6+import java.io.PipedOutputStream;
7+import java.lang.reflect.InvocationTargetException;
8+import java.lang.reflect.Method;
9+import java.util.jar.JarInputStream;
10+import java.util.jar.Pack200;
11+
12+public class PackOutputStream extends OutputStream implements Runnable {
13+
14+ private static final int PIPE_SIZE = 256 * 1024;
15+ private OutputStream out;
16+ private PipedOutputStream pipeOut;
17+ private PipedInputStream pipeIn;
18+ private IOException exception;
19+ private volatile boolean isPackCompleted = false;
20+ private volatile boolean isOutputStreamClosed = false;
21+
22+ public PackOutputStream(OutputStream out) {
23+ this.out = out;
24+ }
25+
26+ public void run() {
27+ try {
28+ pipeIn = new PipedInputStream(this.pipeOut, PIPE_SIZE);
29+ synchronized(this) {
30+ notifyAll();
31+ }
32+ JarInputStream jarIn = new JarInputStream(pipeIn);
33+ Pack200.newPacker().pack(jarIn, this.out);
34+ isPackCompleted = true;
35+ finish(this.out);
36+ this.out.close();
37+ } catch (IOException e) {
38+ e.printStackTrace();
39+ if(this.exception == null) {
40+ this.exception = e;
41+ }
42+ }
43+ synchronized (this) {
44+ this.isOutputStreamClosed = true;
45+ synchronized(this.pipeOut) {
46+ notifyAll();
47+ }
48+ }
49+ }
50+
51+ private void init() throws IOException {
52+ this.pipeOut = new PipedOutputStream();
53+
54+ synchronized(this) {
55+ new Thread(this).start();
56+ try { wait(); } catch (InterruptedException e) {}
57+ }
58+ }
59+
60+ @Override
61+ public void write(int b) throws IOException {
62+ if(this.exception != null) {
63+ throw this.exception;
64+ }
65+
66+ if(this.pipeOut == null) {
67+ init();
68+ }
69+ if(!this.isPackCompleted) {
70+ this.pipeOut.write(b);
71+ this.pipeOut.flush();
72+ }
73+ }
74+
75+ @Override
76+ public void write(byte[] b) throws IOException {
77+ if(this.exception != null) {
78+ throw this.exception;
79+ }
80+
81+ if(this.pipeOut == null) {
82+ init();
83+ }
84+ if(!this.isPackCompleted) {
85+ this.pipeOut.write(b);
86+ this.pipeOut.flush();
87+ }
88+ }
89+
90+ @Override
91+ public void write(byte[] b, int off, int len) throws IOException {
92+ if(this.exception != null) {
93+ throw this.exception;
94+ }
95+
96+ if(this.pipeOut == null) {
97+ init();
98+ }
99+ if(!isPackCompleted) {
100+ this.pipeOut.write(b, off, len);
101+ this.pipeOut.flush();
102+ }
103+ }
104+
105+ @Override
106+ public void flush() throws IOException {
107+ if(this.exception != null) {
108+ throw this.exception;
109+ }
110+
111+ if(this.pipeOut == null) {
112+ init();
113+ }
114+ this.pipeOut.flush();
115+ }
116+
117+ @Override
118+ public void close() throws IOException {
119+ if(this.exception != null) {
120+ throw this.exception;
121+ }
122+
123+ if(this.pipeOut == null) {
124+ init();
125+ }
126+ while(pipeIn.available() > 0) {
127+ Thread.yield();
128+ }
129+ this.pipeOut.close();
130+
131+ synchronized(this) {
132+ if(!isOutputStreamClosed) {
133+ try { wait(); } catch (InterruptedException e) {}
134+ }
135+ }
136+ }
137+
138+ private static boolean finish(OutputStream out) {
139+ boolean succeeded = false;
140+ Method finish = null;
141+
142+ try {
143+ finish = out.getClass().getMethod("finish");
144+ } catch (NoSuchMethodException e) {
145+ } catch (SecurityException e) {
146+ }
147+ if(finish != null) {
148+ try {
149+ finish.invoke(out);
150+ succeeded = true;
151+ } catch (IllegalAccessException e) {
152+ } catch (IllegalArgumentException e) {
153+ } catch (InvocationTargetException e) {
154+ }
155+ }
156+ return succeeded;
157+ }
158+}
--- exewrap/trunk/exewrap/src/java/exewrap/tool/JarProcessor.java (revision 0)
+++ exewrap/trunk/exewrap/src/java/exewrap/tool/JarProcessor.java (revision 20)
@@ -0,0 +1,136 @@
1+package exewrap.tool;
2+
3+import java.io.ByteArrayInputStream;
4+import java.io.ByteArrayOutputStream;
5+import java.io.IOException;
6+import java.io.InputStream;
7+import java.util.jar.JarEntry;
8+import java.util.jar.JarInputStream;
9+import java.util.jar.JarOutputStream;
10+import java.util.jar.Manifest;
11+import java.util.jar.Attributes.Name;
12+import java.util.zip.CRC32;
13+import java.util.zip.GZIPOutputStream;
14+
15+public class JarProcessor {
16+
17+ private ByteArrayOutputStream out;
18+ private Manifest manifest;
19+ private String splashScreenName;
20+ private byte[] splashScreenImage;
21+
22+ public static void main(String[] args) {
23+ }
24+
25+ public JarProcessor(byte[] buf, boolean usePack200) throws IOException {
26+ JarInputStream jarIn = getJarInputStream(buf);
27+ manifest = jarIn.getManifest();
28+ if(manifest == null) {
29+ manifest = getManifest(jarIn);
30+ if(manifest != null) {
31+ jarIn.close();
32+ jarIn = getJarInputStream(buf);
33+ }
34+ }
35+ if(manifest == null) {
36+ throw new IOException("manifest not found");
37+ }
38+ splashScreenName = manifest.getMainAttributes().getValue("SplashScreen-Image");
39+
40+ this.out = new ByteArrayOutputStream();
41+ JarOutputStream jarOut;
42+ int method;
43+ if(usePack200) {
44+ method = JarEntry.STORED;
45+ GZIPOutputStream gzOut = new GZIPOutputStream(this.out);
46+ PackOutputStream packOut = new PackOutputStream(gzOut);
47+ jarOut = new JarOutputStream(packOut, manifest);
48+ } else {
49+ method = JarEntry.DEFLATED;
50+ jarOut = new JarOutputStream(this.out, manifest);
51+ }
52+ jarOut.setMethod(method);
53+
54+ JarEntry entryIn;
55+ while((entryIn = jarIn.getNextJarEntry()) != null) {
56+ if(!isManifest(entryIn)) {
57+ byte[] data = getBytes(jarIn);
58+ if(splashScreenName != null && entryIn.getName().equals(splashScreenName)) {
59+ splashScreenImage = data;
60+ } else {
61+ JarEntry entryOut = new JarEntry(entryIn.getName());
62+ entryOut.setMethod(method);
63+ if(method == JarEntry.STORED) {
64+ entryOut.setSize(data.length);
65+ entryOut.setCrc(getCrc(data));
66+ }
67+ jarOut.putNextEntry(entryOut);
68+ jarOut.write(data);
69+ jarOut.flush();
70+ jarOut.closeEntry();
71+ }
72+ }
73+ jarIn.closeEntry();
74+ }
75+ jarIn.close();
76+ jarOut.flush();
77+ jarOut.finish();
78+ jarOut.close();
79+ }
80+
81+ public String getMainClass() {
82+ return manifest.getMainAttributes().getValue(Name.MAIN_CLASS);
83+ }
84+
85+ public String getClassPath() {
86+ return manifest.getMainAttributes().getValue(Name.CLASS_PATH);
87+ }
88+
89+ public String getSplashScreenName() {
90+ return splashScreenName;
91+ }
92+
93+ public byte[] getSplashScreenImage() {
94+ return splashScreenImage;
95+ }
96+
97+ public byte[] getBytes() {
98+ return this.out.toByteArray();
99+ }
100+
101+ private static JarInputStream getJarInputStream(byte[] buf) throws IOException {
102+ ByteArrayInputStream bIn = new ByteArrayInputStream(buf);
103+ return new JarInputStream(bIn);
104+ }
105+
106+ private static Manifest getManifest(JarInputStream in) throws IOException {
107+ JarEntry e;
108+ while((e = in.getNextJarEntry()) != null) {
109+ if(e.getName().equalsIgnoreCase("META-INF/MANIFEST.MF")) {
110+ return new Manifest(new ByteArrayInputStream(getBytes(in)));
111+ }
112+ }
113+ return null;
114+ }
115+
116+ private static boolean isManifest(JarEntry entry) {
117+ return entry.getName().equalsIgnoreCase("META-INF/")
118+ || entry.getName().equalsIgnoreCase("META-INF/MANIFEST.MF");
119+ }
120+
121+ private static byte[] getBytes(InputStream in) throws IOException {
122+ ByteArrayOutputStream out = new ByteArrayOutputStream();
123+ byte[] buf = new byte[65536];
124+ int size;
125+ while((size = in.read(buf)) != -1) {
126+ out.write(buf, 0, size);
127+ }
128+ return out.toByteArray();
129+ }
130+
131+ private static long getCrc(byte[] data) {
132+ CRC32 crc = new CRC32();
133+ crc.update(data);
134+ return crc.getValue();
135+ }
136+}
--- exewrap/trunk/exewrap/src/java/exewrap/tool/JarOptimizer.java (revision 0)
+++ exewrap/trunk/exewrap/src/java/exewrap/tool/JarOptimizer.java (revision 20)
@@ -0,0 +1,141 @@
1+import java.io.ByteArrayInputStream;
2+import java.io.ByteArrayOutputStream;
3+import java.io.FileInputStream;
4+import java.util.Arrays;
5+import java.util.jar.JarEntry;
6+import java.util.jar.JarInputStream;
7+import java.util.jar.JarOutputStream;
8+import java.util.jar.Manifest;
9+import java.util.jar.Pack200;
10+import java.util.jar.Pack200.Packer;
11+import java.util.zip.CRC32;
12+import java.util.zip.GZIPOutputStream;
13+
14+public class JarOptimizer extends ClassLoader {
15+
16+ private String relative_classpath = null;
17+ private ByteArrayOutputStream resource_gz = new ByteArrayOutputStream();
18+ private ByteArrayOutputStream classes_pack_gz = new ByteArrayOutputStream();
19+ private String splash_path = null;
20+ private byte[] splash_image = null;
21+
22+ public JarOptimizer(String filename) throws Exception {
23+ int resourceCount = 0;
24+ int classCount = 0;
25+ ByteArrayOutputStream resources = new ByteArrayOutputStream();
26+ ByteArrayOutputStream classes = new ByteArrayOutputStream();
27+
28+ JarInputStream in = new JarInputStream(new FileInputStream(filename));
29+ Manifest manifest = in.getManifest();
30+ relative_classpath = manifest.getMainAttributes().getValue("Class-Path");
31+ splash_path = manifest.getMainAttributes().getValue("SplashScreen-Image");
32+ JarOutputStream classJar = new JarOutputStream(classes, manifest);
33+ JarOutputStream resourceJar = new JarOutputStream(resources);
34+
35+ JarEntry inEntry;
36+ byte[] buf = new byte[65536];
37+ int size;
38+ while((inEntry = in.getNextJarEntry()) != null) {
39+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
40+ while(in.available() > 0) {
41+ size = in.read(buf);
42+ if(size > 0) {
43+ baos.write(buf, 0, size);
44+ }
45+ }
46+ byte[] data = baos.toByteArray();
47+ if(inEntry.getName().equals(this.splash_path)) {
48+ this.splash_image = data;
49+ } else if(inEntry.getName().toLowerCase().endsWith(".class")) {
50+ CRC32 crc = new CRC32();
51+ crc.update(data);
52+
53+ JarEntry outEntry = new JarEntry(inEntry.getName());
54+ outEntry.setMethod(JarEntry.STORED);
55+ outEntry.setSize(data.length);
56+ outEntry.setCrc(crc.getValue());
57+
58+ classJar.putNextEntry(outEntry);
59+ classJar.write(data);
60+ classJar.closeEntry();
61+ classCount++;
62+ } else {
63+ /*
64+ String resourceEntryName;
65+ if(inEntry.getName().length() > 1 && inEntry.getName().charAt(0) == '/' && inEntry.getName().charAt(1) != '/') {
66+ resourceEntryName = inEntry.getName().substring(1);
67+ } else {
68+ resourceEntryName = inEntry.getName();
69+ }
70+ */
71+ CRC32 crc = new CRC32();
72+ crc.update(data);
73+
74+ //JarEntry outEntry = new JarEntry(resourceEntryName);
75+ JarEntry outEntry = new JarEntry(inEntry.getName());
76+ outEntry.setMethod(JarEntry.STORED);
77+ outEntry.setSize(data.length);
78+ outEntry.setCrc(crc.getValue());
79+
80+ resourceJar.putNextEntry(outEntry);
81+ resourceJar.write(data);
82+ resourceJar.closeEntry();
83+ resourceCount++;
84+ }
85+ in.closeEntry();
86+ }
87+ in.close();
88+ if(resourceCount > 0) {
89+ resourceJar.close();
90+ GZIPOutputStream gzout = new GZIPOutputStream(resource_gz);
91+ gzout.write(resources.toByteArray());
92+ gzout.flush();
93+ gzout.finish();
94+ gzout.close();
95+ }
96+ if(classCount > 0) {
97+ classJar.close();
98+ Packer packer = Pack200.newPacker();
99+ GZIPOutputStream gzout = new GZIPOutputStream(classes_pack_gz);
100+ in = new JarInputStream(new ByteArrayInputStream(classes.toByteArray()));
101+ packer.pack(in, gzout);
102+ gzout.flush();
103+ gzout.finish();
104+ gzout.close();
105+ in.close();
106+ }
107+ }
108+
109+ public byte[] getRelativeClassPath() {
110+ if(this.relative_classpath != null) {
111+ byte[] buf = this.relative_classpath.replaceAll("/", "\\\\").getBytes();
112+ return Arrays.copyOf(buf, buf.length + 2);
113+ }
114+ return null;
115+ }
116+
117+ public byte[] getClassesPackGz() {
118+ if(this.classes_pack_gz.size() > 0) {
119+ return this.classes_pack_gz.toByteArray();
120+ }
121+ return null;
122+ }
123+
124+ public byte[] getResourcesGz() {
125+ if(this.resource_gz.size() > 0) {
126+ return this.resource_gz.toByteArray();
127+ }
128+ return null;
129+ }
130+
131+ public byte[] getSplashPath() {
132+ if(this.splash_path != null) {
133+ return this.splash_path.getBytes();
134+ }
135+ return null;
136+ }
137+
138+ public byte[] getSplashImage() {
139+ return this.splash_image;
140+ }
141+}
--- exewrap/trunk/exewrap/src/java/exewrap/util/EventLogStream.java (revision 0)
+++ exewrap/trunk/exewrap/src/java/exewrap/util/EventLogStream.java (revision 20)
@@ -0,0 +1,67 @@
1+package exewrap.util;
2+
3+import java.io.ByteArrayOutputStream;
4+import java.io.IOException;
5+import java.io.PrintStream;
6+import java.io.PrintWriter;
7+import java.io.StringWriter;
8+
9+import exewrap.core.ExewrapClassLoader;
10+
11+public class EventLogStream extends PrintStream {
12+ public static final int INFORMATION = 0;
13+ public static final int WARNING = 1;
14+ public static final int ERROR = 2;
15+
16+ static {
17+ System.setOut(new EventLogStream(INFORMATION, new ByteArrayOutputStream()));
18+ System.setErr(new EventLogStream(WARNING, new ByteArrayOutputStream()));
19+ }
20+
21+ private int type;
22+ private ByteArrayOutputStream buffer;
23+
24+ public EventLogStream(int type, ByteArrayOutputStream buffer) {
25+ super(buffer);
26+ this.type = type;
27+ this.buffer = buffer;
28+ }
29+
30+ public void close() {
31+ flush();
32+ }
33+
34+ public void flush() {
35+ ExewrapClassLoader.WriteEventLog(type, new String(buffer.toByteArray()));
36+ buffer.reset();
37+ }
38+
39+ public void write(byte[] b, int off, int len) {
40+ buffer.write(b, off, len);
41+ }
42+
43+ public void write(byte[] b) throws IOException {
44+ buffer.write(b);
45+ }
46+
47+ public void write(int b) {
48+ buffer.write(b);
49+ }
50+
51+ public void print(String s) {
52+ if("".equals(s)) {
53+ buffer.reset();
54+ } else {
55+ super.print(s);
56+ }
57+ }
58+
59+ public static String getStackTrace(Throwable t) {
60+ StringWriter s = new StringWriter();
61+ PrintWriter w = new PrintWriter(s);
62+ t.printStackTrace(w);
63+ w.flush();
64+ s.flush();
65+ return s.toString();
66+ }
67+}
--- exewrap/trunk/exewrap/src/java/exewrap/util/EventLogHandler.java (revision 0)
+++ exewrap/trunk/exewrap/src/java/exewrap/util/EventLogHandler.java (revision 20)
@@ -0,0 +1,38 @@
1+package exewrap.util;
2+
3+import java.util.logging.Handler;
4+import java.util.logging.Level;
5+import java.util.logging.LogRecord;
6+import java.util.logging.Logger;
7+
8+import exewrap.core.ExewrapClassLoader;
9+
10+public class EventLogHandler extends Handler {
11+ public static final int INFORMATION = 0;
12+ public static final int WARNING = 1;
13+ public static final int ERROR = 2;
14+ private static final Logger eventlog = Logger.getLogger("eventlog");
15+
16+ static {
17+ EventLogHandler.eventlog.setUseParentHandlers(false);
18+ EventLogHandler.eventlog.addHandler(new EventLogHandler());
19+ }
20+
21+ public void publish(LogRecord record) {
22+ int level = record.getLevel().intValue();
23+
24+ if(level >= Level.SEVERE.intValue()) {
25+ ExewrapClassLoader.WriteEventLog(ERROR, record.getMessage() + "");
26+ } else if(level >= Level.WARNING.intValue()) {
27+ ExewrapClassLoader.WriteEventLog(WARNING, record.getMessage() + "");
28+ } else if(level >= Level.INFO.intValue()) {
29+ ExewrapClassLoader.WriteEventLog(INFORMATION, record.getMessage() + "");
30+ }
31+ }
32+
33+ public void flush() {
34+ }
35+
36+ public void close() throws SecurityException {
37+ }
38+}
--- exewrap/trunk/exewrap/src/java/exewrap/util/UncaughtExceptionHandler.java (revision 0)
+++ exewrap/trunk/exewrap/src/java/exewrap/util/UncaughtExceptionHandler.java (revision 20)
@@ -0,0 +1,26 @@
1+package exewrap.util;
2+
3+import java.io.PrintWriter;
4+import java.io.StringWriter;
5+
6+import exewrap.core.ExewrapClassLoader;
7+
8+public class UncaughtExceptionHandler implements java.lang.Thread.UncaughtExceptionHandler {
9+
10+ static {
11+ Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler());
12+ }
13+
14+ public void uncaughtException(Thread t, Throwable e) {
15+ ExewrapClassLoader.UncaughtException(t.getName(), e.toString(), getStackTrace(e));
16+ }
17+
18+ private static String getStackTrace(Throwable t) {
19+ StringWriter s = new StringWriter();
20+ PrintWriter w = new PrintWriter(s);
21+ t.printStackTrace(w);
22+ w.flush();
23+ s.flush();
24+ return s.toString();
25+ }
26+}
--- exewrap/trunk/exewrap/src/java/exewrap/util/FileLogStream.java (revision 0)
+++ exewrap/trunk/exewrap/src/java/exewrap/util/FileLogStream.java (revision 20)
@@ -0,0 +1,65 @@
1+package exewrap.util;
2+
3+import java.io.File;
4+import java.io.FileNotFoundException;
5+import java.io.FileOutputStream;
6+import java.io.IOException;
7+import java.io.OutputStream;
8+import java.io.PrintStream;
9+
10+public class FileLogStream extends OutputStream {
11+ static {
12+ String path = System.getProperty("java.application.path");
13+ String name = System.getProperty("java.application.name");
14+ name = name.substring(0, name.lastIndexOf('.')) + ".log";
15+ FileLogStream stream = new FileLogStream(new File(path, name));
16+ System.setOut(new PrintStream(stream));
17+ System.setErr(new PrintStream(stream));
18+ }
19+
20+ private File file;
21+ private FileOutputStream out;
22+
23+ public FileLogStream(File file) {
24+ this.file = file;
25+ }
26+
27+ private void open() {
28+ try {
29+ this.out = new FileOutputStream(this.file);
30+ } catch(FileNotFoundException e) {}
31+ }
32+
33+ public void close() throws IOException {
34+ if(this.out != null) {
35+ this.out.close();
36+ }
37+ }
38+
39+ public void flush() throws IOException {
40+ }
41+
42+ public void write(byte[] b, int off, int len) throws IOException {
43+ if(this.out == null) {
44+ open();
45+ }
46+ this.out.write(b, off, len);
47+ this.out.flush();
48+ }
49+
50+ public void write(byte[] b) throws IOException {
51+ if(out == null) {
52+ open();
53+ }
54+ this.out.write(b);
55+ this.out.flush();
56+ }
57+
58+ public void write(int b) throws IOException {
59+ if(out == null) {
60+ open();
61+ }
62+ this.out.write(b);
63+ this.out.flush();
64+ }
65+}
--- exewrap/trunk/exewrap/src/image_service.c (revision 19)
+++ exewrap/trunk/exewrap/src/image_service.c (revision 20)
@@ -7,986 +7,847 @@
77 #include <jni.h>
88
99 #include "include/jvm.h"
10+#include "include/loader.h"
11+#include "include/message.h"
1012 #include "include/eventlog.h"
11-#include "include/service.h"
12-#include "include/message.h"
1313
14-BOOL WINAPI HandlerRoutine(DWORD dwCtrlType);
15-void InitResource(LPCTSTR name);
16-DWORD GetResourceSize(LPCTSTR name);
17-jbyte* GetResourceBuffer(LPCTSTR name);
18-void OutputMessage(const char* text);
14+#define RUN_AS_ADMINISTRATOR_ARG "__ruN_aA_administratoR__"
15+#define RUN_AS_ADMINISTRATOR 1
16+#define SERVICE_INSTALL 2
17+#define SERVICE_START_IMMEDIATELY 4
18+#define SERVICE_REMOVE 8
19+#define SERVICE_STOP_BEFORE_REMOVE 16
20+#define SERVICE_START_BY_SCM 32
21+#define SHOW_HELP_MESSAGE 64
1922
20-void JNICALL JNI_WriteEventLog(JNIEnv *env, jobject clazz, jint logType, jstring message);
21-void JNICALL JNI_UncaughtException(JNIEnv *env, jobject clazz, jstring message, jstring trace);
22-static DWORD WINAPI uac_thread(void* arglist);
23-static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam);
2423
25-TCHAR cache[] = "12345678901234567890123456789012";
26-jbyte* buffer = NULL;
27-DWORD size = 0;
24+void OutputMessage(const char* text);
25+UINT UncaughtException(const char* thread, const char* message, const char* trace);
2826
29-const char RUN_AS_ADMINISTRATOR[] = "__RUN_AS_ADMINISTRATOR__";
27+static int install_service(char* service_name, int argc, char* argv[], int opt_end);
28+static int set_service_description(char* service_name, char* description);
29+static int remove_service(char* service_name);
30+static int start_service(char* service_name);
31+static int stop_service(char* service_name);
32+static void start_service_main();
33+static void stop_service_main();
34+static BOOL WINAPI console_control_handler(DWORD dwCtrlType);
35+static void service_control_handler(DWORD request);
36+static int service_main(int argc, char* argv[]);
37+static int parse_args(int* argc_ptr, char* argv[], int* opt_end);
38+static char** parse_opt(int argc, char* argv[]);
39+static void show_help_message();
40+static void set_current_dir();
41+static char* get_service_name(char* buf);
42+static char* get_pipe_name(char* buf);
43+static int run_as_administrator(HANDLE pipe, int argc, char* argv[], char* append);
3044
31-static char service_name[1024];
32-static jclass mainClass;
33-static jmethodID stopMethod;
45+static SERVICE_STATUS service_status = { 0 };
46+static SERVICE_STATUS_HANDLE hStatus;
47+static int flags;
48+static int ARG_COUNT;
49+static char** ARG_VALUE;
50+static jclass MainClass;
51+static jmethodID MainClass_stop;
3452
35-int isService = FALSE;
36-int isRunning = FALSE;
3753
38-int main(int argc, char* argv[])
54+static int service_main(int argc, char* argv[])
3955 {
40- int err = 0;
41- int i;
42- char* params = NULL;
43- BOOL is_install = FALSE;
44- BOOL is_remove = FALSE;
45- BOOL is_runas = lstrcmpi(argv[argc - 1], RUN_AS_ADMINISTRATOR) == 0;
46- char pipe_name[MAX_PATH];
47- HANDLE pipe = NULL;
56+ int err;
57+ char* service_name = NULL;
58+ BOOL is_service;
59+ char* relative_classpath;
60+ char* relative_extdirs;
61+ BOOL use_server_vm;
62+ char* ext_flags;
63+ char* vm_args_opt;
64+ char utilities[128];
65+ RESOURCE res;
66+ LOAD_RESULT result;
67+ jmethodID MainClass_start;
68+ jobjectArray MainClass_start_args;
69+ int i;
4870
49- strcpy(pipe_name, "\\\\.\\pipe\\");
50- if (strrchr(argv[0], '\\') != NULL)
71+ service_name = get_service_name(NULL);
72+ is_service = (flags & SERVICE_START_BY_SCM);
73+
74+ result.msg = malloc(2048);
75+
76+ relative_classpath = (char*)GetResource("CLASS_PATH", NULL);
77+ relative_extdirs = (char*)GetResource("EXTDIRS", NULL);
78+ ext_flags = (char*)GetResource("EXTFLAGS", NULL);
79+ use_server_vm = (ext_flags != NULL && strstr(ext_flags, "SERVER") != NULL);
80+ InitializePath(relative_classpath, relative_extdirs, use_server_vm);
81+
82+ vm_args_opt = (char*)GetResource("VMARGS", NULL);
83+ CreateJavaVM(vm_args_opt, use_server_vm, &err);
84+ if (err != JNI_OK)
5185 {
52- strcat(pipe_name, strrchr(argv[0], '\\') + 1);
86+ OutputMessage(GetWinErrorMessage(err, &result.msg_id, result.msg));
87+ goto EXIT;
5388 }
54- else
89+
90+ if (GetResource("TARGET_VERSION", &res) != NULL)
5591 {
56- strcat(pipe_name, argv[0]);
92+ DWORD version = GetJavaRuntimeVersion();
93+ DWORD targetVersion = *(DWORD*)res.buf;
94+ if (targetVersion > version)
95+ {
96+ char* targetVersionString = (char*)res.buf + 4;
97+ result.msg_id = MSG_ID_ERR_TARGET_VERSION;
98+ sprintf(result.msg, _(MSG_ID_ERR_TARGET_VERSION), targetVersionString + 4);
99+ OutputMessage(result.msg);
100+ goto EXIT;
101+ }
57102 }
58- strcat(pipe_name, ".pipe");
59103
60- if (is_runas)
104+ utilities[0] = '\0';
105+ if (ext_flags == NULL || strstr(ext_flags, "IGNORE_UNCAUGHT_EXCEPTION") == NULL)
61106 {
62- argc--;
107+ strcat(utilities, UTIL_UNCAUGHT_EXCEPTION_HANDLER);
63108 }
109+ if (is_service)
110+ {
111+ if (ext_flags == NULL || strstr(ext_flags, "NOLOG") == NULL)
112+ {
113+ strcat(utilities, UTIL_EVENT_LOG_STREAM);
114+ }
115+ strcat(utilities, UTIL_EVENT_LOG_HANDLER);
116+ }
64117
65- params = (char*)HeapAlloc(GetProcessHeap(), 0, 2048);
66- params[0] = '\0';
118+ if (LoadMainClass(argc, argv, utilities, &result) == FALSE)
119+ {
120+ OutputMessage(result.msg);
121+ goto EXIT;
122+ }
123+ MainClass = result.MainClass;
67124
68- for (i = 1; i < argc; i++)
125+ MainClass_start = (*env)->GetStaticMethodID(env, result.MainClass, "start", "([Ljava/lang/String;)V");
126+ if (MainClass_start == NULL)
69127 {
70- if (lstrcmpi(argv[i], "-install") == 0)
128+ result.msg_id = MSG_ID_ERR_FIND_METHOD_SERVICE_START;
129+ strcpy(result.msg, _(MSG_ID_ERR_FIND_METHOD_SERVICE_START));
130+ OutputMessage(result.msg);
131+ goto EXIT;
132+ }
133+ if (is_service && argc > 2)
134+ {
135+ MainClass_start_args = (*env)->NewObjectArray(env, argc - 2, (*env)->FindClass(env, "java/lang/String"), NULL);
136+ for (i = 2; i < argc; i++)
71137 {
72- is_install = TRUE;
138+ (*env)->SetObjectArrayElement(env, MainClass_start_args, (i - 2), GetJString(env, argv[i]));
73139 }
74- if (lstrcmpi(argv[i], "-remove") == 0)
140+ }
141+ else if (!is_service && argc > 1)
142+ {
143+ MainClass_start_args = (*env)->NewObjectArray(env, argc - 1, (*env)->FindClass(env, "java/lang/String"), NULL);
144+ for (i = 1; i < argc; i++)
75145 {
76- is_remove = TRUE;
146+ (*env)->SetObjectArrayElement(env, MainClass_start_args, (i - 1), GetJString(env, argv[i]));
77147 }
78-
79- strcat(params, "\"");
80- strcat(params, argv[i]);
81- strcat(params, "\"");
82- strcat(params, " ");
83148 }
149+ else
150+ {
151+ MainClass_start_args = (*env)->NewObjectArray(env, 0, (*env)->FindClass(env, "java/lang/String"), NULL);
152+ }
153+ MainClass_stop = (*env)->GetStaticMethodID(env, result.MainClass, "stop", "()V");
154+ if (MainClass_stop == NULL)
155+ {
156+ result.msg_id = MSG_ID_ERR_FIND_METHOD_SERVICE_STOP;
157+ strcpy(result.msg, _(MSG_ID_ERR_FIND_METHOD_SERVICE_STOP));
158+ OutputMessage(result.msg);
159+ goto EXIT;
160+ }
84161
85- strcat(params, RUN_AS_ADMINISTRATOR);
86-
87- if (!is_runas && (is_install || is_remove))
162+ sprintf(result.msg, _(MSG_ID_SUCCESS_SERVICE_START), service_name);
163+ if (is_service)
88164 {
89- SHELLEXECUTEINFO si;
90- BOOL ret;
91- DWORD exit_code = 0;
165+ WriteEventLog(EVENTLOG_INFORMATION_TYPE, result.msg);
166+ }
167+ else
168+ {
169+ OutputMessage(result.msg);
170+ }
92171
93- pipe = CreateNamedPipe(pipe_name, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_WAIT, 2, 1024, 1024, 1000, NULL);
94- if (pipe == INVALID_HANDLE_VALUE)
95- {
96- err = ShowErrorMessage();
97- return err;
98- }
172+ // JavaVM が CTRL_SHUTDOWN_EVENT を受け取って終了してしまわないように、ハンドラを登録して先取りします。
173+ SetConsoleCtrlHandler((PHANDLER_ROUTINE)console_control_handler, TRUE);
174+ // シャットダウン時にダイアログが表示されないようにします。
175+ SetProcessShutdownParameters(0x4FF, SHUTDOWN_NORETRY);
99176
100- ZeroMemory(&si, sizeof(SHELLEXECUTEINFO));
101- si.cbSize = sizeof(SHELLEXECUTEINFO);
102- si.fMask = SEE_MASK_NOCLOSEPROCESS;
103- si.hwnd = GetActiveWindow();
104- si.lpVerb = "runas";
105- si.lpFile = argv[0];
106- si.lpParameters = params;
107- si.lpDirectory = NULL;
108- si.nShow = SW_HIDE;
109- si.hInstApp = 0;
110- si.hProcess = 0;
177+ (*env)->CallStaticVoidMethod(env, result.MainClass, MainClass_start, MainClass_start_args);
111178
112- ret = ShellExecuteEx(&si);
113-
114- if (GetLastError() == ERROR_CANCELLED)
179+ if ((*env)->ExceptionCheck(env) == JNI_TRUE)
180+ {
181+ jthrowable throwable = (*env)->ExceptionOccurred(env);
182+ if (throwable != NULL)
115183 {
116- err = ShowErrorMessage();
117- }
118- else if (ret == TRUE)
119- {
120- char* buf = (char*)HeapAlloc(GetProcessHeap(), 0, 1024);
121- DWORD read_size;
122- DWORD write_size;
123-
124- if (!ConnectNamedPipe(pipe, NULL))
184+ ToString(env, throwable, result.msg);
185+ if (is_service)
125186 {
126- err = ShowErrorMessage();
127- CloseHandle(pipe);
128- return err;
187+ WriteEventLog(EVENTLOG_ERROR_TYPE, result.msg);
129188 }
130-
131- for (;;)
189+ else
132190 {
133- if (!ReadFile(pipe, buf, 1024, &read_size, NULL))
134- {
135- break;
136- }
137- WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, read_size, &write_size, NULL);
191+ OutputMessage(result.msg);
138192 }
139- FlushFileBuffers(pipe);
140- DisconnectNamedPipe(pipe);
141- CloseHandle(pipe);
142- pipe = NULL;
143-
144- WaitForSingleObject(si.hProcess, INFINITE);
145- ret = GetExitCodeProcess(si.hProcess, &err);
146- if (ret == FALSE)
147- {
148- err = GetLastError();
149- }
150- CloseHandle(si.hProcess);
193+ (*env)->DeleteLocalRef(env, throwable);
151194 }
195+ (*env)->ExceptionClear(env);
196+ }
197+ else
198+ {
199+ sprintf(result.msg, _(MSG_ID_SUCCESS_SERVICE_STOP), service_name);
200+ if (is_service)
201+ {
202+ WriteEventLog(EVENTLOG_INFORMATION_TYPE, result.msg);
203+ }
152204 else
153205 {
154- err = GetLastError();
206+ OutputMessage(result.msg);
155207 }
156- return err;
157208 }
158209
159- if (is_runas)
210+EXIT:
211+ if (result.msg != NULL)
160212 {
161- pipe = CreateFile(pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
162- if (pipe == INVALID_HANDLE_VALUE)
163- {
164- err = ShowErrorMessage();
165- return err;
166- }
167- SetStdHandle(STD_OUTPUT_HANDLE, pipe);
213+ free(result.msg);
168214 }
169-
170- if((argc >= 2) && (lstrcmpi(argv[1], "-service") == 0))
215+ if (env != NULL)
171216 {
172- isService = TRUE;
217+ DetachJavaVM();
173218 }
174- err = service_main(argc, argv);
175-
176- if (pipe != NULL)
219+ if (jvm != NULL)
177220 {
178- CloseHandle(pipe);
221+ //デーモンではないスレッド(たとえばSwing)が残っていると待機状態になってしまうため、
222+ //サービスでは、DestroyJavaVM() を実行しないようにしています。
223+ if (!is_service)
224+ {
225+ DestroyJavaVM();
226+ }
179227 }
180228
181- return err;
229+ return result.msg_id;
182230 }
183231
184-int service_install(int argc, char* argv[])
232+
233+void OutputMessage(const char* text)
185234 {
186- int err = 0;
235+ DWORD written;
187236
188- if(GetResourceSize("SVCDESC") > 0)
237+ if (text == NULL)
189238 {
190- err = SetServiceDescription((LPTSTR)GetResourceBuffer("SVCDESC"));
191- if (err)
192- {
193- return err;
194- }
239+ return;
195240 }
196- return InstallEventLog();
197-}
198241
199-int service_remove()
200-{
201- return RemoveEventLog();
242+ WriteConsole(GetStdHandle(STD_ERROR_HANDLE), text, (DWORD)strlen(text), &written, NULL);
243+ WriteConsole(GetStdHandle(STD_ERROR_HANDLE), "\r\n", 2, &written, NULL);
202244 }
203245
204-int service_start(int argc, char* argv[])
246+
247+UINT UncaughtException(const char* thread, const char* message, const char* trace)
205248 {
206- int exit_code = 0;
207- int i;
208- BOOL useServerVM = TRUE;
209- int err;
210- LPTSTR ext_flags = NULL;
211- LPTSTR vm_args_opt = NULL;
212- LPTSTR relative_classpath = NULL;
213- LPTSTR relative_extdirs = "lib";
214- char* message = NULL;
215- DWORD version;
216- LPTSTR targetVersionString;
217- DWORD targetVersion;
218- jclass urlConnectionClass;
219- jclass urlStreamHandlerClass;
220- jclass eventLogStreamClass = NULL;
221- jmethodID startMethod;
222- jobjectArray args;
223-
224- message = (char*)HeapAlloc(GetProcessHeap(), 0, 8192);
225-
226- if(GetResourceSize("RELATIVE_CLASSPATH") > 0)
249+ if (thread != NULL)
227250 {
228- relative_classpath = (LPTSTR)GetResourceBuffer("RELATIVE_CLASSPATH");
251+ char* buf = malloc(32 + strlen(thread));
252+ sprintf(buf, "Exception in thread \"%s\"", thread);
253+ OutputMessage(buf);
254+ free(buf);
229255 }
230- if(GetResourceSize("EXTDIRS") > 0)
256+ if (trace != NULL)
231257 {
232- relative_extdirs = (LPTSTR)GetResourceBuffer("EXTDIRS");
258+ OutputMessage(trace);
233259 }
234- if(GetResourceSize("EXTFLAGS") > 0)
235- {
236- ext_flags = _strupr((LPTSTR)GetResourceBuffer("EXTFLAGS"));
237- }
238- if(ext_flags != NULL && strstr(ext_flags, "CLIENT") != NULL)
239- {
240- useServerVM = FALSE;
241- }
260+ return MSG_ID_ERR_UNCAUGHT_EXCEPTION;
261+}
242262
243- InitializePath(relative_classpath, relative_extdirs, useServerVM);
244263
245- if(GetResourceSize("VMARGS") > 0)
264+int main(int argc, char* argv[])
265+{
266+ char* service_name = NULL;
267+ int opt_end;
268+ char* pipe_name = NULL;
269+ HANDLE pipe = NULL;
270+ int exit_code = 0;
271+
272+ set_current_dir();
273+ service_name = get_service_name(NULL);
274+ flags = parse_args(&argc, argv, &opt_end);
275+
276+ if (flags & SHOW_HELP_MESSAGE)
246277 {
247- vm_args_opt = (LPTSTR)GetResourceBuffer("VMARGS");
248- }
249- CreateJavaVM(vm_args_opt, useServerVM, &err);
250- switch(err)
251- {
252- case JNI_OK:
253- break;
254- case JNI_ERR: /* unknown error */
255- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_UNKNOWN));
256- exit_code = MSG_ID_ERR_CREATE_JVM_UNKNOWN;
278+ show_help_message();
257279 goto EXIT;
258- case JNI_EDETACHED: /* thread detached from the VM */
259- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_EDETACHED));
260- exit_code = MSG_ID_ERR_CREATE_JVM_EDETACHED;
261- goto EXIT;
262- case JNI_EVERSION: /* JNI version error */
263- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_EVERSION));
264- exit_code = MSG_ID_ERR_CREATE_JVM_EVERSION;
265- goto EXIT;
266- case JNI_ENOMEM: /* not enough memory */
267- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_ENOMEM));
268- exit_code = MSG_ID_ERR_CREATE_JVM_ENOMEM;
269- goto EXIT;
270- case JNI_EEXIST: /* VM already created */
271- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_EEXIST));
272- exit_code = MSG_ID_ERR_CREATE_JVM_EEXIST;
273- goto EXIT;
274- case JNI_EINVAL: /* invalid arguments */
275- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_EINVAL));
276- exit_code = MSG_ID_ERR_CREATE_JVM_EINVAL;
277- goto EXIT;
278- case JVM_ELOADLIB:
279- sprintf(message, _(MSG_ID_ERR_CREATE_JVM_ELOADLIB), GetProcessArchitecture());
280- OutputMessage(message);
281- exit_code = MSG_ID_ERR_CREATE_JVM_ELOADLIB;
282- goto EXIT;
283- default:
284- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_UNKNOWN));
285- exit_code = MSG_ID_ERR_CREATE_JVM_UNKNOWN;
286- goto EXIT;
287280 }
288281
289- version = GetJavaRuntimeVersion();
290- targetVersionString = (LPTSTR)GetResourceBuffer("TARGET_VERSION");
291- targetVersion = *(DWORD*)targetVersionString;
282+ if (flags & SERVICE_START_BY_SCM)
283+ {
284+ SERVICE_TABLE_ENTRY ServiceTable[2];
292285
293- if(targetVersion > version)
294- {
295- sprintf(message, _(MSG_ID_ERR_TARGET_VERSION), targetVersionString + 4);
296- lstrcat(message, "\r\n");
297- OutputMessage(message);
298- exit_code = MSG_ID_ERR_TARGET_VERSION;
286+ ARG_COUNT = argc;
287+ ARG_VALUE = argv;
288+
289+ ServiceTable[0].lpServiceName = service_name;
290+ ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)start_service_main;
291+ ServiceTable[1].lpServiceName = NULL;
292+ ServiceTable[1].lpServiceProc = NULL;
293+ StartServiceCtrlDispatcher(ServiceTable);
299294 goto EXIT;
300295 }
301296
302- // URLConnection
303- urlConnectionClass = (*env)->DefineClass(env, "URLConnection", NULL, GetResourceBuffer("URL_CONNECTION"), GetResourceSize("URL_CONNECTION"));
304- if(urlConnectionClass == NULL)
297+ if (!(flags & RUN_AS_ADMINISTRATOR) && (flags & (SERVICE_INSTALL | SERVICE_REMOVE)))
305298 {
306- sprintf(message, _(MSG_ID_ERR_DEFINE_CLASS), "URLConnection");
307- lstrcat(message, "\r\n");
308- OutputMessage(message);
309- exit_code = MSG_ID_ERR_DEFINE_CLASS;
299+ pipe_name = get_pipe_name(NULL);
300+ pipe = CreateNamedPipe(pipe_name, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_WAIT, 2, 1024, 1024, 1000, NULL);
301+ if (pipe == INVALID_HANDLE_VALUE)
302+ {
303+ OutputMessage(GetWinErrorMessage(GetLastError(), &exit_code, NULL));
304+ goto EXIT;
305+ }
306+ exit_code = run_as_administrator(pipe, argc, argv, RUN_AS_ADMINISTRATOR_ARG);
310307 goto EXIT;
311308 }
312- // URLStreamHandler
313- urlStreamHandlerClass = (*env)->DefineClass(env, "URLStreamHandler", NULL, GetResourceBuffer("URL_STREAM_HANDLER"), GetResourceSize("URL_STREAM_HANDLER"));
314- if(urlStreamHandlerClass == NULL)
309+
310+ if (flags & RUN_AS_ADMINISTRATOR)
315311 {
316- sprintf(message, _(MSG_ID_ERR_DEFINE_CLASS), "URLStreamHandler");
317- lstrcat(message, "\r\n");
318- OutputMessage(message);
319- exit_code = MSG_ID_ERR_DEFINE_CLASS;
320- goto EXIT;
312+ pipe_name = get_pipe_name(NULL);
313+ pipe = CreateFile(pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
314+ if (pipe == INVALID_HANDLE_VALUE)
315+ {
316+ OutputMessage(GetWinErrorMessage(GetLastError(), &exit_code, NULL));
317+ goto EXIT;
318+ }
319+ SetStdHandle(STD_OUTPUT_HANDLE, pipe);
321320 }
322- //EventLogStream Windowsサービスとして起動している場合、出力をイベントログに切り替えます。
323- if(isService)
321+
322+ if (flags & SERVICE_INSTALL)
324323 {
325- jmethodID eventLogStreamInit;
326-
327- if((eventLogStreamClass = (*env)->DefineClass(env, "EventLogStream", NULL, GetResourceBuffer("EVENTLOG_STREAM"), GetResourceSize("EVENTLOG_STREAM"))) != NULL)
324+ exit_code = install_service(service_name, argc, argv, opt_end);
325+ if (exit_code == 0)
328326 {
329- if(ext_flags == NULL || strstr(ext_flags, "NOLOG") == NULL)
327+ if (flags & SERVICE_START_IMMEDIATELY)
330328 {
331- if((eventLogStreamInit = (*env)->GetStaticMethodID(env, eventLogStreamClass, "initialize", "()V")) != NULL)
332- {
333- JNINativeMethod nm;
334-
335- (*env)->CallStaticVoidMethod(env, eventLogStreamClass, eventLogStreamInit);
336- nm.name = (char*)"WriteEventLog";
337- nm.signature = (char*)"(ILjava/lang/String;)V";
338- nm.fnPtr = (void*)JNI_WriteEventLog;
339-
340- if(((*env)->RegisterNatives(env, eventLogStreamClass, &nm, 1)) != 0)
341- {
342- sprintf(message, _(MSG_ID_ERR_REGISTER_NATIVE), "WriteEventLog");
343- lstrcat(message, "\r\n");
344- OutputMessage(message);
345- exit_code = MSG_ID_ERR_REGISTER_NATIVE;
346- goto EXIT;
347- }
348- }
329+ exit_code = start_service(service_name);
349330 }
350331 }
332+ return exit_code;
351333 }
352- //EventLogHandler (version 1.4.0 or higher only) Windowsサービスとして起動している場合、java.util.Logger.getLogger("eventlog") でイベントログに出力できるようにします。
353- if(version >= 0x01040000)
334+ if (flags & SERVICE_REMOVE)
354335 {
355- jclass eventLogHandlerClass = NULL;
356-
357- if(isService)
336+ if (flags & SERVICE_STOP_BEFORE_REMOVE)
358337 {
359- jmethodID eventLogHandlerInit;
360-
361- if((eventLogHandlerClass = (*env)->DefineClass(env, "EventLogHandler", NULL, GetResourceBuffer("EVENTLOG_HANDLER"), GetResourceSize("EVENTLOG_HANDLER"))) != NULL)
338+ exit_code = stop_service(service_name);
339+ if (exit_code != 0)
362340 {
363- if((eventLogHandlerInit = (*env)->GetStaticMethodID(env, eventLogHandlerClass, "initialize", "()V")) != NULL)
364- {
365- JNINativeMethod nm;
366-
367- (*env)->CallStaticVoidMethod(env, eventLogHandlerClass, eventLogHandlerInit);
368- nm.name = (char*)"WriteEventLog";
369- nm.signature = (char*)"(ILjava/lang/String;)V";
370- nm.fnPtr = (char*)JNI_WriteEventLog;
371-
372- if(((*env)->RegisterNatives(env, eventLogHandlerClass, &nm, 1)) != 0)
373- {
374- sprintf(message, _(MSG_ID_ERR_REGISTER_NATIVE), "WriteEventLog");
375- lstrcat(message, "\r\n");
376- OutputMessage(message);
377- exit_code = MSG_ID_ERR_REGISTER_NATIVE;
378- goto EXIT;
379- }
380- }
341+ return exit_code;
381342 }
343+ Sleep(500);
382344 }
345+ exit_code = remove_service(service_name);
346+ return exit_code;
383347 }
384348
385- // UncaughtHandler (version 1.5.0 or higher only)
386- if(version >= 0x01050000)
349+ exit_code = service_main(argc, argv);
350+
351+EXIT:
352+ if (pipe != NULL && pipe != INVALID_HANDLE_VALUE)
387353 {
388- jclass uncaughtHandlerClass;
389- jmethodID uncaughtHandlerInit;
354+ CloseHandle(pipe);
355+ }
356+ if (pipe_name != NULL)
357+ {
358+ HeapFree(GetProcessHeap(), 0, pipe_name);
359+ }
360+ if (service_name != NULL)
361+ {
362+ HeapFree(GetProcessHeap(), 0, service_name);
363+ }
390364
391- if((uncaughtHandlerClass = (*env)->DefineClass(env, "UncaughtHandler", NULL, GetResourceBuffer("UNCAUGHT_HANDLER"), GetResourceSize("UNCAUGHT_HANDLER"))) != NULL)
392- {
393- if((uncaughtHandlerInit = (*env)->GetStaticMethodID(env, uncaughtHandlerClass, "initialize", "()V")) != NULL)
394- {
395- JNINativeMethod nm;
365+ return exit_code;
366+}
396367
397- (*env)->CallStaticVoidMethod(env, uncaughtHandlerClass, uncaughtHandlerInit);
398- nm.name = (char*)"UncaughtException";
399- nm.signature = (char*)"(Ljava/lang/String;Ljava/lang/String;)V";
400- nm.fnPtr = (void*)JNI_UncaughtException;
401368
402- if(((*env)->RegisterNatives(env, uncaughtHandlerClass, &nm, 1)) != 0)
403- {
404- sprintf(message, _(MSG_ID_ERR_REGISTER_NATIVE), "UncaughtException");
405- lstrcat(message, "\r\n");
406- OutputMessage(message);
407- exit_code = MSG_ID_ERR_REGISTER_NATIVE;
408- goto EXIT;
409- }
410- }
411- }
369+static int install_service(char* service_name, int argc, char* argv[], int opt_end)
370+{
371+ int PATH_SIZE = 1024;
372+ char* path = NULL;
373+ int i;
374+ char** opt = NULL;
375+ char* lpDisplayName = NULL;
376+ DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS;
377+ DWORD dwStartType = SERVICE_AUTO_START;
378+ char* lpDependencies = NULL;
379+ char* lpServiceStartName = NULL;
380+ char* lpPassword = NULL;
381+ SC_HANDLE hSCManager = NULL;
382+ SC_HANDLE hService = NULL;
383+ char* buf = NULL;
384+ DWORD size;
385+ int err = 0;
386+
387+ buf = (char*)malloc(2048);
388+ path = (char*)malloc(PATH_SIZE);
389+ path[0] = '"';
390+ GetModuleFileName(NULL, &path[1], PATH_SIZE - 1);
391+ strcat(path, "\" -service");
392+ for (i = opt_end + 2; i < argc; i++)
393+ {
394+ strcat(path, " \"");
395+ strcat(path, argv[i]);
396+ strcat(path, "\"");
412397 }
413- // Loader
414- if(GetResourceBuffer("PACK_LOADER") != NULL)
398+
399+ opt = parse_opt(opt_end + 1, argv);
400+ if (opt['n'])
415401 {
416- // PackLoader
417- jclass packLoaderClass;
418- jmethodID packLoaderInit;
419- jobject packLoader;
420- jbyteArray classesPackGz = NULL;
421- jbyteArray resourcesGz = NULL;
422- jbyteArray splashPath = NULL;
423- jbyteArray splashImage = NULL;
424- jmethodID packLoaderInitializeMethod;
425-
426- packLoaderClass = (*env)->DefineClass(env, "PackLoader", NULL, GetResourceBuffer("PACK_LOADER"), GetResourceSize("PACK_LOADER"));
427- if(packLoaderClass == NULL)
428- {
429- sprintf(message, _(MSG_ID_ERR_DEFINE_CLASS), "PackLoader");
430- lstrcat(message, "\r\n");
431- OutputMessage(message);
432- exit_code = MSG_ID_ERR_DEFINE_CLASS;
433- goto EXIT;
434- }
435- packLoaderInit = (*env)->GetMethodID(env, packLoaderClass, "<init>", "()V");
436- if(packLoaderInit == NULL)
437- {
438- sprintf(message, _(MSG_ID_ERR_GET_METHOD), "PackLoader#init()");
439- lstrcat(message, "\r\n");
440- OutputMessage(message);
441- exit_code = MSG_ID_ERR_GET_METHOD;
442- goto EXIT;
443- }
444- packLoader = (*env)->NewObject(env, packLoaderClass, packLoaderInit);
445- if(packLoader == NULL)
446- {
447- sprintf(message, _(MSG_ID_ERR_NEW_OBJECT), "PackLoader");
448- lstrcat(message, "\r\n");
449- OutputMessage(message);
450- exit_code = MSG_ID_ERR_NEW_OBJECT;
451- goto EXIT;
452- }
453- if(GetResourceBuffer("CLASSES_PACK_GZ") != NULL)
454- {
455- classesPackGz = (*env)->NewByteArray(env, GetResourceSize("CLASSES_PACK_GZ"));
456- (*env)->SetByteArrayRegion(env, classesPackGz, 0, GetResourceSize("CLASSES_PACK_GZ"), GetResourceBuffer("CLASSES_PACK_GZ"));
457- }
458- if(GetResourceBuffer("RESOURCES_GZ") != NULL)
459- {
460- resourcesGz = (*env)->NewByteArray(env, GetResourceSize("RESOURCES_GZ"));
461- (*env)->SetByteArrayRegion(env, resourcesGz, 0, GetResourceSize("RESOURCES_GZ"), GetResourceBuffer("RESOURCES_GZ"));
462- }
463- if(GetResourceBuffer("SPLASH_PATH") != NULL)
464- {
465- splashPath = (*env)->NewByteArray(env, GetResourceSize("SPLASH_PATH"));
466- (*env)->SetByteArrayRegion(env, splashPath, 0, GetResourceSize("SPLASH_PATH"), GetResourceBuffer("SPLASH_PATH"));
467- }
468- if(GetResourceBuffer("SPLATH_IMAGE") != NULL)
469- {
470- splashImage = (*env)->NewByteArray(env, GetResourceSize("SPLASH_IMAGE"));
471- (*env)->SetByteArrayRegion(env, splashImage, 0, GetResourceSize("SPLASH_IMAGE"), GetResourceBuffer("SPLASH_IMAGE"));
472- }
473- packLoaderInitializeMethod = (*env)->GetMethodID(env, packLoaderClass, "initialize", "([B[B[B[B)Ljava/lang/Class;");
474- if(packLoaderInitializeMethod == NULL)
475- {
476- sprintf(message, _(MSG_ID_ERR_GET_METHOD), "PackLoader#initialize(byte[], byte[], byte[], byte[])");
477- lstrcat(message, "\r\n");
478- OutputMessage(message);
479- exit_code = MSG_ID_ERR_GET_METHOD;
480- goto EXIT;
481- }
482- mainClass = (jclass)((*env)->CallObjectMethod(env, packLoader, packLoaderInitializeMethod, classesPackGz, resourcesGz, splashPath, splashImage));
402+ lpDisplayName = opt['n'];
483403 }
484- else if(GetResourceBuffer("CLASSIC_LOADER") != NULL)
404+ if (opt['i'] && opt['u'] == 0 && opt['p'] == 0)
485405 {
486- // ClassicLoader
487- jclass classicLoaderClass;
488- jmethodID classicLoaderInit;
489- jobject classicLoader;
490- jbyteArray jar;
491- jmethodID classicLoaderInitializeMethod;
492-
493- classicLoaderClass = (*env)->DefineClass(env, "ClassicLoader", NULL, GetResourceBuffer("CLASSIC_LOADER"), GetResourceSize("CLASSIC_LOADER"));
494- if(classicLoaderClass == NULL)
406+ dwServiceType += SERVICE_INTERACTIVE_PROCESS;
407+ }
408+ if (opt['m'])
409+ {
410+ dwStartType = SERVICE_DEMAND_START;
411+ }
412+ if (opt['d'])
413+ {
414+ lpDependencies = (char*)malloc(strlen(opt['d']) + 2);
415+ lstrcpy(lpDependencies, opt['d']);
416+ lstrcat(lpDependencies, ";");
417+ while (strrchr(lpDependencies, ';') != NULL)
495418 {
496- sprintf(message, _(MSG_ID_ERR_DEFINE_CLASS), "ClassicLoader");
497- lstrcat(message, "\r\n");
498- OutputMessage(message);
499- exit_code = MSG_ID_ERR_DEFINE_CLASS;
500- goto EXIT;
419+ *(strrchr(lpDependencies, ';')) = '\0';
501420 }
502- classicLoaderInit = (*env)->GetMethodID(env, classicLoaderClass, "<init>", "()V");
503- if(classicLoaderInit == NULL)
504- {
505- sprintf(message, _(MSG_ID_ERR_GET_METHOD), "ClassicLoader#init()");
506- lstrcat(message, "\r\n");
507- OutputMessage(message);
508- exit_code = MSG_ID_ERR_GET_METHOD;
509- goto EXIT;
510- }
511- classicLoader = (*env)->NewObject(env, classicLoaderClass, classicLoaderInit);
512- if(classicLoader == NULL)
513- {
514- sprintf(message, _(MSG_ID_ERR_NEW_OBJECT), "ClassicLoader");
515- lstrcat(message, "\r\n");
516- OutputMessage(message);
517- exit_code = MSG_ID_ERR_NEW_OBJECT;
518- goto EXIT;
519- }
520- jar = (*env)->NewByteArray(env, GetResourceSize("JAR"));
521- (*env)->SetByteArrayRegion(env, jar, 0, GetResourceSize("JAR"), GetResourceBuffer("JAR"));
522- classicLoaderInitializeMethod = (*env)->GetMethodID(env, classicLoaderClass, "initialize", "([B)Ljava/lang/Class;");
523- if(classicLoaderInitializeMethod == NULL)
524- {
525- sprintf(message, _(MSG_ID_ERR_GET_METHOD), "ClassicLoader#initialize(byte[])");
526- lstrcat(message, "\r\n");
527- OutputMessage(message);
528- exit_code = MSG_ID_ERR_GET_METHOD;
529- goto EXIT;
530- }
531- mainClass = (jclass)((*env)->CallObjectMethod(env, classicLoader, classicLoaderInitializeMethod, jar));
532421 }
533- else
422+ if (opt['u'])
534423 {
535- sprintf(message, _(MSG_ID_ERR_FIND_CLASSLOADER));
536- lstrcat(message, "\r\n");
537- OutputMessage(message);
538- exit_code = MSG_ID_ERR_FIND_CLASSLOADER;
424+ lpServiceStartName = opt['u'];
425+ }
426+ if (opt['p'])
427+ {
428+ lpPassword = opt['p'];
429+ }
430+
431+ hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
432+ if (hSCManager == NULL)
433+ {
434+ GetWinErrorMessage(GetLastError(), &err, buf);
435+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
539436 goto EXIT;
540437 }
541- // Main-Class
542- if(mainClass == NULL)
438+
439+ hService = CreateService(hSCManager, service_name, lpDisplayName, SERVICE_ALL_ACCESS, dwServiceType, dwStartType, SERVICE_ERROR_NORMAL, path, NULL, NULL, lpDependencies, lpServiceStartName, lpPassword);
440+ if (hService == NULL)
543441 {
544- (*env)->ExceptionDescribe(env);
545- exit_code = MSG_ID_ERR_LOAD_MAIN_CLASS;
442+ GetWinErrorMessage(GetLastError(), &err, buf);
443+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
546444 goto EXIT;
547445 }
548- startMethod = (*env)->GetStaticMethodID(env, mainClass, "start", "([Ljava/lang/String;)V");
549- if(startMethod == NULL)
446+ else
550447 {
551- lstrcpy(message, _(MSG_ID_ERR_FIND_METHOD_SERVICE_START));
552- if(isService)
553- {
554- WriteEventLog(EVENTLOG_ERROR_TYPE, message);
555- }
556- else
557- {
558- lstrcat(message, "\r\n");
559- OutputMessage(message);
560- }
561- exit_code = MSG_ID_ERR_FIND_METHOD_SERVICE_START;
448+ sprintf(buf, _(MSG_ID_SUCCESS_SERVICE_INSTALL), service_name);
449+ strcat(buf, "\n");
450+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
451+ }
452+ err = set_service_description(service_name, GetResource("SVCDESC", NULL));
453+ if (err != 0)
454+ {
562455 goto EXIT;
563456 }
564- stopMethod = (*env)->GetStaticMethodID(env, mainClass, "stop", "()V");
565- if(stopMethod == NULL)
457+ err = InstallEventLog();
458+ if (err != 0)
566459 {
567- lstrcpy(message, _(MSG_ID_ERR_FIND_METHOD_SERVICE_STOP));
568- if(isService)
569- {
570- WriteEventLog(EVENTLOG_ERROR_TYPE, message);
571- }
572- else
573- {
574- lstrcat(message, "\r\n");
575- OutputMessage(message);
576- }
577- exit_code = MSG_ID_ERR_FIND_METHOD_SERVICE_STOP;
578460 goto EXIT;
579461 }
580462
581- if(isService && argc > 2)
463+EXIT:
464+ if (buf != NULL)
582465 {
583- args = (*env)->NewObjectArray(env, argc - 2, (*env)->FindClass(env, "java/lang/String"), NULL);
584- for(i = 2; i < argc; i++)
585- {
586- (*env)->SetObjectArrayElement(env, args, (i - 2), GetJString(env, argv[i]));
587- }
466+ free(buf);
588467 }
589- else if(!isService && argc > 1)
468+ if (hService != NULL)
590469 {
591- args = (*env)->NewObjectArray(env, argc - 1, (*env)->FindClass(env, "java/lang/String"), NULL);
592- for(i = 1; i < argc; i++)
593- {
594- (*env)->SetObjectArrayElement(env, args, (i - 1), GetJString(env, argv[i]));
595- }
470+ CloseServiceHandle(hService);
596471 }
597- else
472+ if (hSCManager != NULL)
598473 {
599- args = (*env)->NewObjectArray(env, 0, (*env)->FindClass(env, "java/lang/String"), NULL);
474+ CloseServiceHandle(hSCManager);
600475 }
601-
602- lstrcpy(service_name, argv[0]);
603- sprintf(message, _(MSG_ID_SUCCESS_SERVICE_START), service_name);
604- if(isService)
476+ if (lpDependencies != NULL)
605477 {
606- WriteEventLog(EVENTLOG_INFORMATION_TYPE, message);
478+ free(lpDependencies);
607479 }
608- else
480+ if (path != NULL)
609481 {
610- printf("%s\r\n", message);
482+ free(path);
611483 }
612484
613- // JavaVM が CTRL_SHUTDOWN_EVENT を受け取って終了してしまわないように、ハンドラを登録して先取りします。
614- SetConsoleCtrlHandler((PHANDLER_ROUTINE)HandlerRoutine, TRUE);
615- // シャットダウン時にダイアログが表示されないようにします。
616- SetProcessShutdownParameters(0x4FF, SHUTDOWN_NORETRY);
485+ return err;
486+}
617487
618- (*env)->CallStaticVoidMethod(env, mainClass, startMethod, args);
619488
620- if((*env)->ExceptionCheck(env) == JNI_TRUE)
489+static int set_service_description(char* service_name, char* description)
490+{
491+ char* buf = NULL;
492+ DWORD size;
493+ char* key = NULL;
494+ HKEY hKey = NULL;
495+ int err = 0;
496+
497+ if (description == NULL)
621498 {
622- if(isService)
623- {
624- jthrowable throwable;
625- jmethodID getStackTraceMethod;
626- jstring s;
499+ goto EXIT;
500+ }
627501
628- throwable = (*env)->ExceptionOccurred(env);
629- (*env)->ExceptionClear(env);
630- getStackTraceMethod = (*env)->GetStaticMethodID(env, eventLogStreamClass, "getStackTrace", "(Ljava/lang/Throwable;)Ljava/lang/String;");
631- s = (jstring)(*env)->CallStaticObjectMethod(env, eventLogStreamClass, getStackTraceMethod, throwable);
632- sprintf(message, _(MSG_ID_ERR_SERVICE_ABORT), service_name);
633- lstrcat(message, "\r\n\r\n");
634- lstrcat(message, GetShiftJIS(env, s));
635- WriteEventLog(EVENTLOG_ERROR_TYPE, message);
636- exit_code = 0;
637- goto EXIT;
638- }
639- else
640- {
641- sprintf(message, _(MSG_ID_ERR_SERVICE_ABORT), service_name);
642- lstrcat(message, "\r\n\r\n");
643- OutputMessage(message);
644- (*env)->ExceptionDescribe(env);
645- (*env)->ExceptionClear(env);
646- }
502+ buf = (char*)malloc(2048);
503+ key = (char*)malloc(1024);
504+ strcpy(key, "SYSTEM\\CurrentControlSet\\Services\\");
505+ strcat(key, service_name);
506+
507+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS)
508+ {
509+ GetWinErrorMessage(GetLastError(), &err, buf);
510+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
511+ goto EXIT;
647512 }
648- else
513+ if (RegSetValueEx(hKey, "Description", 0, REG_SZ, (LPBYTE)description, (DWORD)strlen(description) + 1) != ERROR_SUCCESS)
649514 {
650- sprintf(message, _(MSG_ID_SUCCESS_SERVICE_STOP), service_name);
651- if(isService)
652- {
653- WriteEventLog(EVENTLOG_INFORMATION_TYPE, message);
654- }
655- else
656- {
657- printf("%s\r\n", message);
658- }
515+ GetWinErrorMessage(GetLastError(), &err, buf);
516+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
517+ goto EXIT;
659518 }
660519
661520 EXIT:
662- if(message != NULL)
521+ if (hKey != NULL)
663522 {
664- HeapFree(GetProcessHeap(), 0, message);
523+ RegCloseKey(hKey);
665524 }
666- if(env != NULL)
525+ if (key != NULL)
667526 {
668- DetachJavaVM();
527+ free(key);
669528 }
670- //デーモンではないスレッド(たとえばSwing)が残っていると待機状態になってしまうため、
671- //サービスでは、DestroyJavaVM() を実行しないようにしています。
672- //if(jvm != NULL) {
673- // DestroyJavaVM();
674- //}
529+ if (buf != NULL)
530+ {
531+ free(buf);
532+ }
675533
676- return exit_code;
534+ return err;
677535 }
678536
679-int service_stop()
537+
538+static int remove_service(char* service_name)
680539 {
681- JNIEnv* env = AttachJavaVM();
540+ char* buf = NULL;
541+ DWORD size;
542+ SC_HANDLE hSCManager = NULL;
543+ SC_HANDLE hService = NULL;
544+ SERVICE_STATUS status;
545+ BOOL ret;
546+ int err = 0;
682547
683- (*env)->CallStaticVoidMethod(env, mainClass, stopMethod);
684- DetachJavaVM();
548+ buf = (char*)malloc(2048);
685549
686- return 0;
687-}
550+ hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
551+ if (hSCManager == NULL)
552+ {
553+ GetWinErrorMessage(GetLastError(), &err, buf);
554+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
555+ goto EXIT;
556+ }
557+ hService = OpenService(hSCManager, service_name, SERVICE_ALL_ACCESS | DELETE);
558+ if (hService == NULL)
559+ {
560+ GetWinErrorMessage(GetLastError(), &err, buf);
561+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
562+ goto EXIT;
563+ }
688564
689-int service_error()
690-{
691- return 0;
692-}
565+ ret = QueryServiceStatus(hService, &status);
566+ if (ret == FALSE)
567+ {
568+ GetWinErrorMessage(GetLastError(), &err, buf);
569+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
570+ goto EXIT;
571+ }
572+ if (status.dwCurrentState != SERVICE_STOPPED)
573+ {
574+ err = MSG_ID_ERR_SERVICE_NOT_STOPPED;
575+ sprintf(buf, _(MSG_ID_ERR_SERVICE_NOT_STOPPED), service_name);
576+ strcat(buf, "\n");
577+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
578+ goto EXIT;
579+ }
693580
694-int main_start(int argc, char* argv[])
695-{
696- jclass mainClass = NULL;
697- jmethodID mainMethod = NULL;
698- int exit_code;
699- int i;
700- BOOL useServerVM = TRUE;
701- int err;
702- LPTSTR ext_flags = NULL;
703- LPTSTR vm_args_opt = NULL;
704- LPTSTR relative_classpath = NULL;
705- LPTSTR relative_extdirs = "lib";
706- DWORD version;
707- LPTSTR targetVersionString;
708- DWORD targetVersion;
709- char* message = NULL;
710- jclass urlConnectionClass;
711- jclass urlStreamHandlerClass;
712- jobjectArray args;
581+ if (!DeleteService(hService))
582+ {
583+ GetWinErrorMessage(GetLastError(), &err, buf);
584+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
585+ goto EXIT;
586+ }
713587
714- message = (char*)HeapAlloc(GetProcessHeap(), 0, 1024);
588+ sprintf(buf, _(MSG_ID_SUCCESS_SERVICE_REMOVE), service_name);
589+ strcat(buf, "\n");
590+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
715591
716- if(GetResourceSize("RELATIVE_CLASSPATH") > 0)
592+ err = RemoveEventLog();
593+ if (err != 0)
717594 {
718- relative_classpath = (LPTSTR)GetResourceBuffer("RELATIVE_CLASSPATH");
595+ goto EXIT;
719596 }
720- if(GetResourceSize("EXTDIRS") > 0)
597+
598+EXIT:
599+ if (hService != NULL)
721600 {
722- relative_extdirs = (LPTSTR)GetResourceBuffer("EXTDIRS");
601+ CloseServiceHandle(hService);
723602 }
724- if(GetResourceSize("EXTFLAGS") > 0)
603+ if (hSCManager != NULL)
725604 {
726- ext_flags = _strupr((LPTSTR)GetResourceBuffer("EXTFLAGS"));
605+ CloseServiceHandle(hSCManager);
727606 }
728- if(ext_flags != NULL && strstr(ext_flags, "CLIENT") != NULL)
607+ if (service_name != NULL)
729608 {
730- useServerVM = FALSE;
609+ HeapFree(GetProcessHeap(), 0, service_name);
731610 }
611+ if (buf != NULL)
612+ {
613+ free(buf);
614+ }
732615
733- InitializePath(relative_classpath, relative_extdirs, useServerVM);
616+ return err;
617+}
734618
735- if(GetResourceSize("VMARGS") > 0)
619+
620+int start_service(char* service_name)
621+{
622+ SC_HANDLE hSCManager = NULL;
623+ SC_HANDLE hService = NULL;
624+ BOOL ret;
625+ char* buf = NULL;
626+ DWORD size;
627+ int err = 0;
628+
629+ buf = (char*)malloc(2048);
630+
631+ hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
632+ if (hSCManager == NULL)
736633 {
737- vm_args_opt = (LPTSTR)GetResourceBuffer("VMARGS");
634+ GetWinErrorMessage(GetLastError(), &err, buf);
635+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
636+ goto EXIT;
738637 }
739- CreateJavaVM(vm_args_opt, useServerVM, &err);
740- switch(err)
638+ hService = OpenService(hSCManager, service_name, SERVICE_START);
639+ if(hService == NULL)
741640 {
742- case JNI_OK:
743- break;
744- case JNI_ERR: /* unknown error */
745- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_UNKNOWN));
746- exit_code = MSG_ID_ERR_CREATE_JVM_UNKNOWN;
641+ GetWinErrorMessage(GetLastError(), &err, buf);
642+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
747643 goto EXIT;
748- case JNI_EDETACHED: /* thread detached from the VM */
749- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_EDETACHED));
750- exit_code = MSG_ID_ERR_CREATE_JVM_EDETACHED;
644+ }
645+ ret = StartService(hService, 0, NULL);
646+ if (ret == FALSE)
647+ {
648+ GetWinErrorMessage(GetLastError(), &err, buf);
649+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
751650 goto EXIT;
752- case JNI_EVERSION: /* JNI version error */
753- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_EVERSION));
754- exit_code = MSG_ID_ERR_CREATE_JVM_EVERSION;
755- goto EXIT;
756- case JNI_ENOMEM: /* not enough memory */
757- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_ENOMEM));
758- exit_code = MSG_ID_ERR_CREATE_JVM_ENOMEM;
759- goto EXIT;
760- case JNI_EEXIST: /* VM already created */
761- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_EEXIST));
762- exit_code = MSG_ID_ERR_CREATE_JVM_EEXIST;
763- goto EXIT;
764- case JNI_EINVAL: /* invalid arguments */
765- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_EINVAL));
766- exit_code = MSG_ID_ERR_CREATE_JVM_EINVAL;
767- goto EXIT;
768- case JVM_ELOADLIB:
769- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_ELOADLIB));
770- exit_code = MSG_ID_ERR_CREATE_JVM_ELOADLIB;
771- goto EXIT;
772651 }
773652
774- version = GetJavaRuntimeVersion();
775- targetVersionString = (LPTSTR)GetResourceBuffer("TARGET_VERSION");
776- targetVersion = *(DWORD*)targetVersionString;
777- if(targetVersion > version)
653+ sprintf(buf, _(MSG_ID_SUCCESS_SERVICE_START), service_name);
654+ strcat(buf, "\n");
655+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
656+
657+EXIT:
658+ if (buf != NULL)
778659 {
779- sprintf(message, _(MSG_ID_ERR_TARGET_VERSION), targetVersionString + 4);
780- lstrcat(message, "\r\n");
781- OutputMessage(message);
782- exit_code = MSG_ID_ERR_TARGET_VERSION;
783- goto EXIT;
660+ free(buf);
784661 }
662+ if (hService != NULL)
663+ {
664+ CloseServiceHandle(hService);
665+ }
666+ if (hSCManager != NULL)
667+ {
668+ CloseServiceHandle(hSCManager);
669+ }
785670
786- // URLConnection
787- urlConnectionClass = (*env)->DefineClass(env, "URLConnection", NULL, GetResourceBuffer("URL_CONNECTION"), GetResourceSize("URL_CONNECTION"));
788- if(urlConnectionClass == NULL)
671+ return err;
672+}
673+
674+
675+static int stop_service(char* service_name)
676+{
677+ SC_HANDLE hSCManager = NULL;
678+ SC_HANDLE hService = NULL;
679+ SERVICE_STATUS status;
680+ BOOL ret;
681+ char* buf = NULL;
682+ DWORD size;
683+ int i;
684+ int err = 0;
685+
686+ buf = (char*)malloc(2048);
687+
688+ hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
689+ if (hSCManager == NULL)
789690 {
790- sprintf(message, _(MSG_ID_ERR_DEFINE_CLASS), "URLConnection");
791- lstrcat(message, "\r\n");
792- OutputMessage(message);
793- exit_code = MSG_ID_ERR_DEFINE_CLASS;
691+ GetWinErrorMessage(GetLastError(), &err, buf);
692+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
794693 goto EXIT;
795694 }
796- // URLStreamHandler
797- urlStreamHandlerClass = (*env)->DefineClass(env, "URLStreamHandler", NULL, GetResourceBuffer("URL_STREAM_HANDLER"), GetResourceSize("URL_STREAM_HANDLER"));
798- if(urlStreamHandlerClass == NULL)
695+ hService = OpenService(hSCManager, service_name, SERVICE_ALL_ACCESS);
696+ if (hService == NULL)
799697 {
800- sprintf(message, _(MSG_ID_ERR_DEFINE_CLASS), "URLStreamHandler");
801- lstrcat(message, "\r\n");
802- OutputMessage(message);
803- exit_code = MSG_ID_ERR_DEFINE_CLASS;
698+ GetWinErrorMessage(GetLastError(), &err, buf);
699+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
804700 goto EXIT;
805701 }
806- // Loader
807- if(GetResourceBuffer("PACK_LOADER") != NULL)
702+ ret = QueryServiceStatus(hService, &status);
703+ if (ret == FALSE)
808704 {
809- // PackLoader
810- jclass packLoaderClass;
811- jmethodID packLoaderInit;
812- jobject packLoader;
813- jbyteArray classesPackGz = NULL;
814- jbyteArray resourcesGz = NULL;
815- jbyteArray splashPath = NULL;
816- jbyteArray splashImage = NULL;
817- jmethodID packLoaderInitializeMethod;
818-
819- packLoaderClass = (*env)->DefineClass(env, "PackLoader", NULL, GetResourceBuffer("PACK_LOADER"), GetResourceSize("PACK_LOADER"));
820- if(packLoaderClass == NULL)
821- {
822- sprintf(message, _(MSG_ID_ERR_DEFINE_CLASS), "PackLoader");
823- lstrcat(message, "\r\n");
824- OutputMessage(message);
825- exit_code = MSG_ID_ERR_DEFINE_CLASS;
826- goto EXIT;
827- }
828- packLoaderInit = (*env)->GetMethodID(env, packLoaderClass, "<init>", "()V");
829- if(packLoaderInit == NULL)
830- {
831- sprintf(message, _(MSG_ID_ERR_GET_METHOD), "PackLoader#init()");
832- lstrcat(message, "\r\n");
833- OutputMessage(message);
834- exit_code = MSG_ID_ERR_GET_METHOD;
835- goto EXIT;
836- }
837- packLoader = (*env)->NewObject(env, packLoaderClass, packLoaderInit);
838- if(packLoader == NULL)
839- {
840- sprintf(message, _(MSG_ID_ERR_NEW_OBJECT), "PackLoader");
841- lstrcat(message, "\r\n");
842- OutputMessage(message);
843- exit_code = MSG_ID_ERR_NEW_OBJECT;
844- goto EXIT;
845- }
846- if(GetResourceBuffer("CLASSES_PACK_GZ") != NULL)
847- {
848- classesPackGz = (*env)->NewByteArray(env, GetResourceSize("CLASSES_PACK_GZ"));
849- (*env)->SetByteArrayRegion(env, classesPackGz, 0, GetResourceSize("CLASSES_PACK_GZ"), GetResourceBuffer("CLASSES_PACK_GZ"));
850- }
851- if(GetResourceBuffer("RESOURCES_GZ") != NULL)
852- {
853- resourcesGz = (*env)->NewByteArray(env, GetResourceSize("RESOURCES_GZ"));
854- (*env)->SetByteArrayRegion(env, resourcesGz, 0, GetResourceSize("RESOURCES_GZ"), GetResourceBuffer("RESOURCES_GZ"));
855- }
856- if(GetResourceBuffer("SPLASH_PATH") != NULL)
857- {
858- splashPath = (*env)->NewByteArray(env, GetResourceSize("SPLASH_PATH"));
859- (*env)->SetByteArrayRegion(env, splashPath, 0, GetResourceSize("SPLASH_PATH"), GetResourceBuffer("SPLASH_PATH"));
860- }
861- if(GetResourceBuffer("SPLATH_IMAGE") != NULL)
862- {
863- splashImage = (*env)->NewByteArray(env, GetResourceSize("SPLASH_IMAGE"));
864- (*env)->SetByteArrayRegion(env, splashImage, 0, GetResourceSize("SPLASH_IMAGE"), GetResourceBuffer("SPLASH_IMAGE"));
865- }
866- packLoaderInitializeMethod = (*env)->GetMethodID(env, packLoaderClass, "initialize", "([B[B[B[B)Ljava/lang/Class;");
867- if(packLoaderInitializeMethod == NULL)
868- {
869- sprintf(message, _(MSG_ID_ERR_GET_METHOD), "PackLoader#initialize(byte[], byte[], byte[], byte[])");
870- lstrcat(message, "\r\n");
871- OutputMessage(message);
872- exit_code = MSG_ID_ERR_GET_METHOD;
873- goto EXIT;
874- }
875- mainClass = (jclass)((*env)->CallObjectMethod(env, packLoader, packLoaderInitializeMethod, classesPackGz, resourcesGz, splashPath, splashImage));
705+ GetWinErrorMessage(GetLastError(), &err, buf);
706+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
707+ goto EXIT;
876708 }
877- else if(GetResourceBuffer("CLASSIC_LOADER") != NULL)
709+ if (status.dwCurrentState != SERVICE_STOPPED && status.dwCurrentState != SERVICE_STOP_PENDING)
878710 {
879- // ClassicLoader
880- jclass classicLoaderClass;
881- jmethodID classicLoaderInit;
882- jobject classicLoader;
883- jbyteArray jar;
884- jmethodID classicLoaderInitializeMethod;
885-
886- classicLoaderClass = (*env)->DefineClass(env, "ClassicLoader", NULL, GetResourceBuffer("CLASSIC_LOADER"), GetResourceSize("CLASSIC_LOADER"));
887- if(classicLoaderClass == NULL)
711+ if (ControlService(hService, SERVICE_CONTROL_STOP, &status) == 0)
888712 {
889- sprintf(message, _(MSG_ID_ERR_DEFINE_CLASS), "ClassicLoader");
890- lstrcat(message, "\r\n");
891- OutputMessage(message);
892- exit_code = MSG_ID_ERR_DEFINE_CLASS;
713+ GetWinErrorMessage(GetLastError(), &err, buf);
714+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
893715 goto EXIT;
894716 }
895- classicLoaderInit = (*env)->GetMethodID(env, classicLoaderClass, "<init>", "()V");
896- if(classicLoaderInit == NULL)
717+ buf = (char*)malloc(1024);
718+ sprintf(buf, _(MSG_ID_SERVICE_STOPING), service_name);
719+ strcat(buf, "\n");
720+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
721+ for (i = 0; i < 240; i++)
897722 {
898- sprintf(message, _(MSG_ID_ERR_GET_METHOD), "ClassicLoader#init()");
899- lstrcat(message, "\r\n");
900- OutputMessage(message);
901- exit_code = MSG_ID_ERR_GET_METHOD;
902- goto EXIT;
723+ if (QueryServiceStatus(hService, &status) == 0)
724+ {
725+ GetWinErrorMessage(GetLastError(), &err, buf);
726+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
727+ goto EXIT;
728+ }
729+ if (status.dwCurrentState == SERVICE_STOPPED)
730+ {
731+ sprintf(buf, _(MSG_ID_SUCCESS_SERVICE_STOP), service_name);
732+ strcat(buf, "\n");
733+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)strlen(buf), &size, NULL);
734+ break;
735+ }
736+ Sleep(500);
903737 }
904- classicLoader = (*env)->NewObject(env, classicLoaderClass, classicLoaderInit);
905- if(classicLoader == NULL)
906- {
907- sprintf(message, _(MSG_ID_ERR_NEW_OBJECT), "ClassicLoader");
908- lstrcat(message, "\r\n");
909- OutputMessage(message);
910- exit_code = MSG_ID_ERR_NEW_OBJECT;
911- goto EXIT;
912- }
913- jar = (*env)->NewByteArray(env, GetResourceSize("JAR"));
914- (*env)->SetByteArrayRegion(env, jar, 0, GetResourceSize("JAR"), GetResourceBuffer("JAR"));
915- classicLoaderInitializeMethod = (*env)->GetMethodID(env, classicLoaderClass, "initialize", "([B)Ljava/lang/Class;");
916- if(classicLoaderInitializeMethod == NULL)
917- {
918- sprintf(message, _(MSG_ID_ERR_GET_METHOD), "ClassicLoader#initialize(byte[])");
919- lstrcat(message, "\r\n");
920- OutputMessage(message);
921- exit_code = MSG_ID_ERR_GET_METHOD;
922- goto EXIT;
923- }
924- mainClass = (jclass)((*env)->CallObjectMethod(env, classicLoader, classicLoaderInitializeMethod, jar));
925738 }
926- else
739+
740+EXIT:
741+ if (buf != NULL)
927742 {
928- sprintf(message, _(MSG_ID_ERR_FIND_CLASSLOADER));
929- lstrcat(message, "\r\n");
930- OutputMessage(message);
931- exit_code = MSG_ID_ERR_FIND_CLASSLOADER;
932- goto EXIT;
743+ free(buf);
933744 }
934- // Main-Class
935- if(mainClass == NULL)
745+ if (hService != NULL)
936746 {
937- (*env)->ExceptionDescribe(env);
938- exit_code = MSG_ID_ERR_LOAD_MAIN_CLASS;
939- goto EXIT;
747+ CloseServiceHandle(hService);
940748 }
941- mainMethod = (*env)->GetStaticMethodID(env, mainClass, "main", "([Ljava/lang/String;)V");
942- if(mainMethod == NULL)
749+ if (hSCManager != NULL)
943750 {
944- sprintf(message, _(MSG_ID_ERR_FIND_MAIN_METHOD));
945- lstrcat(message, "\r\n");
946- OutputMessage(message);
947- exit_code = MSG_ID_ERR_FIND_MAIN_METHOD;
948- goto EXIT;
751+ CloseServiceHandle(hSCManager);
949752 }
950- args = (*env)->NewObjectArray(env, argc - 1, (*env)->FindClass(env, "java/lang/String"), NULL);
951- for(i = 1; i < argc; i++)
753+
754+ return err;
755+}
756+
757+
758+static void start_service_main()
759+{
760+ char* service_name = get_service_name(NULL);
761+
762+ service_status.dwServiceType = SERVICE_WIN32;
763+ service_status.dwCurrentState = SERVICE_START_PENDING;
764+ service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
765+ service_status.dwWin32ExitCode = 0;
766+ service_status.dwServiceSpecificExitCode = 0;
767+ service_status.dwCheckPoint = 0;
768+ service_status.dwWaitHint = 0;
769+
770+ hStatus = RegisterServiceCtrlHandler(service_name, (LPHANDLER_FUNCTION)service_control_handler);
771+ if (hStatus == (SERVICE_STATUS_HANDLE)0)
952772 {
953- (*env)->SetObjectArrayElement(env, args, (i - 1), GetJString(env, argv[i]));
773+ // Registering Control Handler failed.
774+ goto EXIT;
954775 }
955- (*env)->CallStaticVoidMethod(env, mainClass, mainMethod, args);
956-
957- (*env)->ExceptionDescribe(env);
958- (*env)->ExceptionClear(env);
959776
777+ service_status.dwCurrentState = SERVICE_RUNNING;
778+ SetServiceStatus(hStatus, &service_status);
779+
780+ ARG_VALUE[0] = service_name;
781+ service_status.dwServiceSpecificExitCode = service_main(ARG_COUNT, ARG_VALUE);
782+ service_status.dwWin32ExitCode = NO_ERROR;
783+
784+ service_status.dwCurrentState = SERVICE_STOPPED;
785+ service_status.dwCheckPoint++;
786+ service_status.dwWaitHint = 0;
787+ SetServiceStatus(hStatus, &service_status);
788+
960789 EXIT:
961- if(message != NULL)
790+ if (service_name != NULL)
962791 {
963- HeapFree(GetProcessHeap(), 0, message);
792+ HeapFree(GetProcessHeap(), 0, service_name);
964793 }
965- if(env != NULL)
794+}
795+
796+
797+static void stop_service_main()
798+{
799+ BOOL is_service = (flags & SERVICE_START_BY_SCM);
800+ JNIEnv* env = AttachJavaVM();
801+ char* buf = NULL;
802+
803+ (*env)->CallStaticVoidMethod(env, MainClass, MainClass_stop);
804+
805+ if ((*env)->ExceptionCheck(env) == JNI_TRUE)
966806 {
967- DetachJavaVM();
807+ jthrowable throwable = (*env)->ExceptionOccurred(env);
808+ if (throwable != NULL)
809+ {
810+ buf = malloc(2048);
811+ ToString(env, throwable, buf);
812+ if (is_service)
813+ {
814+ WriteEventLog(EVENTLOG_ERROR_TYPE, buf);
815+ }
816+ else
817+ {
818+ OutputMessage(buf);
819+ }
820+ (*env)->DeleteLocalRef(env, throwable);
821+ }
822+ (*env)->ExceptionClear(env);
968823 }
969- if(jvm != NULL)
824+
825+ DetachJavaVM();
826+
827+ if (buf != NULL)
970828 {
971- DestroyJavaVM();
829+ free(buf);
972830 }
973- return exit_code;
974831 }
975832
976833
977-BOOL WINAPI HandlerRoutine(DWORD dwCtrlType)
834+static BOOL WINAPI console_control_handler(DWORD dwCtrlType)
978835 {
979836 static int ctrl_c = 0;
980837
981- switch(dwCtrlType)
838+ switch (dwCtrlType)
982839 {
983840 case CTRL_C_EVENT:
984- if(ctrl_c++ == 0) { //初回は終了処理を試みます。
841+ if (ctrl_c++ == 0)
842+ {
843+ //初回は終了処理を試みます。
985844 printf(_(MSG_ID_CTRL_SERVICE_STOP), "CTRL_C");
986845 printf("\r\n");
987- service_stop();
846+ stop_service_main();
988847 return TRUE;
989- } else {
848+ }
849+ else
850+ {
990851 printf(_(MSG_ID_CTRL_SERVICE_TERMINATE), "CTRL_C");
991852 printf("\r\n");
992853 return FALSE;
@@ -1000,22 +861,24 @@
1000861 case CTRL_CLOSE_EVENT:
1001862 printf(_(MSG_ID_CTRL_SERVICE_STOP), "CTRL_CLOSE");
1002863 printf("\r\n");
1003- service_stop();
864+ stop_service_main();
1004865 return TRUE;
1005866
1006867 case CTRL_LOGOFF_EVENT:
1007- if(isService == FALSE) {
868+ if (!(flags & SERVICE_START_BY_SCM))
869+ {
1008870 printf(_(MSG_ID_CTRL_SERVICE_STOP), "CTRL_LOGOFF");
1009871 printf("\r\n");
1010- service_stop();
872+ stop_service_main();
1011873 }
1012874 return TRUE;
1013875
1014876 case CTRL_SHUTDOWN_EVENT:
1015- if(isService == FALSE) {
877+ if (!(flags & SERVICE_START_BY_SCM))
878+ {
1016879 printf(_(MSG_ID_CTRL_SERVICE_STOP), "CTRL_SHUTDOWN");
1017880 printf("\r\n");
1018- service_stop();
881+ stop_service_main();
1019882 }
1020883 return TRUE;
1021884 }
@@ -1022,77 +885,290 @@
1022885 return FALSE;
1023886 }
1024887
1025-void InitResource(LPCTSTR name)
888+
889+static void service_control_handler(DWORD request)
1026890 {
1027- HRSRC hrsrc;
891+ switch (request) {
892+ case SERVICE_CONTROL_STOP:
893+ case SERVICE_CONTROL_SHUTDOWN:
894+ if (service_status.dwCurrentState == SERVICE_RUNNING)
895+ {
896+ service_status.dwWin32ExitCode = 0;
897+ service_status.dwCurrentState = SERVICE_STOP_PENDING;
898+ service_status.dwCheckPoint = 0;
899+ service_status.dwWaitHint = 2000;
900+ SetServiceStatus(hStatus, &service_status);
901+ stop_service_main();
1028902
1029- if((hrsrc = FindResource(NULL, name, RT_RCDATA)) == NULL)
1030- {
1031- size = 0;
1032- buffer = NULL;
1033- return;
903+ return;
904+ }
905+ else
906+ {
907+ service_status.dwCheckPoint++;
908+ SetServiceStatus(hStatus, &service_status);
909+
910+ return;
911+ }
1034912 }
1035- size = SizeofResource(NULL, hrsrc);
1036- buffer = (jbyte*)LockResource(LoadResource(NULL, hrsrc));
1037- lstrcpy(cache, name);
913+ SetServiceStatus(hStatus, &service_status);
1038914 }
1039915
1040-DWORD GetResourceSize(LPCTSTR name)
916+
917+static int parse_args(int* argc_ptr, char* argv[], int* opt_end)
1041918 {
1042- if(lstrcmp(name, cache) != 0)
919+ int argc = *argc_ptr;
920+ int flags = 0;
921+ int i;
922+ BOOL has_opt_s = FALSE;
923+
924+ *opt_end = 0;
925+
926+ if (strcmp(argv[argc - 1], RUN_AS_ADMINISTRATOR_ARG) == 0)
1043927 {
1044- InitResource(name);
928+ flags |= RUN_AS_ADMINISTRATOR;
929+ *argc_ptr = --argc;
1045930 }
1046- return size;
931+ if ((argc >= 2) && (strcmp(argv[1], "-service") == 0))
932+ {
933+ flags |= SERVICE_START_BY_SCM;
934+ }
935+ for (i = 1; i < argc; i++)
936+ {
937+ if (strcmp(argv[i], "-s") == 0)
938+ {
939+ has_opt_s = TRUE;
940+ }
941+ if (strcmp(argv[i], "-install") == 0)
942+ {
943+ flags |= SERVICE_INSTALL;
944+ if (has_opt_s)
945+ {
946+ flags |= SERVICE_START_IMMEDIATELY;
947+ }
948+ *opt_end = i - 1;
949+ break;
950+ }
951+ if (strcmp(argv[i], "-remove") == 0)
952+ {
953+ flags |= SERVICE_REMOVE;
954+ if (has_opt_s)
955+ {
956+ flags |= SERVICE_STOP_BEFORE_REMOVE;
957+ }
958+ *opt_end = i - 1;
959+ break;
960+ }
961+ }
962+ if ((argc == 2) && ((strcmp(argv[1], "--help") == 0) || (strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "-?") == 0)))
963+ {
964+ flags |= SHOW_HELP_MESSAGE;
965+ }
966+
967+ return flags;
1047968 }
1048969
1049-jbyte* GetResourceBuffer(LPCTSTR name)
970+
971+static char** parse_opt(int argc, char* argv[])
1050972 {
1051- if(lstrcmp(name, cache) != 0)
973+ int i;
974+ char** opt = (char**)HeapAlloc(GetProcessHeap(), 0, 256 * 8);
975+
976+ SecureZeroMemory(opt, 256 * 8);
977+
978+ if ((argc > 1) && (*argv[1] != '-'))
1052979 {
1053- InitResource(name);
980+ opt[0] = argv[1];
1054981 }
1055- return buffer;
982+ for (i = 0; i < argc; i++)
983+ {
984+ if (*argv[i] == '-')
985+ {
986+ if (argv[i + 1] == NULL || *argv[i + 1] == '-')
987+ {
988+ opt[*(argv[i] + 1)] = "";
989+ }
990+ else
991+ {
992+ opt[*(argv[i] + 1)] = argv[i + 1];
993+ }
994+ }
995+ }
996+ if ((opt[0] == NULL) && (*argv[argc - 1] != '-'))
997+ {
998+ opt[0] = argv[argc - 1];
999+ }
1000+ return opt;
10561001 }
10571002
1058-void OutputMessage(const char* text)
1003+
1004+static void show_help_message()
10591005 {
1060- int size = lstrlen(text);
1061- DWORD written;
1006+ char* buf;
1007+ char* name;
10621008
1063- WriteConsole(GetStdHandle(STD_ERROR_HANDLE), text, size, &written, NULL);
1009+ buf = malloc(1024);
1010+ GetModuleFileName(NULL, buf, 1024);
1011+ name = strrchr(buf, '\\') + 1;
1012+
1013+ printf("Usage:\r\n"
1014+ " %s [install-options] -install [runtime-arguments]\r\n"
1015+ " %s [remove-options] -remove\r\n"
1016+ " %s [runtime-arguments]\r\n"
1017+ "\r\n"
1018+ "Install Options:\r\n"
1019+ " -n <display-name>\t set service display name.\r\n"
1020+ " -i \t allow interactive.\r\n"
1021+ " -m \t \r\n"
1022+ " -d <dependencies>\t \r\n"
1023+ " -u <username> \t \r\n"
1024+ " -p <password> \t \r\n"
1025+ " -s \t start service.\r\n"
1026+ "\r\n"
1027+ "Remove Options:\r\n"
1028+ " -s \t stop service.\r\n"
1029+ , name, name, name);
10641030 }
10651031
1066-void JNICALL JNI_WriteEventLog(JNIEnv *env, jobject clazz, jint logType, jstring message)
1032+
1033+static void set_current_dir()
10671034 {
1068- WORD nType = EVENTLOG_INFORMATION_TYPE;
1069- switch(logType)
1035+ char* b = (char*)HeapAlloc(GetProcessHeap(), 0, 1024);
1036+
1037+ GetModuleFileName(NULL, b, 1024);
1038+ *(strrchr(b, '\\')) = '\0';
1039+ SetCurrentDirectory(b);
1040+
1041+ HeapFree(GetProcessHeap(), 0, b);
1042+}
1043+
1044+
1045+static char* get_service_name(char* buf)
1046+{
1047+ char* b = (char*)HeapAlloc(GetProcessHeap(), 0, 1024);
1048+ char* name;
1049+
1050+ GetModuleFileName(NULL, b, 1024);
1051+ *(strrchr(b, '.')) = '\0';
1052+ name = strrchr(b, '\\') + 1;
1053+
1054+ if (buf == NULL)
10701055 {
1071- case 0: nType = EVENTLOG_INFORMATION_TYPE; break;
1072- case 1: nType = EVENTLOG_WARNING_TYPE; break;
1073- case 2: nType = EVENTLOG_ERROR_TYPE; break;
1056+ buf = (char*)HeapAlloc(GetProcessHeap(), 0, strlen(name) + 1);
10741057 }
1075- WriteEventLog(nType, GetShiftJIS(env, message));
1058+ strcpy(buf, name);
1059+ HeapFree(GetProcessHeap(), 0, b);
1060+ return buf;
10761061 }
10771062
1078-void JNICALL JNI_UncaughtException(JNIEnv *env, jobject clazz, jstring message, jstring trace)
1063+
1064+static char* get_pipe_name(char* buf)
10791065 {
1080- char* buf = (char*)HeapAlloc(GetProcessHeap(), 0, 8192);
1066+ char* b = (char*)HeapAlloc(GetProcessHeap(), 0, 1024);
1067+ char* name;
10811068
1082- sprintf(buf, _(MSG_ID_ERR_SERVICE_ABORT), service_name);
1083- lstrcat(buf, "\r\n\r\n");
1084- lstrcat(buf, GetShiftJIS(env, trace));
1069+ GetModuleFileName(NULL, b, 1024);
1070+ name = strrchr(b, '\\') + 1;
10851071
1086- if(isService)
1072+ if (buf == NULL)
10871073 {
1088- WriteEventLog(EVENTLOG_ERROR_TYPE, buf);
1074+ buf = (char*)HeapAlloc(GetProcessHeap(), 0, strlen(name) + 16);
10891075 }
1076+ sprintf(buf, "\\\\.\\pipe\\%s.pipe", name);
1077+ HeapFree(GetProcessHeap(), 0, b);
1078+
1079+ return buf;
1080+}
1081+
1082+
1083+static int run_as_administrator(HANDLE pipe, int argc, char* argv[], char* append)
1084+{
1085+ char* module = NULL;
1086+ char* params = NULL;
1087+ int i;
1088+ char* buf = NULL;
1089+ BOOL ret;
1090+ int exit_code = 0;
1091+ SHELLEXECUTEINFO si;
1092+
1093+ module = malloc(1024);
1094+ GetModuleFileName(NULL, module, 1024);
1095+
1096+ params = malloc(2048);
1097+ params[0] = '\0';
1098+ for (i = 1; i < argc; i++)
1099+ {
1100+ strcat(params, "\"");
1101+ strcat(params, argv[i]);
1102+ strcat(params, "\" ");
1103+ }
1104+ strcat(params, append);
1105+
1106+ ZeroMemory(&si, sizeof(SHELLEXECUTEINFO));
1107+ si.cbSize = sizeof(SHELLEXECUTEINFO);
1108+ si.fMask = SEE_MASK_NOCLOSEPROCESS;
1109+ si.hwnd = GetActiveWindow();
1110+ si.lpVerb = "runas";
1111+ si.lpFile = module;
1112+ si.lpParameters = params;
1113+ si.lpDirectory = NULL;
1114+ si.nShow = SW_HIDE;
1115+ si.hInstApp = 0;
1116+ si.hProcess = 0;
1117+
1118+ ret = ShellExecuteEx(&si);
1119+ if (GetLastError() == ERROR_CANCELLED)
1120+ {
1121+ OutputMessage(GetWinErrorMessage(GetLastError(), &exit_code, NULL));
1122+ goto EXIT;
1123+ }
1124+ else if (ret == TRUE)
1125+ {
1126+ buf = (char*)HeapAlloc(GetProcessHeap(), 0, 1024);
1127+ DWORD read_size;
1128+ DWORD write_size;
1129+
1130+ if (!ConnectNamedPipe(pipe, NULL))
1131+ {
1132+ OutputMessage(GetWinErrorMessage(GetLastError(), &exit_code, NULL));
1133+ goto EXIT;
1134+ }
1135+ for (;;)
1136+ {
1137+ if (!ReadFile(pipe, buf, 1024, &read_size, NULL))
1138+ {
1139+ break;
1140+ }
1141+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, read_size, &write_size, NULL);
1142+ }
1143+ FlushFileBuffers(pipe);
1144+ DisconnectNamedPipe(pipe);
1145+
1146+ WaitForSingleObject(si.hProcess, INFINITE);
1147+ ret = GetExitCodeProcess(si.hProcess, &exit_code);
1148+ if (ret == FALSE)
1149+ {
1150+ exit_code = GetLastError();
1151+ }
1152+ CloseHandle(si.hProcess);
1153+ }
10901154 else
10911155 {
1092- lstrcat(buf, "\r\n");
1093- OutputMessage(buf);
1156+ exit_code = GetLastError();
10941157 }
1095- HeapFree(GetProcessHeap(), 0, buf);
10961158
1097- ExitProcess(0);
1159+EXIT:
1160+ if (buf != NULL)
1161+ {
1162+ HeapFree(GetProcessHeap(), 0, buf);
1163+ }
1164+ if (params != NULL)
1165+ {
1166+ free(params);
1167+ }
1168+ if (module != NULL)
1169+ {
1170+ free(module);
1171+ }
1172+
1173+ return exit_code;
10981174 }
--- exewrap/trunk/exewrap/src/include/message.h (revision 19)
+++ exewrap/trunk/exewrap/src/include/message.h (revision 20)
@@ -7,7 +7,7 @@
77 #define MSG_LANG_ID_EN 0
88 #define MSG_LANG_ID_JA 1
99
10-#define MSG_ID_COUNT 27
10+#define MSG_ID_COUNT 31
1111 #define MSG_ID_ERR_CREATE_JVM_UNKNOWN 1
1212 #define MSG_ID_ERR_CREATE_JVM_EDETACHED 2
1313 #define MSG_ID_ERR_CREATE_JVM_EVERSION 3
@@ -15,26 +15,30 @@
1515 #define MSG_ID_ERR_CREATE_JVM_EEXIST 5
1616 #define MSG_ID_ERR_CREATE_JVM_EINVAL 6
1717 #define MSG_ID_ERR_CREATE_JVM_ELOADLIB 7
18-#define MSG_ID_ERR_TARGET_VERSION 8
19-#define MSG_ID_ERR_DEFINE_CLASS 9
20-#define MSG_ID_ERR_GET_METHOD 10
21-#define MSG_ID_ERR_NEW_OBJECT 11
22-#define MSG_ID_ERR_FIND_CLASSLOADER 12
23-#define MSG_ID_ERR_REGISTER_NATIVE 13
24-#define MSG_ID_ERR_LOAD_MAIN_CLASS 14
25-#define MSG_ID_ERR_FIND_MAIN_METHOD 15
26-#define MSG_ID_ERR_FIND_METHOD_SERVICE_START 16
27-#define MSG_ID_ERR_FIND_METHOD_SERVICE_STOP 17
28-#define MSG_ID_ERR_SERVICE_ABORT 18
29-#define MSG_ID_SUCCESS_SERVICE_INSTALL 19
30-#define MSG_ID_SUCCESS_SERVICE_REMOVE 20
31-#define MSG_ID_SERVICE_STARTING 21
32-#define MSG_ID_SERVICE_STOPING 22
33-#define MSG_ID_SUCCESS_SERVICE_START 23
34-#define MSG_ID_SUCCESS_SERVICE_STOP 24
35-#define MSG_ID_CTRL_SERVICE_STOP 25
36-#define MSG_ID_CTRL_SERVICE_TERMINATE 26
37-#define MSG_ID_CTRL_BREAK 27
18+#define MSG_ID_ERR_UNCAUGHT_EXCEPTION 8
19+#define MSG_ID_ERR_RESOURCE_NOT_FOUND 9
20+#define MSG_ID_ERR_TARGET_VERSION 10
21+#define MSG_ID_ERR_DEFINE_CLASS 11
22+#define MSG_ID_ERR_GET_METHOD 12
23+#define MSG_ID_ERR_GET_CONSTRUCTOR 13
24+#define MSG_ID_ERR_NEW_OBJECT 14
25+#define MSG_ID_ERR_FIND_CLASSLOADER 15
26+#define MSG_ID_ERR_REGISTER_NATIVE 16
27+#define MSG_ID_ERR_LOAD_MAIN_CLASS 17
28+#define MSG_ID_ERR_FIND_MAIN_METHOD 18
29+#define MSG_ID_ERR_FIND_METHOD_SERVICE_START 19
30+#define MSG_ID_ERR_FIND_METHOD_SERVICE_STOP 20
31+#define MSG_ID_ERR_SERVICE_ABORT 21
32+#define MSG_ID_ERR_SERVICE_NOT_STOPPED 22
33+#define MSG_ID_SUCCESS_SERVICE_INSTALL 23
34+#define MSG_ID_SUCCESS_SERVICE_REMOVE 24
35+#define MSG_ID_SERVICE_STARTING 25
36+#define MSG_ID_SERVICE_STOPING 26
37+#define MSG_ID_SUCCESS_SERVICE_START 27
38+#define MSG_ID_SUCCESS_SERVICE_STOP 28
39+#define MSG_ID_CTRL_SERVICE_STOP 29
40+#define MSG_ID_CTRL_SERVICE_TERMINATE 30
41+#define MSG_ID_CTRL_BREAK 31
3842
3943 extern const char* get_message(int msg_id);
4044
--- exewrap/trunk/exewrap/src/include/loader.h (revision 0)
+++ exewrap/trunk/exewrap/src/include/loader.h (revision 20)
@@ -0,0 +1,44 @@
1+#ifndef _LOADER_H_
2+#define _LOADER_H_
3+
4+#include <windows.h>
5+#include <jni.h>
6+
7+#define UTIL_UNCAUGHT_EXCEPTION_HANDLER "UncaughtExceptionHandler;"
8+#define UTIL_FILE_LOG_STREAM "FileLogStream;"
9+#define UTIL_EVENT_LOG_STREAM "EventLogStream;"
10+#define UTIL_EVENT_LOG_HANDLER "EventLogHandler;"
11+
12+typedef struct _RESOURCE {
13+ BYTE* buf;
14+ DWORD len;
15+} RESOURCE;
16+
17+typedef struct _LOAD_RESULT {
18+ jclass MainClass;
19+ jmethodID MainClass_main;
20+ jobjectArray MainClass_main_args;
21+ int msg_id;
22+ char* msg;
23+} LOAD_RESULT;
24+
25+#ifdef __cplusplus
26+extern "C" {
27+#endif
28+
29+extern BOOL LoadMainClass(int argc, char* argv[], char* utilities, LOAD_RESULT* result);
30+extern BOOL SetSplashScreenResource(char* splash_screen_name, BYTE* splash_screen_image_buf, DWORD splash_screen_image_len);
31+extern DWORD WINAPI RemoteCallMainMethod(void* _shared_memory_handle);
32+extern char* ToString(JNIEnv* env, jobject object, char* buf);
33+extern char* GetModuleObjectName(const char* prefix);
34+extern BYTE* GetResource(LPCTSTR name, RESOURCE* resource);
35+extern char* GetWinErrorMessage(DWORD err, int* exit_code, char* buf);
36+extern char* GetJniErrorMessage(int err, int* exit_code, char* buf);
37+extern void JNICALL JNI_WriteEventLog(JNIEnv *env, jobject clazz, jint logType, jstring message);
38+extern void JNICALL JNI_UncaughtException(JNIEnv *env, jobject clazz, jstring thread, jstring message, jstring trace);
39+
40+#ifdef __cplusplus
41+}
42+#endif
43+
44+#endif
--- exewrap/trunk/exewrap/src/include/notify.h (revision 19)
+++ exewrap/trunk/exewrap/src/include/notify.h (revision 20)
@@ -5,9 +5,8 @@
55 extern "C" {
66 #endif
77
8-extern LPSTR GetModuleObjectName(LPCSTR prefix);
9-extern HANDLE notify_exec(DWORD (WINAPI *start_address)(void*), int argc, char* argv[]);
10-extern void notify_close();
8+extern HANDLE NotifyExec(DWORD (WINAPI *start_address)(void*), int argc, char* argv[]);
9+extern void NotifyClose();
1110
1211 #ifdef __cplusplus
1312 }
--- exewrap/trunk/exewrap/src/image_console.c (revision 19)
+++ exewrap/trunk/exewrap/src/image_console.c (revision 20)
@@ -7,460 +7,144 @@
77 #include <jni.h>
88
99 #include "include/jvm.h"
10+#include "include/loader.h"
1011 #include "include/notify.h"
1112 #include "include/message.h"
1213
13-DWORD WINAPI CallMainMethod(void* arglist);
14-char** arg_split(char* buffer, int* p_argc);
15-
16-void InitResource(LPCTSTR name);
17-DWORD GetResourceSize(LPCTSTR name);
18-jbyte* GetResourceBuffer(LPCTSTR name);
1914 void OutputMessage(const char* text);
15+UINT UncaughtException(const char* thread, const char* message, const char* trace);
2016
21-TCHAR cache[] = "12345678901234567890123456789012";
22-jbyte* buffer = NULL;
23-DWORD size = 0;
24-
25-jclass mainClass = NULL;
26-jmethodID mainMethod = NULL;
27-
2817 int main(int argc, char* argv[])
2918 {
30- int exit_code = 0;
31- int i;
32- BOOL useServerVM = FALSE;
33- int err;
34- LPTSTR ext_flags = NULL;
35- LPTSTR relative_classpath = NULL;
36- LPTSTR relative_extdirs = "lib";
37- HANDLE synchronize_mutex_handle = NULL;
38- LPTSTR vm_args_opt = NULL;
39- DWORD version;
40- LPTSTR targetVersionString;
41- DWORD targetVersion;
42- char* message = NULL;
43- jclass urlConnectionClass;
44- jclass urlStreamHandlerClass;
45- jobjectArray args;
19+ int err;
20+ char* relative_classpath;
21+ char* relative_extdirs;
22+ BOOL use_server_vm;
23+ HANDLE synchronize_mutex_handle = NULL;
24+ char* ext_flags;
25+ char* vm_args_opt;
26+ char utilities[128];
27+ RESOURCE res;
28+ LOAD_RESULT result;
4629
47- message = (char*)HeapAlloc(GetProcessHeap(), 0, 1024);
30+ result.msg = malloc(2048);
4831
49- if(GetResourceSize("RELATIVE_CLASSPATH") > 0)
50- {
51- relative_classpath = (LPTSTR)GetResourceBuffer("RELATIVE_CLASSPATH");
52- }
53- if(GetResourceSize("EXTDIRS") > 0)
54- {
55- relative_extdirs = (LPTSTR)GetResourceBuffer("EXTDIRS");
56- }
57- if(GetResourceSize("EXTFLAGS") > 0)
58- {
59- ext_flags = _strupr((LPTSTR)GetResourceBuffer("EXTFLAGS"));
60- }
61- if(ext_flags != NULL && strstr(ext_flags, "SERVER") != NULL)
62- {
63- useServerVM = TRUE;
64- }
32+ relative_classpath = (char*)GetResource("CLASS_PATH", NULL);
33+ relative_extdirs = (char*)GetResource("EXTDIRS", NULL);
34+ ext_flags = (char*)GetResource("EXTFLAGS", NULL);
35+ use_server_vm = (ext_flags != NULL && strstr(ext_flags, "SERVER") != NULL);
36+ InitializePath(relative_classpath, relative_extdirs, use_server_vm);
6537
66- InitializePath(relative_classpath, relative_extdirs, useServerVM);
67-
68- if(ext_flags != NULL && strstr(ext_flags, "SHARE") != NULL)
38+ if (ext_flags != NULL && strstr(ext_flags, "SHARE") != NULL)
6939 {
70- synchronize_mutex_handle = notify_exec(CallMainMethod, argc, argv);
71- if(synchronize_mutex_handle == NULL)
40+ synchronize_mutex_handle = NotifyExec(RemoteCallMainMethod, argc, argv);
41+ if (synchronize_mutex_handle == NULL)
7242 {
73- exit_code = 0;
43+ result.msg_id = 0;
7444 goto EXIT;
7545 }
7646 }
77- if(ext_flags != NULL && strstr(ext_flags, "SINGLE") != NULL)
47+ if (ext_flags != NULL && strstr(ext_flags, "SINGLE") != NULL)
7848 {
79- if(CreateMutex(NULL, TRUE, GetModuleObjectName("SINGLE")), GetLastError() == ERROR_ALREADY_EXISTS)
49+ if (CreateMutex(NULL, TRUE, GetModuleObjectName("SINGLE")), GetLastError() == ERROR_ALREADY_EXISTS)
8050 {
81- exit_code = 0;
51+ result.msg_id = 0;
8252 goto EXIT;
8353 }
8454 }
8555
86- if(GetResourceSize("VMARGS") > 0)
56+ vm_args_opt = (char*)GetResource("VMARGS", NULL);
57+ CreateJavaVM(vm_args_opt, use_server_vm, &err);
58+ if (err != JNI_OK)
8759 {
88- vm_args_opt = (LPTSTR)GetResourceBuffer("VMARGS");
89- }
90-
91- CreateJavaVM(vm_args_opt, useServerVM, &err);
92- switch(err) {
93- case JNI_OK:
94- break;
95- case JNI_ERR: /* unknown error */
96- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_UNKNOWN));
97- exit_code = MSG_ID_ERR_CREATE_JVM_UNKNOWN;
60+ OutputMessage(GetJniErrorMessage(err, &result.msg_id, result.msg));
9861 goto EXIT;
99- case JNI_EDETACHED: /* thread detached from the VM */
100- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_EDETACHED));
101- exit_code = MSG_ID_ERR_CREATE_JVM_EDETACHED;
102- goto EXIT;
103- case JNI_EVERSION: /* JNI version error */
104- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_EVERSION));
105- exit_code = MSG_ID_ERR_CREATE_JVM_EVERSION;
106- goto EXIT;
107- case JNI_ENOMEM: /* not enough memory */
108- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_ENOMEM));
109- exit_code = MSG_ID_ERR_CREATE_JVM_ENOMEM;
110- goto EXIT;
111- case JNI_EEXIST: /* VM already created */
112- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_EEXIST));
113- exit_code = MSG_ID_ERR_CREATE_JVM_EEXIST;
114- goto EXIT;
115- case JNI_EINVAL: /* invalid arguments */
116- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_EINVAL));
117- exit_code = MSG_ID_ERR_CREATE_JVM_EINVAL;
118- goto EXIT;
119- case JVM_ELOADLIB:
120- sprintf(message, _(MSG_ID_ERR_CREATE_JVM_ELOADLIB), GetProcessArchitecture());
121- OutputMessage(message);
122- exit_code = MSG_ID_ERR_CREATE_JVM_ELOADLIB;
123- goto EXIT;
124- default:
125- OutputMessage(_(MSG_ID_ERR_CREATE_JVM_UNKNOWN));
126- exit_code = MSG_ID_ERR_CREATE_JVM_UNKNOWN;
127- goto EXIT;
12862 }
12963
130- version = GetJavaRuntimeVersion();
131- targetVersionString = (LPTSTR)GetResourceBuffer("TARGET_VERSION");
132- targetVersion = *(DWORD*)targetVersionString;
133- if (targetVersion > version)
64+ if(GetResource("TARGET_VERSION", &res) != NULL)
13465 {
135- sprintf(message, _(MSG_ID_ERR_TARGET_VERSION), targetVersionString + 4);
136- lstrcat(message, "\r\n");
137- OutputMessage(message);
138- exit_code = MSG_ID_ERR_TARGET_VERSION;
139- goto EXIT;
140- }
141-
142- // URLConnection
143- urlConnectionClass = (*env)->DefineClass(env, "URLConnection", NULL, GetResourceBuffer("URL_CONNECTION"), GetResourceSize("URL_CONNECTION"));
144- if(urlConnectionClass == NULL)
145- {
146- sprintf(message, _(MSG_ID_ERR_DEFINE_CLASS), "URLConnection");
147- lstrcat(message, "\r\n");
148- OutputMessage(message);
149- exit_code = MSG_ID_ERR_DEFINE_CLASS;
150- goto EXIT;
151- }
152- // URLStreamHandler
153- urlStreamHandlerClass = (*env)->DefineClass(env, "URLStreamHandler", NULL, GetResourceBuffer("URL_STREAM_HANDLER"), GetResourceSize("URL_STREAM_HANDLER"));
154- if(urlStreamHandlerClass == NULL)
155- {
156- sprintf(message, _(MSG_ID_ERR_DEFINE_CLASS), "URLStreamHandler");
157- lstrcat(message, "\r\n");
158- OutputMessage(message);
159- exit_code = MSG_ID_ERR_DEFINE_CLASS;
160- goto EXIT;
161- }
162- // Loader
163- if(GetResourceBuffer("PACK_LOADER") != NULL)
164- {
165- // PackLoader
166- jclass packLoaderClass;
167- jmethodID packLoaderInit;
168- jobject packLoader;
169- jbyteArray classesPackGz = NULL;
170- jbyteArray resourcesGz = NULL;
171- jbyteArray splashPath = NULL;
172- jbyteArray splashImage = NULL;
173- jmethodID packLoaderInitializeMethod;
174-
175- packLoaderClass = (*env)->DefineClass(env, "PackLoader", NULL, GetResourceBuffer("PACK_LOADER"), GetResourceSize("PACK_LOADER"));
176- if(packLoaderClass == NULL)
66+ DWORD version = GetJavaRuntimeVersion();
67+ DWORD targetVersion = *(DWORD*)res.buf;
68+ if (targetVersion > version)
17769 {
178- sprintf(message, _(MSG_ID_ERR_DEFINE_CLASS), "PackLoader");
179- lstrcat(message, "\r\n");
180- OutputMessage(message);
181- exit_code = MSG_ID_ERR_DEFINE_CLASS;
70+ char* targetVersionString = (char*)res.buf + 4;
71+ result.msg_id = MSG_ID_ERR_TARGET_VERSION;
72+ sprintf(result.msg, _(MSG_ID_ERR_TARGET_VERSION), targetVersionString + 4);
73+ OutputMessage(result.msg);
18274 goto EXIT;
18375 }
184- packLoaderInit = (*env)->GetMethodID(env, packLoaderClass, "<init>", "()V");
185- if(packLoaderInit == NULL)
186- {
187- sprintf(message, _(MSG_ID_ERR_GET_METHOD), "PackLoader#init()");
188- lstrcat(message, "\r\n");
189- OutputMessage(message);
190- exit_code = MSG_ID_ERR_GET_METHOD;
191- goto EXIT;
192- }
193- packLoader = (*env)->NewObject(env, packLoaderClass, packLoaderInit);
194- if(packLoader == NULL)
195- {
196- sprintf(message, _(MSG_ID_ERR_NEW_OBJECT), "PackLoader");
197- lstrcat(message, "\r\n");
198- exit_code = MSG_ID_ERR_NEW_OBJECT;
199- goto EXIT;
200- }
201- if(GetResourceBuffer("CLASSES_PACK_GZ") != NULL)
202- {
203- classesPackGz = (*env)->NewByteArray(env, GetResourceSize("CLASSES_PACK_GZ"));
204- (*env)->SetByteArrayRegion(env, classesPackGz, 0, GetResourceSize("CLASSES_PACK_GZ"), GetResourceBuffer("CLASSES_PACK_GZ"));
205- }
206- if(GetResourceBuffer("RESOURCES_GZ") != NULL)
207- {
208- resourcesGz = (*env)->NewByteArray(env, GetResourceSize("RESOURCES_GZ"));
209- (*env)->SetByteArrayRegion(env, resourcesGz, 0, GetResourceSize("RESOURCES_GZ"), GetResourceBuffer("RESOURCES_GZ"));
210- }
211- if(GetResourceBuffer("SPLASH_PATH") != NULL)
212- {
213- splashPath = (*env)->NewByteArray(env, GetResourceSize("SPLASH_PATH"));
214- (*env)->SetByteArrayRegion(env, splashPath, 0, GetResourceSize("SPLASH_PATH"), GetResourceBuffer("SPLASH_PATH"));
215- }
216- if(GetResourceBuffer("SPLATH_IMAGE") != NULL)
217- {
218- splashImage = (*env)->NewByteArray(env, GetResourceSize("SPLASH_IMAGE"));
219- (*env)->SetByteArrayRegion(env, splashImage, 0, GetResourceSize("SPLASH_IMAGE"), GetResourceBuffer("SPLASH_IMAGE"));
220- }
221- packLoaderInitializeMethod = (*env)->GetMethodID(env, packLoaderClass, "initialize", "([B[B[B[B)Ljava/lang/Class;");
222- if(packLoaderInitializeMethod == NULL)
223- {
224- sprintf(message, _(MSG_ID_ERR_GET_METHOD), "PackLoader#initialize(byte[], byte[], byte[], byte[])");
225- lstrcat(message, "\r\n");
226- OutputMessage(message);
227- exit_code = MSG_ID_ERR_GET_METHOD;
228- goto EXIT;
229- }
230- mainClass = (jclass)((*env)->CallObjectMethod(env, packLoader, packLoaderInitializeMethod, classesPackGz, resourcesGz, splashPath, splashImage));
23176 }
232- else if(GetResourceBuffer("CLASSIC_LOADER") != NULL)
233- {
234- // ClassicLoader
235- jclass classicLoaderClass;
236- jmethodID classicLoaderInit;
237- jobject classicLoader;
238- jbyteArray jar;
239- jmethodID classicLoaderInitializeMethod;
24077
241- classicLoaderClass = (*env)->DefineClass(env, "ClassicLoader", NULL, GetResourceBuffer("CLASSIC_LOADER"), GetResourceSize("CLASSIC_LOADER"));
242- if(classicLoaderClass == NULL)
243- {
244- sprintf(message, _(MSG_ID_ERR_DEFINE_CLASS), "ClassicLoader");
245- lstrcat(message, "\r\n");
246- OutputMessage(message);
247- exit_code = MSG_ID_ERR_DEFINE_CLASS;
248- goto EXIT;
249- }
250- classicLoaderInit = (*env)->GetMethodID(env, classicLoaderClass, "<init>", "()V");
251- if(classicLoaderInit == NULL)
252- {
253- sprintf(message, _(MSG_ID_ERR_GET_METHOD), "ClassicLoader#init()");
254- lstrcat(message, "\r\n");
255- OutputMessage(message);
256- exit_code = MSG_ID_ERR_GET_METHOD;
257- goto EXIT;
258- }
259- classicLoader = (*env)->NewObject(env, classicLoaderClass, classicLoaderInit);
260- if(classicLoader == NULL)
261- {
262- sprintf(message, _(MSG_ID_ERR_NEW_OBJECT), "ClassicLoader");
263- lstrcat(message, "\r\n");
264- OutputMessage(message);
265- exit_code = MSG_ID_ERR_NEW_OBJECT;
266- goto EXIT;
267- }
268- jar = (*env)->NewByteArray(env, GetResourceSize("JAR"));
269- (*env)->SetByteArrayRegion(env, jar, 0, GetResourceSize("JAR"), GetResourceBuffer("JAR"));
270- classicLoaderInitializeMethod = (*env)->GetMethodID(env, classicLoaderClass, "initialize", "([B)Ljava/lang/Class;");
271- if(classicLoaderInitializeMethod == NULL)
272- {
273- sprintf(message, _(MSG_ID_ERR_GET_METHOD), "ClassicLoader#initialize(byte[])");
274- lstrcat(message, "\r\n");
275- OutputMessage(message);
276- exit_code = MSG_ID_ERR_GET_METHOD;
277- goto EXIT;
278- }
279- mainClass = (jclass)((*env)->CallObjectMethod(env, classicLoader, classicLoaderInitializeMethod, jar));
280- }
281- else
78+ utilities[0] = '\0';
79+ if (ext_flags == NULL || strstr(ext_flags, "IGNORE_UNCAUGHT_EXCEPTION") == NULL)
28280 {
283- sprintf(message, _(MSG_ID_ERR_FIND_CLASSLOADER));
284- lstrcat(message, "\r\n");
285- OutputMessage(message);
286- exit_code = MSG_ID_ERR_FIND_CLASSLOADER;
287- goto EXIT;
81+ strcat(utilities, UTIL_UNCAUGHT_EXCEPTION_HANDLER);
28882 }
289- // Main-Class
290- if(mainClass == NULL)
83+ if (LoadMainClass(argc, argv, utilities, &result) == FALSE)
29184 {
292- (*env)->ExceptionDescribe(env);
293- exit_code = MSG_ID_ERR_LOAD_MAIN_CLASS;
85+ OutputMessage(result.msg);
29486 goto EXIT;
29587 }
296- mainMethod = (*env)->GetStaticMethodID(env, mainClass, "main", "([Ljava/lang/String;)V");
297- if(mainMethod == NULL)
88+ if (synchronize_mutex_handle != NULL)
29889 {
299- sprintf(message, _(MSG_ID_ERR_FIND_MAIN_METHOD));
300- lstrcat(message, "\r\n");
301- OutputMessage(message);
302- exit_code = MSG_ID_ERR_FIND_MAIN_METHOD;
303- goto EXIT;
304- }
305- args = (*env)->NewObjectArray(env, argc - 1, (*env)->FindClass(env, "java/lang/String"), NULL);
306- for(i = 1; i < argc; i++)
307- {
308- (*env)->SetObjectArrayElement(env, args, (i - 1), GetJString(env, argv[i]));
309- }
310-
311- if(synchronize_mutex_handle != NULL)
312- {
31390 ReleaseMutex(synchronize_mutex_handle);
31491 CloseHandle(synchronize_mutex_handle);
31592 synchronize_mutex_handle = NULL;
31693 }
94+ (*env)->CallStaticVoidMethod(env, result.MainClass, result.MainClass_main, result.MainClass_main_args);
31795
318- (*env)->CallStaticVoidMethod(env, mainClass, mainMethod, args);
319-
32096 (*env)->ExceptionDescribe(env);
32197 (*env)->ExceptionClear(env);
32298
32399 EXIT:
324- if(synchronize_mutex_handle != NULL)
100+ if (synchronize_mutex_handle != NULL)
325101 {
326102 ReleaseMutex(synchronize_mutex_handle);
327103 CloseHandle(synchronize_mutex_handle);
328104 }
329- if(message != NULL)
105+ if (result.msg != NULL)
330106 {
331- HeapFree(GetProcessHeap(), 0, message);
107+ free(result.msg);
332108 }
333- if(env != NULL)
109+ if (env != NULL)
334110 {
335111 DetachJavaVM();
336112 }
337- if(jvm != NULL)
113+ if (jvm != NULL)
338114 {
339115 DestroyJavaVM();
340116 }
341117
342- notify_close();
118+ NotifyClose();
343119
344- return exit_code;
120+ return result.msg_id;
345121 }
346122
347-DWORD WINAPI CallMainMethod(void* _shared_memory_handle)
123+void OutputMessage(const char* text)
348124 {
349- HANDLE shared_memory_handle = (HANDLE)_shared_memory_handle;
350- char* arglist;
351- char* buf;
352- int argc;
353- char** argv = NULL;
354- int i;
355- LPSTR shared_memory_read_event_name;
356- HANDLE shared_memory_read_event_handle;
357- LPBYTE lpShared = (LPBYTE)MapViewOfFile(shared_memory_handle, FILE_MAP_READ, 0, 0, 0);
358- JNIEnv* env;
359- jobjectArray args;
125+ DWORD written;
360126
361- arglist = (char*)(lpShared + sizeof(DWORD) + sizeof(DWORD));
362- buf = (char*)HeapAlloc(GetProcessHeap(), 0, lstrlen(arglist) + 1);
363- lstrcpy(buf, (char*)arglist);
364- UnmapViewOfFile(lpShared);
365-
366- shared_memory_read_event_name = GetModuleObjectName("SHARED_MEMORY_READ");
367- shared_memory_read_event_handle = OpenEvent(EVENT_MODIFY_STATE, FALSE, shared_memory_read_event_name);
368- if(shared_memory_read_event_handle != NULL)
127+ if (text == NULL)
369128 {
370- SetEvent(shared_memory_read_event_handle);
371- CloseHandle(shared_memory_read_event_handle);
129+ return;
372130 }
373- HeapFree(GetProcessHeap(), 0, shared_memory_read_event_name);
374131
375- argv = arg_split((char*)buf, &argc);
376- HeapFree(GetProcessHeap(), 0, buf);
377-
378- env = AttachJavaVM();
379- if(env == NULL)
380- {
381- goto EXIT;
382- }
383- args = (*env)->NewObjectArray(env, argc - 1, (*env)->FindClass(env, "java/lang/String"), NULL);
384- for(i = 1; i < argc; i++)
385- {
386- (*env)->SetObjectArrayElement(env, args, (i - 1), GetJString(env, argv[i]));
387- }
388-
389- (*env)->CallStaticVoidMethod(env, mainClass, mainMethod, args);
390- if((*env)->ExceptionCheck(env) == JNI_TRUE)
391- {
392- (*env)->ExceptionDescribe(env);
393- (*env)->ExceptionClear(env);
394- }
395- DetachJavaVM();
396-
397-EXIT:
398- if(argv != NULL)
399- {
400- HeapFree(GetProcessHeap(), 0, argv);
401- }
402- //_endthread();
403-
404- return 0;
132+ WriteConsole(GetStdHandle(STD_ERROR_HANDLE), text, (DWORD)strlen(text), &written, NULL);
133+ WriteConsole(GetStdHandle(STD_ERROR_HANDLE), "\r\n", 2, &written, NULL);
405134 }
406135
407-char** arg_split(char* buffer, int* p_argc)
136+UINT UncaughtException(const char* thread, const char* message, const char* trace)
408137 {
409- int i;
410- int buf_len = lstrlen(buffer);
411- char** argv;
412-
413- *p_argc = 0;
414- for(i = 0; i < buf_len; i++)
138+ if (thread != NULL)
415139 {
416- *p_argc += (buffer[i] == '\n')?1:0;
140+ char* buf = malloc(32 + strlen(thread));
141+ sprintf(buf, "Exception in thread \"%s\"", thread);
142+ OutputMessage(buf);
143+ free(buf);
417144 }
418- argv = (char**)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (*p_argc) * sizeof(char*));
419- for(i = 0; i < *p_argc; i++)
145+ if (trace != NULL)
420146 {
421- argv[i] = strtok(i?NULL:buffer, "\n");
147+ OutputMessage(trace);
422148 }
423- return argv;
149+ return MSG_ID_ERR_UNCAUGHT_EXCEPTION;
424150 }
425-
426-void InitResource(LPCTSTR name)
427-{
428- HRSRC hrsrc;
429-
430- if((hrsrc = FindResource(NULL, name, RT_RCDATA)) == NULL)
431- {
432- size = 0;
433- buffer = NULL;
434- return;
435- }
436- size = SizeofResource(NULL, hrsrc);
437- buffer = (jbyte*)LockResource(LoadResource(NULL, hrsrc));
438- lstrcpy(cache, name);
439-}
440-
441-DWORD GetResourceSize(LPCTSTR name)
442-{
443- if(lstrcmp(name, cache) != 0)
444- {
445- InitResource(name);
446- }
447- return size;
448-}
449-
450-jbyte* GetResourceBuffer(LPCTSTR name)
451-{
452- if(lstrcmp(name, cache) != 0)
453- {
454- InitResource(name);
455- }
456- return buffer;
457-}
458-
459-void OutputMessage(const char* text)
460-{
461- int size = lstrlen(text);
462- DWORD written;
463-
464- WriteConsole(GetStdHandle(STD_ERROR_HANDLE), text, size, &written, NULL);
465- WriteConsole(GetStdHandle(STD_ERROR_HANDLE), "\r\n", 2, &written, NULL);
466-}
--- exewrap/trunk/exewrap/src/loader.c (revision 0)
+++ exewrap/trunk/exewrap/src/loader.c (revision 20)
@@ -0,0 +1,808 @@
1+#define _CRT_SECURE_NO_WARNINGS
2+
3+#include <windows.h>
4+#include <process.h>
5+#include <shlobj.h>
6+#include <stdio.h>
7+#include <jni.h>
8+
9+#include "include/jvm.h"
10+#include "include/loader.h"
11+#include "include/eventlog.h"
12+#include "include/message.h"
13+
14+BOOL LoadMainClass(int argc, char* argv[], char* utilities, LOAD_RESULT* result);
15+BOOL SetSplashScreenResource(char* splash_screen_name, BYTE* splash_screen_image_buf, DWORD splash_screen_image_len);
16+DWORD WINAPI RemoteCallMainMethod(void* _shared_memory_handle);
17+char* ToString(JNIEnv* env, jobject object, char* buf);
18+char* GetModuleObjectName(const char* prefix);
19+BYTE* GetResource(LPCTSTR name, RESOURCE* resource);
20+char* GetWinErrorMessage(DWORD err, int* exit_code, char* buf);
21+char* GetJniErrorMessage(int err, int* exit_code, char* buf);
22+void JNICALL JNI_WriteEventLog(JNIEnv *env, jobject clazz, jint logType, jstring message);
23+void JNICALL JNI_UncaughtException(JNIEnv *env, jobject clazz, jstring thread, jstring message, jstring trace);
24+
25+static jint register_native(JNIEnv* env, jclass cls, const char* name, const char* signature, void* fnPtr);
26+static void print_stack_trace(const char* text);
27+static char** split_args(char* buffer, int* p_argc);
28+
29+extern void OutputMessage(const char* text);
30+extern UINT UncaughtException(const char* thread, const char* message, const char* trace);
31+
32+jclass ExewrapClassLoader = NULL;
33+jobject exewrapClassLoader = NULL;
34+jclass MainClass = NULL;
35+jmethodID MainClass_main = NULL;
36+
37+BOOL LoadMainClass(int argc, char* argv[], char* utilities, LOAD_RESULT* result)
38+{
39+ RESOURCE res;
40+ jclass ClassLoader;
41+ jmethodID ClassLoader_getSystemClassLoader;
42+ jmethodID ClassLoader_definePackage;
43+ jobject systemClassLoader;
44+ jclass JarInputStream;
45+ jmethodID JarInputStream_init;
46+ jclass ByteBufferInputStream;
47+ jmethodID ByteBufferInputStream_init;
48+ jobjectArray jars;
49+ jclass URLConnection;
50+ jclass URLStreamHandler;
51+ jmethodID ExewrapClassLoader_init;
52+ jmethodID exewrapClassLoader_registerSystemClassLoader;
53+ jmethodID exewrapClassLoader_loadUtilities;
54+ jmethodID exewrapClassLoader_getMainClass;
55+
56+ // ClassLoader
57+ ClassLoader = (*env)->FindClass(env, "java/lang/ClassLoader");
58+ if (ClassLoader == NULL)
59+ {
60+ result->msg_id = MSG_ID_ERR_DEFINE_CLASS;
61+ sprintf(result->msg, _(MSG_ID_ERR_DEFINE_CLASS), "java.lang.ClassLoader");
62+ goto EXIT;
63+ }
64+ ClassLoader_definePackage = (*env)->GetMethodID(env, ClassLoader, "definePackage", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/net/URL;)Ljava/lang/Package;");
65+ if (ClassLoader_definePackage == NULL)
66+ {
67+ result->msg_id = MSG_ID_ERR_GET_METHOD;
68+ sprintf(result->msg, _(MSG_ID_ERR_GET_METHOD), "java.lang.ClassLoader.definePackage(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.net.URL)");
69+ goto EXIT;
70+ }
71+ ClassLoader_getSystemClassLoader = (*env)->GetStaticMethodID(env, ClassLoader, "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
72+ if (ClassLoader_getSystemClassLoader == NULL)
73+ {
74+ result->msg_id = MSG_ID_ERR_GET_METHOD;
75+ sprintf(result->msg, _(MSG_ID_ERR_GET_METHOD), "java.lang.ClassLoader.getSystemClassLoader()");
76+ goto EXIT;
77+ }
78+ systemClassLoader = (*env)->CallStaticObjectMethod(env, ClassLoader, ClassLoader_getSystemClassLoader);
79+ if (systemClassLoader == NULL)
80+ {
81+ //ignore
82+ }
83+ else
84+ {
85+ // Define package "exewrap.core"
86+ jstring packageName = GetJString(env, "exewrap.core");
87+ (*env)->CallObjectMethod(env, systemClassLoader, ClassLoader_definePackage, packageName, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
88+ }
89+
90+ // JarInputStream
91+ JarInputStream = (*env)->FindClass(env, "java/util/jar/JarInputStream");
92+ if (JarInputStream == NULL)
93+ {
94+ result->msg_id = MSG_ID_ERR_DEFINE_CLASS;
95+ sprintf(result->msg, _(MSG_ID_ERR_DEFINE_CLASS), "java.util.jar.JarInputStream");
96+ goto EXIT;
97+ }
98+ JarInputStream_init = (*env)->GetMethodID(env, JarInputStream, "<init>", "(Ljava/io/InputStream;)V");
99+ if (JarInputStream_init == NULL)
100+ {
101+ result->msg_id = MSG_ID_ERR_GET_CONSTRUCTOR;
102+ sprintf(result->msg, _(MSG_ID_ERR_GET_CONSTRUCTOR), "java.util.jar.JarInputStream(java.io.InputStream)");
103+ goto EXIT;
104+ }
105+
106+ // ByteBufferInputStream
107+ if (GetResource("BYTE_BUFFER_INPUT_STREAM", &res) == NULL)
108+ {
109+ result->msg_id = MSG_ID_ERR_RESOURCE_NOT_FOUND;
110+ sprintf(result->msg, _(MSG_ID_ERR_RESOURCE_NOT_FOUND), "RT_RCDATA: BYTE_BUFFER_INPUT_STREAM");
111+ goto EXIT;
112+ }
113+ ByteBufferInputStream = (*env)->DefineClass(env, "exewrap/core/ByteBufferInputStream", systemClassLoader, res.buf, res.len);
114+ if (ByteBufferInputStream == NULL)
115+ {
116+ result->msg_id = MSG_ID_ERR_DEFINE_CLASS;
117+ sprintf(result->msg, _(MSG_ID_ERR_DEFINE_CLASS), "exewrap.core.ByteBufferInputStream");
118+ goto EXIT;
119+ }
120+ ByteBufferInputStream_init = (*env)->GetMethodID(env, ByteBufferInputStream, "<init>", "(Ljava/nio/ByteBuffer;)V");
121+ if (ByteBufferInputStream_init == NULL)
122+ {
123+ result->msg_id = MSG_ID_ERR_GET_CONSTRUCTOR;
124+ sprintf(result->msg, _(MSG_ID_ERR_GET_CONSTRUCTOR), "exewrap.core.ByteBufferInputStream(java.nio.ByteBuffer)");
125+ goto EXIT;
126+ }
127+
128+ // JarInputStream[] jars = new JarInputStream[2];
129+ jars = (*env)->NewObjectArray(env, 2, JarInputStream, NULL);
130+ if (jars == NULL)
131+ {
132+ result->msg_id = MSG_ID_ERR_NEW_OBJECT;
133+ sprintf(result->msg, _(MSG_ID_ERR_NEW_OBJECT), "JarInputStream[]");
134+ goto EXIT;
135+ }
136+
137+ //util.jar
138+ {
139+ jobject byteBuffer;
140+ jobject byteBufferInputStream = NULL;
141+ jobject jarInputStream = NULL;
142+
143+ if (GetResource("UTIL_JAR", &res) == NULL)
144+ {
145+ result->msg_id = MSG_ID_ERR_RESOURCE_NOT_FOUND;
146+ sprintf(result->msg, _(MSG_ID_ERR_RESOURCE_NOT_FOUND), "RT_RCDATA: UTIL_JAR");
147+ goto EXIT;
148+ }
149+ byteBuffer = (*env)->NewDirectByteBuffer(env, res.buf, res.len);
150+ if (byteBuffer == NULL)
151+ {
152+ result->msg_id = MSG_ID_ERR_NEW_OBJECT;
153+ sprintf(result->msg, _(MSG_ID_ERR_NEW_OBJECT), "NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity)");
154+ goto EXIT;
155+ }
156+ byteBufferInputStream = (*env)->NewObject(env, ByteBufferInputStream, ByteBufferInputStream_init, byteBuffer);
157+ if (byteBufferInputStream == NULL)
158+ {
159+ result->msg_id = MSG_ID_ERR_NEW_OBJECT;
160+ sprintf(result->msg, _(MSG_ID_ERR_NEW_OBJECT), "exewrap.core.ByteBufferInputStream(java.nio.ByteBuffer)");
161+ goto EXIT;
162+ }
163+ jarInputStream = (*env)->NewObject(env, JarInputStream, JarInputStream_init, byteBufferInputStream);
164+ if (jarInputStream == NULL)
165+ {
166+ result->msg_id = MSG_ID_ERR_NEW_OBJECT;
167+ sprintf(result->msg, _(MSG_ID_ERR_NEW_OBJECT), "java.util.jar.JarInputStream(exewrap.core.ByteBufferInputStream)");
168+ goto EXIT;
169+ }
170+ (*env)->SetObjectArrayElement(env, jars, 0, jarInputStream);
171+ }
172+
173+ // user.jar or user.pack.gz
174+ {
175+ BOOL isPackGz = TRUE;
176+ jobject byteBuffer;
177+ jobject byteBufferInputStream;
178+ jobject jarInputStream;
179+
180+ if (GetResource("PACK_GZ", &res) == NULL)
181+ {
182+ isPackGz = FALSE;
183+ if (GetResource("JAR", &res) == NULL)
184+ {
185+ result->msg_id = MSG_ID_ERR_RESOURCE_NOT_FOUND;
186+ sprintf(result->msg, _(MSG_ID_ERR_RESOURCE_NOT_FOUND), "RT_RCDATA: JAR, RT_RCDATA: PACK_GZ");
187+ goto EXIT;
188+ }
189+ }
190+ byteBuffer = (*env)->NewDirectByteBuffer(env, res.buf, res.len);
191+ if (byteBuffer == NULL)
192+ {
193+ result->msg_id = MSG_ID_ERR_NEW_OBJECT;
194+ sprintf(result->msg, _(MSG_ID_ERR_NEW_OBJECT), "NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity)");
195+ goto EXIT;
196+ }
197+ byteBufferInputStream = (*env)->NewObject(env, ByteBufferInputStream, ByteBufferInputStream_init, byteBuffer);
198+ if (byteBufferInputStream == NULL)
199+ {
200+ result->msg_id = MSG_ID_ERR_NEW_OBJECT;
201+ sprintf(result->msg, _(MSG_ID_ERR_NEW_OBJECT), "exewrap.core.ByteBufferInputStream(java.nio.ByteBuffer)");
202+ goto EXIT;
203+ }
204+ if (isPackGz)
205+ {
206+ jclass GZIPInputStream;
207+ jmethodID GZIPInputStream_init;
208+ jobject gzipInputStream;
209+ jclass PackInputStream;
210+ jmethodID PackInputStream_init;
211+ jobject packInputStream;
212+
213+ // GZIPInputStream
214+ GZIPInputStream = (*env)->FindClass(env, "java/util/zip/GZIPInputStream");
215+ if (GZIPInputStream == NULL)
216+ {
217+ result->msg_id = MSG_ID_ERR_DEFINE_CLASS;
218+ sprintf(result->msg, _(MSG_ID_ERR_DEFINE_CLASS), "java.util.zip.GZIPInputStream");
219+ goto EXIT;
220+ }
221+ GZIPInputStream_init = (*env)->GetMethodID(env, GZIPInputStream, "<init>", "(Ljava/io/InputStream;)V");
222+ if (GZIPInputStream_init == NULL)
223+ {
224+ result->msg_id = MSG_ID_ERR_GET_CONSTRUCTOR;
225+ sprintf(result->msg, _(MSG_ID_ERR_GET_CONSTRUCTOR), "java.util.zip.GZIPInputStream(java.io.InputStream)");
226+ goto EXIT;
227+ }
228+ gzipInputStream = (*env)->NewObject(env, GZIPInputStream, GZIPInputStream_init, byteBufferInputStream);
229+ if (gzipInputStream == NULL)
230+ {
231+ result->msg_id = MSG_ID_ERR_NEW_OBJECT;
232+ sprintf(result->msg, _(MSG_ID_ERR_NEW_OBJECT), "java.util.zip.GZIPInputStream(ByteBufferInputStream)");
233+ goto EXIT;
234+ }
235+
236+ // PackInputStream
237+ if (GetResource("PACK_INPUT_STREAM", &res) == NULL)
238+ {
239+ result->msg_id = MSG_ID_ERR_RESOURCE_NOT_FOUND;
240+ sprintf(result->msg, _(MSG_ID_ERR_RESOURCE_NOT_FOUND), "RT_RCDATA: PACK_INPUT_STREAM");
241+ goto EXIT;
242+ }
243+ PackInputStream = (*env)->DefineClass(env, "exewrap/core/PackInputStream", systemClassLoader, res.buf, res.len);
244+ if (PackInputStream == NULL)
245+ {
246+ result->msg_id = MSG_ID_ERR_DEFINE_CLASS;
247+ sprintf(result->msg, _(MSG_ID_ERR_DEFINE_CLASS), "exewrap.core.PackInputStream");
248+ goto EXIT;
249+ }
250+ PackInputStream_init = (*env)->GetMethodID(env, PackInputStream, "<init>", "(Ljava/io/InputStream;)V");
251+ if (PackInputStream_init == NULL)
252+ {
253+ result->msg_id = MSG_ID_ERR_GET_CONSTRUCTOR;
254+ sprintf(result->msg, _(MSG_ID_ERR_GET_CONSTRUCTOR), "exewrap.core.PackInputStream(java.io.InputStream)");
255+ goto EXIT;
256+ }
257+ packInputStream = (*env)->NewObject(env, PackInputStream, PackInputStream_init, gzipInputStream);
258+ if (packInputStream == NULL)
259+ {
260+ result->msg_id = MSG_ID_ERR_NEW_OBJECT;
261+ sprintf(result->msg, _(MSG_ID_ERR_NEW_OBJECT), "exewrap.core.PackInputStream(java.util.zip.GZIPInputStream)");
262+ goto EXIT;
263+ }
264+
265+ // JarInputStream
266+ jarInputStream = (*env)->NewObject(env, JarInputStream, JarInputStream_init, packInputStream);
267+ if (jarInputStream == NULL)
268+ {
269+ result->msg_id = MSG_ID_ERR_NEW_OBJECT;
270+ sprintf(result->msg, _(MSG_ID_ERR_NEW_OBJECT), "java.util.jar.JarInputStream(PackInputStream)");
271+ goto EXIT;
272+ }
273+ }
274+ else
275+ {
276+ // JarInputStream
277+ jarInputStream = (*env)->NewObject(env, JarInputStream, JarInputStream_init, byteBufferInputStream);
278+ if (jarInputStream == NULL)
279+ {
280+ result->msg_id = MSG_ID_ERR_NEW_OBJECT;
281+ sprintf(result->msg, _(MSG_ID_ERR_NEW_OBJECT), "java.util.jar.JarInputStream(ByteBufferInputStream)");
282+ goto EXIT;
283+ }
284+ }
285+ (*env)->SetObjectArrayElement(env, jars, 1, jarInputStream);
286+ }
287+
288+ // URLConnection
289+ if (GetResource("URL_CONNECTION", &res) == NULL)
290+ {
291+ result->msg_id = MSG_ID_ERR_RESOURCE_NOT_FOUND;
292+ sprintf(result->msg, _(MSG_ID_ERR_RESOURCE_NOT_FOUND), "RT_RCDATA: URL_CONNECTION");
293+ goto EXIT;
294+ }
295+ URLConnection = (*env)->DefineClass(env, "exewrap/core/URLConnection", systemClassLoader, res.buf, res.len);
296+ if (URLConnection == NULL)
297+ {
298+ result->msg_id = MSG_ID_ERR_DEFINE_CLASS;
299+ sprintf(result->msg, _(MSG_ID_ERR_DEFINE_CLASS), "exewrap.core.URLConnection");
300+ goto EXIT;
301+ }
302+ // URLStreamHandler
303+ if (GetResource("URL_STREAM_HANDLER", &res) == NULL)
304+ {
305+ result->msg_id = MSG_ID_ERR_RESOURCE_NOT_FOUND;
306+ sprintf(result->msg, _(MSG_ID_ERR_RESOURCE_NOT_FOUND), "RT_RCDATA: URL_STREAM_HANDLER");
307+ goto EXIT;
308+ }
309+ URLStreamHandler = (*env)->DefineClass(env, "exewrap/core/URLStreamHandler", systemClassLoader, res.buf, res.len);
310+ if (URLStreamHandler == NULL)
311+ {
312+ result->msg_id = MSG_ID_ERR_DEFINE_CLASS;
313+ sprintf(result->msg, _(MSG_ID_ERR_DEFINE_CLASS), "exewrap.core.URLStreamHandler");
314+ goto EXIT;
315+ }
316+ // ExewrapClassLoader
317+ if (GetResource("EXEWRAP_CLASS_LOADER", &res) == NULL)
318+ {
319+ result->msg_id = MSG_ID_ERR_RESOURCE_NOT_FOUND;
320+ sprintf(result->msg, _(MSG_ID_ERR_RESOURCE_NOT_FOUND), "RT_RCDATA: EXEWRAP_CLASS_LOADER");
321+ goto EXIT;
322+ }
323+ ExewrapClassLoader = (*env)->DefineClass(env, "exewrap/core/ExewrapClassLoader", systemClassLoader, res.buf, res.len);
324+ if (ExewrapClassLoader == NULL)
325+ {
326+ result->msg_id = MSG_ID_ERR_DEFINE_CLASS;
327+ sprintf(result->msg, _(MSG_ID_ERR_DEFINE_CLASS), "exewrap.core.ExewrapClassLoader");
328+ goto EXIT;
329+ }
330+ // register native methods
331+ if (register_native(env, ExewrapClassLoader, "WriteEventLog", "(ILjava/lang/String;)V", JNI_WriteEventLog) != 0)
332+ {
333+ result->msg_id = MSG_ID_ERR_REGISTER_NATIVE;
334+ sprintf(result->msg, _(MSG_ID_ERR_REGISTER_NATIVE), "WriteEventLog");
335+ goto EXIT;
336+ }
337+ if (register_native(env, ExewrapClassLoader, "UncaughtException", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", JNI_UncaughtException) != 0)
338+ {
339+ result->msg_id = MSG_ID_ERR_REGISTER_NATIVE;
340+ sprintf(result->msg, _(MSG_ID_ERR_REGISTER_NATIVE), "UncaughtException");
341+ goto EXIT;
342+ }
343+ // Create ExewrapClassLoader instance
344+ ExewrapClassLoader_init = (*env)->GetMethodID(env, ExewrapClassLoader, "<init>", "(Ljava/lang/ClassLoader;[Ljava/util/jar/JarInputStream;)V");
345+ if (ExewrapClassLoader_init == NULL)
346+ {
347+ result->msg_id = MSG_ID_ERR_GET_CONSTRUCTOR;
348+ sprintf(result->msg, _(MSG_ID_ERR_GET_CONSTRUCTOR), "exewrap.core.ExewrapClassLoader(java.lang.ClassLoader, java.util.jar.JarInputStream[])");
349+ goto EXIT;
350+ }
351+ // ExewrapClassLoader exewrarpClassLoader = new ExewrapClassLoader(ClassLoader.getSystemClasssLoader());
352+ exewrapClassLoader = (*env)->NewObject(env, ExewrapClassLoader, ExewrapClassLoader_init, systemClassLoader, jars);
353+ if (exewrapClassLoader == NULL)
354+ {
355+ result->msg_id = MSG_ID_ERR_NEW_OBJECT;
356+ sprintf(result->msg, _(MSG_ID_ERR_NEW_OBJECT), "exewrap.core.ExewrapClassLoader(java.lang.ClassLoader, java.util.jar.JarInputStream[])");
357+ goto EXIT;
358+ }
359+ exewrapClassLoader_registerSystemClassLoader = (*env)->GetMethodID(env, ExewrapClassLoader, "registerSystemClassLoader", "()V");
360+ if (exewrapClassLoader_registerSystemClassLoader == NULL)
361+ {
362+ result->msg_id = MSG_ID_ERR_GET_METHOD;
363+ sprintf(result->msg, _(MSG_ID_ERR_GET_METHOD), "exewrap.core.ExewrapClassLoader.registerSystemClassLoader()");
364+ goto EXIT;
365+ }
366+ exewrapClassLoader_loadUtilities = (*env)->GetMethodID(env, ExewrapClassLoader, "loadUtilities", "(Ljava/lang/String;)V");
367+ if (exewrapClassLoader_loadUtilities == NULL)
368+ {
369+ result->msg_id = MSG_ID_ERR_GET_METHOD;
370+ sprintf(result->msg, _(MSG_ID_ERR_GET_METHOD), "exewrap.core.ExewrapClassLoader.loadUtilities(java.lang.String)");
371+ goto EXIT;
372+ }
373+
374+ // exewrapClassLoader.registerSystemClassLoader();
375+ (*env)->CallObjectMethod(env, exewrapClassLoader, exewrapClassLoader_registerSystemClassLoader);
376+
377+ // exewrapClassLoader.loadUtilities();
378+ {
379+ jstring s = GetJString(env, utilities);
380+ (*env)->CallObjectMethod(env, exewrapClassLoader, exewrapClassLoader_loadUtilities, s);
381+ }
382+
383+ // MainClass
384+ exewrapClassLoader_getMainClass = (*env)->GetMethodID(env, ExewrapClassLoader, "getMainClass", "(Ljava/lang/String;)Ljava/lang/Class;");
385+ if (exewrapClassLoader_getMainClass == NULL)
386+ {
387+ result->msg_id = MSG_ID_ERR_GET_METHOD;
388+ sprintf(result->msg, _(MSG_ID_ERR_GET_METHOD), "exewrap.core.ExewrapClassLoader.getMainClass(java.lang.String)");
389+ goto EXIT;
390+ }
391+ MainClass = (*env)->CallObjectMethod(env, exewrapClassLoader, exewrapClassLoader_getMainClass, GetJString(env, GetResource("MAIN_CLASS", NULL)));
392+ if (MainClass == NULL)
393+ {
394+ result->msg_id = MSG_ID_ERR_LOAD_MAIN_CLASS;
395+ strcpy(result->msg, _(MSG_ID_ERR_LOAD_MAIN_CLASS));
396+ goto EXIT;
397+ }
398+ MainClass_main = (*env)->GetStaticMethodID(env, MainClass, "main", "([Ljava/lang/String;)V");
399+ if (MainClass_main == NULL)
400+ {
401+ result->msg_id = MSG_ID_ERR_FIND_MAIN_METHOD;
402+ strcpy(result->msg, _(MSG_ID_ERR_FIND_MAIN_METHOD));
403+ goto EXIT;
404+ }
405+ result->MainClass_main_args = (*env)->NewObjectArray(env, argc - 1, (*env)->FindClass(env, "java/lang/String"), NULL);
406+ {
407+ int i;
408+ for (i = 1; i < argc; i++)
409+ {
410+ (*env)->SetObjectArrayElement(env, result->MainClass_main_args, (i - 1), GetJString(env, argv[i]));
411+ }
412+ }
413+ result->MainClass = MainClass;
414+ result->MainClass_main = MainClass_main;
415+ result->msg_id = 0;
416+ *(result->msg) = '\0';
417+ return TRUE;
418+
419+EXIT:
420+
421+ return FALSE;
422+}
423+
424+
425+BOOL SetSplashScreenResource(char* splash_screen_name, BYTE* splash_screen_image_buf, DWORD splash_screen_image_len)
426+{
427+ BOOL ret = FALSE;
428+ jstring name;
429+ jbyteArray image;
430+ jmethodID exewrapClassLoader_setSplashScreenResource;
431+
432+ name = GetJString(env, splash_screen_name);
433+ if (name == NULL)
434+ {
435+ goto EXIT;
436+ }
437+
438+ image = (*env)->NewByteArray(env, splash_screen_image_len);
439+ if (image == NULL)
440+ {
441+ goto EXIT;
442+ }
443+ (*env)->SetByteArrayRegion(env, image, 0, splash_screen_image_len, splash_screen_image_buf);
444+
445+ exewrapClassLoader_setSplashScreenResource = (*env)->GetMethodID(env, ExewrapClassLoader, "setSplashScreenResource", "(Ljava/lang/String;[B)V");
446+ if (exewrapClassLoader_setSplashScreenResource == NULL)
447+ {
448+ goto EXIT;
449+ }
450+
451+ (*env)->CallVoidMethod(env, exewrapClassLoader, exewrapClassLoader_setSplashScreenResource, name, image);
452+
453+ ret = TRUE;
454+
455+EXIT:
456+ if ((*env)->ExceptionCheck(env) == JNI_TRUE)
457+ {
458+ (*env)->ExceptionDescribe(env);
459+ (*env)->ExceptionClear(env);
460+ ret = FALSE;
461+ }
462+ return ret;
463+}
464+
465+
466+DWORD WINAPI RemoteCallMainMethod(void* _shared_memory_handle)
467+{
468+ HANDLE shared_memory_handle = (HANDLE)_shared_memory_handle;
469+ char* arglist;
470+ char* buf;
471+ int argc;
472+ char** argv = NULL;
473+ int i;
474+ LPSTR shared_memory_read_event_name;
475+ HANDLE shared_memory_read_event_handle;
476+ LPBYTE lpShared = (LPBYTE)MapViewOfFile(shared_memory_handle, FILE_MAP_READ, 0, 0, 0);
477+ JNIEnv* env;
478+ jobjectArray args;
479+
480+ arglist = (char*)(lpShared + sizeof(DWORD) + sizeof(DWORD));
481+ buf = (char*)HeapAlloc(GetProcessHeap(), 0, lstrlen(arglist) + 1);
482+ lstrcpy(buf, (char*)arglist);
483+ UnmapViewOfFile(lpShared);
484+
485+ argv = split_args(buf, &argc);
486+ HeapFree(GetProcessHeap(), 0, buf);
487+
488+ env = AttachJavaVM();
489+ if (env != NULL)
490+ {
491+ args = (*env)->NewObjectArray(env, argc - 1, (*env)->FindClass(env, "java/lang/String"), NULL);
492+ for (i = 1; i < argc; i++)
493+ {
494+ (*env)->SetObjectArrayElement(env, args, (i - 1), GetJString(env, argv[i]));
495+ }
496+ }
497+
498+ shared_memory_read_event_name = GetModuleObjectName("SHARED_MEMORY_READ");
499+ shared_memory_read_event_handle = OpenEvent(EVENT_MODIFY_STATE, FALSE, shared_memory_read_event_name);
500+ if (shared_memory_read_event_handle != NULL)
501+ {
502+ SetEvent(shared_memory_read_event_handle);
503+ CloseHandle(shared_memory_read_event_handle);
504+ }
505+ HeapFree(GetProcessHeap(), 0, shared_memory_read_event_name);
506+
507+ if (env == NULL)
508+ {
509+ goto EXIT;
510+ }
511+
512+ (*env)->CallStaticVoidMethod(env, MainClass, MainClass_main, args);
513+ if ((*env)->ExceptionCheck(env) == JNI_TRUE)
514+ {
515+ print_stack_trace(NULL);
516+ }
517+ DetachJavaVM();
518+
519+EXIT:
520+ if (argv != NULL)
521+ {
522+ HeapFree(GetProcessHeap(), 0, argv);
523+ }
524+
525+ return 0;
526+}
527+
528+
529+char* ToString(JNIEnv* env, jobject object, char* buf)
530+{
531+ jclass Object;
532+ jmethodID Object_getClass;
533+ jclass object_class;
534+ jmethodID object_class_toString;
535+ jstring str;
536+ char* sjis;
537+
538+ if (object == NULL)
539+ {
540+ return NULL;
541+ }
542+ Object = (*env)->FindClass(env, "java/lang/Object");
543+ if (Object == NULL)
544+ {
545+ return NULL;
546+ }
547+ Object_getClass = (*env)->GetMethodID(env, Object, "getClass", "()Ljava/lang/Class;");
548+ if (Object_getClass == NULL)
549+ {
550+ return NULL;
551+ }
552+ object_class = (*env)->CallObjectMethod(env, object, Object_getClass);
553+ if (object_class == NULL)
554+ {
555+ return NULL;
556+ }
557+ object_class_toString = (*env)->GetMethodID(env, object_class, "toString", "()Ljava/lang/String;");
558+ if (object_class_toString == NULL)
559+ {
560+ return NULL;
561+ }
562+ str = (*env)->CallObjectMethod(env, object, object_class_toString);
563+ if (str == NULL)
564+ {
565+ return NULL;
566+ }
567+
568+ sjis = GetShiftJIS(env, str);
569+ if (buf != NULL)
570+ {
571+ strcpy(buf, sjis);
572+ HeapFree(GetProcessHeap(), 0, sjis);
573+ sjis = buf;
574+ }
575+
576+ return sjis;
577+}
578+
579+
580+char* GetModuleObjectName(const char* prefix)
581+{
582+ char* object_name = (char*)HeapAlloc(GetProcessHeap(), 0, MAX_PATH + 32);
583+ char* module_filename = (char*)malloc(MAX_PATH);
584+
585+ GetModuleFileName(NULL, module_filename, MAX_PATH);
586+ strcpy(object_name, "EXEWRAP:");
587+ if (prefix != NULL)
588+ {
589+ strcat(object_name, prefix);
590+ }
591+ strcat(object_name, ":");
592+ strcat(object_name, (char*)(strrchr(module_filename, '\\') + 1));
593+
594+ free(module_filename);
595+ return object_name;
596+}
597+
598+
599+BYTE* GetResource(LPCTSTR name, RESOURCE* resource)
600+{
601+ HRSRC hrsrc;
602+ BYTE* buf = NULL;
603+ DWORD len = 0;
604+
605+ if ((hrsrc = FindResource(NULL, name, RT_RCDATA)) != NULL)
606+ {
607+ buf = (BYTE*)LockResource(LoadResource(NULL, hrsrc));
608+ len = SizeofResource(NULL, hrsrc);
609+ }
610+ if (resource != NULL)
611+ {
612+ resource->buf = buf;
613+ resource->len = len;
614+ }
615+ return buf;
616+}
617+
618+
619+char* GetWinErrorMessage(DWORD err, int* exit_code, char* buf)
620+{
621+ LPVOID msg = NULL;
622+
623+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
624+ NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL);
625+
626+ if (buf == NULL)
627+ {
628+ buf = (char*)HeapAlloc(GetProcessHeap(), 0, strlen(msg) + 1);
629+ }
630+ strcpy(buf, msg);
631+ LocalFree(msg);
632+
633+ *exit_code = err;
634+
635+ return buf;
636+}
637+
638+
639+char* GetJniErrorMessage(int err, int* exit_code, char* buf)
640+{
641+ switch (err) {
642+ case JNI_OK:
643+ *exit_code = 0;
644+ sprintf(buf, "");
645+ return NULL;
646+ case JNI_ERR: /* unknown error */
647+ *exit_code = MSG_ID_ERR_CREATE_JVM_UNKNOWN;
648+ strcpy(buf, _(MSG_ID_ERR_CREATE_JVM_UNKNOWN));
649+ break;
650+ case JNI_EDETACHED: /* thread detached from the VM */
651+ *exit_code = MSG_ID_ERR_CREATE_JVM_EDETACHED;
652+ strcpy(buf, _(MSG_ID_ERR_CREATE_JVM_EDETACHED));
653+ break;
654+ case JNI_EVERSION: /* JNI version error */
655+ *exit_code = MSG_ID_ERR_CREATE_JVM_EVERSION;
656+ strcpy(buf, _(MSG_ID_ERR_CREATE_JVM_EVERSION));
657+ break;
658+ case JNI_ENOMEM: /* not enough memory */
659+ *exit_code = MSG_ID_ERR_CREATE_JVM_ENOMEM;
660+ strcpy(buf, _(MSG_ID_ERR_CREATE_JVM_ENOMEM));
661+ break;
662+ case JNI_EEXIST: /* VM already created */
663+ *exit_code = MSG_ID_ERR_CREATE_JVM_EEXIST;
664+ strcpy(buf, _(MSG_ID_ERR_CREATE_JVM_EEXIST));
665+ break;
666+ case JNI_EINVAL: /* invalid arguments */
667+ *exit_code = MSG_ID_ERR_CREATE_JVM_EINVAL;
668+ strcpy(buf, _(MSG_ID_ERR_CREATE_JVM_EINVAL));
669+ break;
670+ case JVM_ELOADLIB:
671+ *exit_code = MSG_ID_ERR_CREATE_JVM_ELOADLIB;
672+ sprintf(buf, _(MSG_ID_ERR_CREATE_JVM_ELOADLIB), GetProcessArchitecture());
673+ break;
674+ default:
675+ *exit_code = MSG_ID_ERR_CREATE_JVM_UNKNOWN;
676+ strcpy(buf, _(MSG_ID_ERR_CREATE_JVM_UNKNOWN));
677+ break;
678+ }
679+ return buf;
680+}
681+
682+
683+void JNICALL JNI_WriteEventLog(JNIEnv *env, jobject clazz, jint logType, jstring message)
684+{
685+ WORD nType;
686+ char* sjis;
687+
688+ switch (logType)
689+ {
690+ case 0: nType = EVENTLOG_INFORMATION_TYPE; break;
691+ case 1: nType = EVENTLOG_WARNING_TYPE; break;
692+ case 2: nType = EVENTLOG_ERROR_TYPE; break;
693+ default: nType = EVENTLOG_INFORMATION_TYPE;
694+ }
695+ sjis = GetShiftJIS(env, message);
696+ WriteEventLog(nType, sjis);
697+ HeapFree(GetProcessHeap(), 0, sjis);
698+}
699+
700+
701+void JNICALL JNI_UncaughtException(JNIEnv *env, jobject clazz, jstring thread, jstring message, jstring trace)
702+{
703+ char* sjis_thread;
704+ char* sjis_message;
705+ char* sjis_trace;
706+ UINT exit_code;
707+
708+ sjis_thread = GetShiftJIS(env, thread);
709+ sjis_message = GetShiftJIS(env, message);
710+ sjis_trace = GetShiftJIS(env, trace);
711+
712+ exit_code = UncaughtException(sjis_thread, sjis_message, sjis_trace);
713+
714+ if (sjis_thread != NULL)
715+ {
716+ HeapFree(GetProcessHeap(), 0, sjis_thread);
717+ }
718+ if (sjis_message != NULL)
719+ {
720+ HeapFree(GetProcessHeap(), 0, sjis_message);
721+ }
722+ if (sjis_trace != NULL)
723+ {
724+ HeapFree(GetProcessHeap(), 0, sjis_trace);
725+ }
726+
727+ ExitProcess(exit_code);
728+}
729+
730+
731+static jint register_native(JNIEnv* env, jclass cls, const char* name, const char* signature, void* fnPtr)
732+{
733+ JNINativeMethod nm;
734+
735+ nm.name = (char*)name;
736+ nm.signature = (char*)signature;
737+ nm.fnPtr = fnPtr;
738+
739+ return (*env)->RegisterNatives(env, cls, &nm, 1);
740+}
741+
742+static void print_stack_trace(const char* text)
743+{
744+ jclass Throwable;
745+ jthrowable throwable;
746+ jmethodID throwable_toString;
747+ jstring src;
748+ char* message;
749+
750+ if ((*env)->ExceptionCheck(env) != JNI_TRUE)
751+ {
752+ if (text != NULL)
753+ {
754+ OutputMessage(text);
755+ }
756+ goto EXIT;
757+ }
758+
759+ Throwable = (*env)->FindClass(env, "java/lang/Throwable");
760+
761+ throwable = (*env)->ExceptionOccurred(env);
762+ (*env)->ExceptionDescribe(env);
763+ (*env)->ExceptionClear(env);
764+
765+ throwable_toString = (*env)->GetMethodID(env, Throwable, "toString", "()Ljava/lang/String;");
766+
767+ src = (jstring)(*env)->CallObjectMethod(env, throwable, throwable_toString);
768+ message = GetShiftJIS(env, src);
769+
770+ if (text != NULL)
771+ {
772+ char* buf = (char*)malloc(8192);
773+ strcpy(buf, text);
774+ strcat(buf, "\r\n");
775+ strcat(buf, message);
776+ OutputMessage(buf);
777+ free(buf);
778+ }
779+ else
780+ {
781+ OutputMessage(message);
782+ }
783+
784+EXIT:
785+ if (message != NULL)
786+ {
787+ HeapFree(GetProcessHeap(), 0, message);
788+ }
789+}
790+
791+
792+static char** split_args(char* buffer, int* p_argc)
793+{
794+ int i;
795+ int buf_len = lstrlen(buffer);
796+ char** argv;
797+
798+ *p_argc = 0;
799+ for (i = 0; i < buf_len; i++) {
800+ *p_argc += (buffer[i] == '\n') ? 1 : 0;
801+ }
802+ argv = (char**)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (*p_argc) * sizeof(char*));
803+ for (i = 0; i < *p_argc; i++)
804+ {
805+ argv[i] = strtok(i ? NULL : buffer, "\n");
806+ }
807+ return argv;
808+}
--- exewrap/trunk/exewrap/src/notify.c (revision 19)
+++ exewrap/trunk/exewrap/src/notify.c (revision 20)
@@ -3,14 +3,15 @@
33 #include <stdio.h>
44
55 #include "include\notify.h"
6+#include "include\loader.h"
67
7-#define WM_APP_NOTIFY (WM_APP + 0x702)
8+#define WM_APP_NOTIFY (WM_APP + 0x702)
89
9-HANDLE g_event = NULL;
10+HANDLE NotifyExec(DWORD(WINAPI *start_address)(void*), int argc, char* argv[]);
11+void NotifyClose();
1012
11-static char* create_arglist(int argc, char* argv[]);
12-static DWORD WINAPI listener(void* arglist);
13-static char* GetModuleSharedMemoryName();
13+static char* create_arglist(int argc, char* argv[]);
14+static DWORD WINAPI listener(void* arglist);
1415
1516 static HANDLE shared_memory_handle = NULL;
1617 static HANDLE listener_thread_handle = NULL;
@@ -17,8 +18,10 @@
1718 static DWORD listener_thread_id = 0;
1819
1920 DWORD (WINAPI *p_callback_function)(void* x);
21+HANDLE g_event = NULL;
2022
21-HANDLE notify_exec(DWORD (WINAPI *_p_callback_function)(void*), int argc, char* argv[])
23+
24+HANDLE NotifyExec(DWORD (WINAPI *_p_callback_function)(void*), int argc, char* argv[])
2225 {
2326 DWORD dwReturn;
2427 int len = 2048;
@@ -69,8 +72,6 @@
6972 {
7073 p_callback_function = _p_callback_function;
7174 listener_thread_handle = (HANDLE)_beginthreadex(NULL, 0, listener, NULL, 0, &listener_thread_id);
72- //listener_thread_handle = CreateThread(NULL, 0, listener, NULL, 0, &listener_thread_id);
73- //_beginthread(listener, 0, NULL);
7475 }
7576 HeapFree(GetProcessHeap(), 0, synchronize_mutex_name);
7677
@@ -77,7 +78,8 @@
7778 return synchronize_mutex_handle;
7879 }
7980
80-void notify_close()
81+
82+void NotifyClose()
8183 {
8284 if(listener_thread_id != 0)
8385 {
@@ -101,6 +103,7 @@
101103 }
102104 }
103105
106+
104107 static char* create_arglist(int argc, char* argv[])
105108 {
106109 int size = 1;
@@ -120,6 +123,7 @@
120123 return buf;
121124 }
122125
126+
123127 static DWORD WINAPI listener(void* arglist)
124128 {
125129 BOOL b;
@@ -148,7 +152,6 @@
148152 DWORD threadId;
149153
150154 hThread = (HANDLE)_beginthreadex(NULL, 0, p_callback_function, shared_memory_handle, 0, &threadId);
151- //hThread = CreateThread(NULL, 0, p_callback_function, shared_memory_handle, 0, &threadId);
152155 CloseHandle(hThread);
153156 }
154157 }
@@ -155,21 +158,3 @@
155158
156159 return 0;
157160 }
158-
159-char* GetModuleObjectName(const char* prefix)
160-{
161- char* objectName = (char*)HeapAlloc(GetProcessHeap(), 0, MAX_PATH + 32);
162- char* moduleFileName = (char*)HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
163-
164- GetModuleFileName(NULL, moduleFileName, MAX_PATH);
165- lstrcpy(objectName, "EXEWRAP:");
166- if(prefix != NULL)
167- {
168- lstrcat(objectName, prefix);
169- }
170- lstrcat(objectName, ":");
171- lstrcat(objectName, (char*)(strrchr(moduleFileName, '\\') + 1));
172-
173- HeapFree(GetProcessHeap(), 0, moduleFileName);
174- return objectName;
175-}
Show on old repository browser