Develop and Download Open Source Software

Browse Subversion Repository

Contents of /exewrap/trunk/exewrap/src/jvm.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 101 - (show annotations) (download) (as text)
Mon Jul 18 02:19:21 2022 UTC (19 months, 4 weeks ago) by hirukawa_ryo
File MIME type: text/x-csrc
File size: 53176 byte(s)
* exewrap 1.6.5
Java 18 で UseSharedSpaces が非推奨になったため、UseSharedSpaces を指定しないように変更しました。
LICENSE.txt の文字コードを Shift_JIS から UTF-8 に変更しました。
1 /* このファイルの文字コードは Shift_JIS (MS932) です。*/
2
3 #include <windows.h>
4 #include <stdio.h>
5 #include <shlobj.h>
6 #include <jni.h>
7
8 #define JVM_ELOADLIB (+1)
9
10 #define VM_SEARCH_APPDIR (0x00000001)
11 #define VM_SEARCH_PARENTDIR (0x00000002)
12 #define VM_SEARCH_JAVAHOME (0x00000004)
13 #define VM_SEARCH_REGISTRY (0x00000008)
14 #define VM_SEARCH_PATHENV (0x00000010)
15 #define VM_SEARCH_JARASSOC (0x00000020)
16 #define VM_SEARCH_ALL (0xFFFFFFFF)
17
18 #define BUFFER_SIZE 32768
19 #define MAX_LONG_PATH 32768
20
21 int get_process_architecture(void);
22 int get_platform_architecture(void);
23 BOOL initialize_path(const wchar_t* relative_classpath, const wchar_t* relative_extdirs, BOOL use_server_vm, DWORD vm_search_locations);
24 JNIEnv* create_java_vm(const wchar_t* vm_args_opt, BOOL use_server_vm, DWORD vm_search_locations, BOOL* is_security_manager_required, int* error);
25 jint destroy_java_vm(void);
26 JNIEnv* attach_java_vm(void);
27 jint detach_java_vm(void);
28 BOOL set_application_properties(SYSTEMTIME* startup);
29 wchar_t* get_class_path(void);
30 void get_java_runtime_version(const wchar_t* version_string, DWORD* major, DWORD* minor, DWORD* build, DWORD* revision);
31 wchar_t* get_java_version_string(DWORD major, DWORD minor, DWORD build, DWORD revision);
32 wchar_t* get_module_version(wchar_t* buf, size_t size);
33
34 char* to_platform_encoding(const wchar_t* str);
35 char* to_utf8(const wchar_t* str);
36 wchar_t* from_utf8(const char* utf8);
37 jstring to_jstring(JNIEnv* env, const wchar_t* str);
38 wchar_t* from_jstring(JNIEnv* env, jstring jstr);
39
40 static BOOL find_java_vm(wchar_t* output, const wchar_t* jre, BOOL use_server_vm);
41 static wchar_t* find_java_home_from_registry(const wchar_t* _subkey, wchar_t* output);
42 static BOOL add_path_env(const wchar_t* path);
43 static void add_dll_directory(const wchar_t* path);
44 static BOOL is_directory(const wchar_t* path);
45 static wchar_t* get_sub_dirs(const wchar_t* dir);
46 static BOOL add_sub_dirs(wchar_t* buf, size_t buf_size, const wchar_t* dir, size_t* size);
47 static wchar_t* get_jars(const wchar_t* dir);
48 static BOOL add_jars(wchar_t* buf, size_t buf_size, const wchar_t* dir, size_t* size);
49 static int get_java_vm_bits(const wchar_t* jvmpath);
50 static wchar_t* urldecode(wchar_t *dst, size_t dst_size, const wchar_t *src);
51
52 typedef PVOID (WINAPI* Kernel32_AddDllDirectory)(PCWSTR);
53 typedef jint (WINAPI* JNIGetDefaultJavaVMInitArgs)(JavaVMInitArgs*);
54 typedef jint (WINAPI* JNICreateJavaVM)(JavaVM**, void**, JavaVMInitArgs*);
55
56 JavaVM* jvm = NULL;
57 JNIEnv* env = NULL;
58 BOOL is_add_dll_directory_supported = FALSE;
59 BOOL is_security_manager_required = FALSE;
60
61 static BOOL path_initialized = FALSE;
62 static wchar_t* binpath = NULL;
63 static wchar_t* jvmpath = NULL;
64 static wchar_t* libpath = NULL;
65
66 static HMODULE jvmdll = NULL;
67 static HMODULE kernel32 = NULL;
68 static Kernel32_AddDllDirectory _AddDllDirectory = NULL;
69
70
71 /* このプロセスのアーキテクチャ(32ビット/64ビット)を返します。
72 * 64ビットOSで32ビットプロセスを実行している場合、この関数は32を返します。
73 * 戻り値として32ビットなら 32 を返します。64ビットなら 64 を返します。
74 */
75 int get_process_architecture()
76 {
77 return sizeof(int*) * 8;
78 }
79
80
81 /* OSのアーキテクチャ(32ビット/64ビット)を返します。
82 * 64ビットOSで32ビットプロセスを実行している場合、この関数は64を返します。
83 * 戻り値として32ビットなら 32 を返します。64ビットなら 64 を返します。
84 */
85 int get_platform_architecture()
86 {
87 wchar_t buf[256];
88 if(GetEnvironmentVariable(L"PROCESSOR_ARCHITECTURE", buf, 256))
89 {
90 if(wcsstr(buf, L"64") != NULL)
91 {
92 return 64;
93 }
94 else if(GetEnvironmentVariable(L"PROCESSOR_ARCHITEW6432", buf, 256))
95 {
96 if(wcsstr(buf, L"64") != NULL)
97 {
98 return 64;
99 }
100 }
101 }
102 return 32;
103 }
104
105
106 JNIEnv* create_java_vm(const wchar_t* vm_args_opt, BOOL use_server_vm, DWORD vm_search_locations, BOOL* is_security_manager_required, int* error)
107 {
108 JNIGetDefaultJavaVMInitArgs GetDefaultJavaVMInitArgs;
109 JNICreateJavaVM CreateJavaVM;
110 JavaVMOption options[256];
111 JavaVMInitArgs vm_args;
112 char* char_buf = NULL;
113 wchar_t* wchar_buf = NULL;
114 int err = 0;
115
116 vm_args.version = JNI_VERSION_1_2;
117 vm_args.options = options;
118 vm_args.nOptions = 0;
119 vm_args.ignoreUnrecognized = 1;
120
121 if(!path_initialized)
122 {
123 initialize_path(NULL, L"lib", use_server_vm, vm_search_locations);
124 }
125
126 if(jvmdll == NULL)
127 {
128 if(_AddDllDirectory != NULL)
129 {
130 jvmdll = LoadLibraryEx(L"jvm.dll", NULL, 0x00001000); // LOAD_LIBRARY_SEARCH_DEFAULT_DIRS (0x00001000)
131 }
132 else
133 {
134 // Windows XP以前はAddDllDirectory関数がなくDLL参照ディレクトリを細かく制御することができません。
135 // Windows XP以前ではPATH環境変数からもDLLを参照できるように従来のライブラリ参照方法を使用します。
136 jvmdll = LoadLibrary(L"jvm.dll");
137 }
138 if(jvmdll == NULL)
139 {
140 err = JVM_ELOADLIB;
141 goto EXIT;
142 }
143 }
144
145 GetDefaultJavaVMInitArgs = (JNIGetDefaultJavaVMInitArgs)GetProcAddress(jvmdll, "JNI_GetDefaultJavaVMInitArgs");
146 CreateJavaVM = (JNICreateJavaVM)GetProcAddress(jvmdll, "JNI_CreateJavaVM");
147
148 char_buf = (char*)malloc(BUFFER_SIZE * 2);
149 if(char_buf == NULL)
150 {
151 err = JNI_ENOMEM;
152 goto EXIT;
153 }
154 wchar_buf = (wchar_t*)malloc(BUFFER_SIZE * sizeof(wchar_t));
155 if(wchar_buf == NULL)
156 {
157 err = JNI_ENOMEM;
158 goto EXIT;
159 }
160
161 if(GetModuleFileName(NULL, wchar_buf, BUFFER_SIZE) != 0)
162 {
163 char* str;
164 size_t len;
165
166 str = to_platform_encoding(wchar_buf);
167 strcpy_s(char_buf, BUFFER_SIZE * 2, "-Djava.class.path=");
168 strcat_s(char_buf, BUFFER_SIZE * 2, str);
169 free(str);
170
171 len = strlen(char_buf);
172 str = (char*)malloc(len + 1);
173 if(str == NULL)
174 {
175 err = JNI_ENOMEM;
176 goto EXIT;
177 }
178 strcpy_s(str, len + 1, char_buf);
179 options[vm_args.nOptions++].optionString = str;
180 }
181
182 if(libpath != NULL)
183 {
184 char* str;
185 size_t len;
186
187 str = to_platform_encoding(libpath);
188 strcpy_s(char_buf, BUFFER_SIZE * 2, "-Djava.library.path=");
189 strcat_s(char_buf, BUFFER_SIZE * 2, str);
190 free(str);
191
192 len = strlen(char_buf);
193 str = (char*)malloc(len + 1);
194 if(str == NULL)
195 {
196 err = JNI_ENOMEM;
197 goto EXIT;
198 }
199 strcpy_s(str, len + 1, char_buf);
200 options[vm_args.nOptions++].optionString = str;
201 }
202
203 if(strcpy_s(char_buf, BUFFER_SIZE * 2, "-Djava.system.class.loader=Loader") == 0)
204 {
205 char* str;
206 size_t len;
207
208 len = strlen(char_buf);
209 str = (char*)malloc(len + 1);
210 if(str == NULL)
211 {
212 err = JNI_ENOMEM;
213 goto EXIT;
214 }
215 strcpy_s(str, len + 1, char_buf);
216 options[vm_args.nOptions++].optionString = str;
217 }
218
219 if(GetModuleFileName(NULL, wchar_buf, BUFFER_SIZE) != 0)
220 {
221 wchar_t* p = wcsrchr(wchar_buf, L'\\');
222 wchar_t* app_path = wchar_buf;
223 wchar_t* app_name = p + 1;
224 char* str;
225 size_t len;
226
227 *p = L'\0';
228
229 str = to_platform_encoding(app_path);
230 strcpy_s(char_buf, BUFFER_SIZE * 2, "-Djava.application.path=");
231 strcat_s(char_buf, BUFFER_SIZE * 2, str);
232 free(str);
233
234 len = strlen(char_buf);
235 str = (char*)malloc(len + 1);
236 if(str == NULL)
237 {
238 err = JNI_ENOMEM;
239 goto EXIT;
240 }
241 strcpy_s(str, len + 1, char_buf);
242 options[vm_args.nOptions++].optionString = str;
243
244 str = to_platform_encoding(app_name);
245 strcpy_s(char_buf, BUFFER_SIZE * 2, "-Djava.application.name=");
246 strcat_s(char_buf, BUFFER_SIZE * 2, str);
247 free(str);
248
249 len = strlen(char_buf);
250 str = (char*)malloc(len + 1);
251 if(str == NULL)
252 {
253 err = JNI_ENOMEM;
254 goto EXIT;
255 }
256 strcpy_s(str, len + 1, char_buf);
257 options[vm_args.nOptions++].optionString = str;
258 }
259
260 if(GetModuleFileName(NULL, wchar_buf, BUFFER_SIZE) != 0)
261 {
262 wchar_t* policy_file = wchar_buf;
263 wchar_t* p;
264
265 if((p = wcsrchr(policy_file, L'.')) != NULL)
266 {
267 *p = L'\0';
268 wcscat_s(policy_file, BUFFER_SIZE, L".policy");
269 if(GetFileAttributes(policy_file) != INVALID_FILE_ATTRIBUTES)
270 {
271 char* str;
272 size_t len;
273
274 // -Djava.security.manager でセキュリティマネージャーをインストールすると、
275 // CreateJavaVM 関数を呼び出したときに Loader クラスを見つけられなくなります。(ClassNotFoundException)
276 // この問題を回避するために -Djava.security.manager を指定せずにJavaVM作成後にコードによってセキュリティマネージャーをインストールします。
277 // is_security_manager_required はセキュリティマネージャーのインストールが必要であることを示すフラグです。
278 if(is_security_manager_required != NULL)
279 {
280 *is_security_manager_required = TRUE;
281 }
282
283 str = to_platform_encoding(policy_file);
284 strcpy_s(char_buf, BUFFER_SIZE * 2, "-Djava.security.policy=");
285 strcat_s(char_buf, BUFFER_SIZE * 2, str);
286 free(str);
287
288 len = strlen(char_buf);
289 str = (char*)malloc(len + 1);
290 if(str == NULL)
291 {
292 err = JNI_ENOMEM;
293 goto EXIT;
294 }
295 strcpy_s(str, len + 1, char_buf);
296 options[vm_args.nOptions++].optionString = str;
297 }
298 }
299 }
300
301 if(vm_args_opt != NULL)
302 {
303 int argc = 0;
304 wchar_t** argv = NULL;
305
306 argv = CommandLineToArgvW(vm_args_opt, &argc);
307 if(argv != NULL && argc > 0)
308 {
309 int i;
310 for(i = 0; i < argc; i++)
311 {
312 char* opt = to_platform_encoding(argv[i]);
313 options[vm_args.nOptions++].optionString = opt;
314 }
315 }
316 LocalFree(argv);
317 }
318
319 //read .exe.vmoptions
320 //同じVM引数が複数回指定された場合は後優先になるので、.exe.vmoptionsを優先するために最後に追加します。
321 //.exe.vmoptions の文字コードはプラットフォームエンコーディングである必要があります。
322 //.exe.vmoptions は32KB以下である必要があります。
323 if(GetModuleFileName(NULL, wchar_buf, BUFFER_SIZE) != 0)
324 {
325 wchar_t* vm_opt_file = wchar_buf;
326
327 wcscat_s(vm_opt_file, MAX_LONG_PATH, L".vmoptions");
328 if(GetFileAttributes(vm_opt_file) != INVALID_FILE_ATTRIBUTES)
329 {
330 HANDLE hFile = CreateFile(vm_opt_file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
331 if(hFile != INVALID_HANDLE_VALUE)
332 {
333 char* ptr = char_buf;
334 DWORD size = BUFFER_SIZE * 2;
335 DWORD read_size;
336
337 while(size > 0)
338 {
339 BOOL ret = ReadFile(hFile, ptr, size, &read_size, NULL);
340 if(ret == FALSE) // ERROR
341 {
342 break;
343 }
344 if(read_size == 0) // END OF FILE
345 {
346 ptr = NULL;
347 break;
348 }
349 ptr += read_size;
350 size -= read_size;
351 }
352 if(ptr == NULL) // READ SUCCESSFUL
353 {
354 size_t line_len;
355 char* line = ptr = char_buf;
356 while(*ptr != '\0')
357 {
358 if(*ptr == '\r' || *ptr == '\n')
359 {
360 *ptr = '\0';
361 line_len = strlen(line);
362 if(line_len > 0)
363 {
364 char* str = malloc(line_len + 1);
365 if(str == NULL)
366 {
367 CloseHandle(hFile);
368 err = JNI_ENOMEM;
369 goto EXIT;
370 }
371 strcpy_s(str, line_len + 1, line);
372 options[vm_args.nOptions++].optionString = str;
373 }
374 line = ptr + 1;
375 }
376 ptr++;
377 }
378 }
379 CloseHandle(hFile);
380 }
381 }
382 }
383
384 /*
385 // FIXME: debug
386 {
387 int i;
388 for(i = 0; i < vm_args.nOptions; i++)
389 {
390 printf("[%d] %s\n\n", i, options[i].optionString);
391 }
392 }
393 */
394
395 GetDefaultJavaVMInitArgs(&vm_args);
396 err = CreateJavaVM(&jvm, (void**)&env, &vm_args);
397
398 EXIT:
399 if(err != JNI_OK)
400 {
401 jvm = NULL;
402 env = NULL;
403 }
404 if(wchar_buf != NULL)
405 {
406 free(wchar_buf);
407 }
408 if(char_buf != NULL)
409 {
410 free(char_buf);
411 }
412
413 while(vm_args.nOptions > 0)
414 {
415 free(options[vm_args.nOptions - 1].optionString);
416 vm_args.nOptions--;
417 }
418
419 if(error != NULL)
420 {
421 *error = err;
422 }
423 return env;
424 }
425
426
427 jint destroy_java_vm()
428 {
429 jint ret = JNI_ERR;
430
431 if(jvm != NULL)
432 {
433 ret = (*jvm)->DestroyJavaVM(jvm);
434 jvm = NULL;
435 }
436
437 if(libpath != NULL)
438 {
439 free(libpath);
440 libpath = NULL;
441 }
442
443 return ret;
444 }
445
446
447 JNIEnv* attach_java_vm()
448 {
449 JNIEnv* env = NULL;
450
451 if(jvm != NULL)
452 {
453 if((*jvm)->AttachCurrentThread(jvm, (void**)&env, NULL) != JNI_OK)
454 {
455 env = NULL;
456 }
457 }
458
459 return env;
460 }
461
462
463 jint detach_java_vm()
464 {
465 jint ret = JNI_ERR;
466
467 if(jvm != NULL)
468 {
469 ret = (*jvm)->DetachCurrentThread(jvm);
470 }
471
472 return ret;
473 }
474
475
476 void get_java_runtime_version(const wchar_t* version_string, DWORD* major, DWORD* minor, DWORD* build, DWORD* revision)
477 {
478 wchar_t* buffer = NULL;
479 wchar_t* version = NULL;
480
481 if(major != NULL)
482 {
483 *major = 0;
484 }
485 if(minor != NULL)
486 {
487 *minor = 0;
488 }
489 if(build != NULL)
490 {
491 *build = 0;
492 }
493 if(revision != NULL)
494 {
495 *revision = 0;
496 }
497
498 if(version_string == NULL)
499 {
500 jclass System;
501 jmethodID System_getProperty;
502
503 System = (*env)->FindClass(env, "java/lang/System");
504 if(System != NULL)
505 {
506 System_getProperty = (*env)->GetStaticMethodID(env, System, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;");
507 if(System_getProperty != NULL)
508 {
509 jstring param = to_jstring(env, L"java.runtime.version");
510 jstring ret = (jstring)((*env)->CallStaticObjectMethod(env, System, System_getProperty, param));
511 version = buffer = from_jstring(env, ret);
512 }
513 }
514 }
515 else
516 {
517 size_t len = wcslen(version_string);
518 buffer = (wchar_t*)malloc((len + 1) * sizeof(wchar_t));
519 if(buffer == NULL)
520 {
521 goto EXIT;
522 }
523 wcscpy_s(buffer, len + 1, version_string);
524 version = buffer;
525 }
526
527
528 //数字が出てくるまでスキップ
529 while(*version != L'\0' && !(L'0' <= *version && *version <= L'9'))
530 {
531 version++;
532 }
533 if(*version == L'\0')
534 {
535 goto EXIT;
536 }
537 if(major != NULL)
538 {
539 *major = _wtoi(version);
540 }
541
542 //数字以外が出てくるまでスキップ
543 while(*version != L'\0' && (L'0' <= *version && *version <= L'9'))
544 {
545 version++;
546 }
547 if(*version == L'\0')
548 {
549 goto EXIT;
550 }
551 //数字が出てくるまでスキップ
552 while(*version != L'\0' && !(L'0' <= *version && *version <= L'9'))
553 {
554 version++;
555 }
556 if(*version == L'\0')
557 {
558 goto EXIT;
559 }
560 if(minor != NULL)
561 {
562 *minor = _wtoi(version);
563 }
564
565 //数字以外が出てくるまでスキップ
566 while(*version != L'\0' && (L'0' <= *version && *version <= L'9'))
567 {
568 version++;
569 }
570 if(*version == L'\0')
571 {
572 goto EXIT;
573 }
574 //数字が出てくるまでスキップ
575 while(*version != L'\0' && !(L'0' <= *version && *version <= L'9'))
576 {
577 version++;
578 }
579 if(*version == L'\0')
580 {
581 goto EXIT;
582 }
583 if(build != NULL)
584 {
585 *build = _wtoi(version);
586 }
587
588 //数字以外が出てくるまでスキップ
589 while(*version != L'\0' && (L'0' <= *version && *version <= L'9'))
590 {
591 version++;
592 }
593 if(*version == L'\0')
594 {
595 goto EXIT;
596 }
597 //数字が出てくるまでスキップ
598 while(*version != L'\0' && !(L'0' <= *version && *version <= L'9'))
599 {
600 version++;
601 }
602 if(*version == L'\0')
603 {
604 goto EXIT;
605 }
606 if(revision != NULL)
607 {
608 *revision = _wtoi(version);
609 }
610
611 EXIT:
612 if(buffer != NULL)
613 {
614 free(buffer);
615 }
616 }
617
618
619 wchar_t* get_java_version_string(DWORD major, DWORD minor, DWORD build, DWORD revision)
620 {
621 int len = 128;
622 wchar_t* buf = (wchar_t*)malloc(128 * sizeof(wchar_t));
623
624 if(buf == NULL)
625 {
626 return NULL;
627 }
628
629 //JDK9-
630 if(major >= 5)
631 {
632 if(minor == 0 && build == 0 && revision == 0)
633 {
634 swprintf_s(buf, len, L"Java %d", major);
635 }
636 else if(build == 0 && revision == 0)
637 {
638 swprintf_s(buf, len, L"Java %d.%d", major, minor);
639 }
640 else if(revision == 0)
641 {
642 swprintf_s(buf, len, L"Java %d.%d.%d", major, minor, build);
643 }
644 else
645 {
646 swprintf_s(buf, len, L"Java %d.%d.%d", major, minor, build, revision);
647 }
648 return buf;
649 }
650
651 //1.7, 1.8
652 if(major == 1 && (minor == 7 || minor == 8))
653 {
654 if(build == 0 )
655 {
656 if(revision == 0)
657 {
658 swprintf_s(buf, len, L"Java %d", minor);
659 }
660 else
661 {
662 swprintf_s(buf, len, L"Java %du%d", minor, revision);
663 }
664 }
665 else
666 {
667 swprintf_s(buf, len, L"Java %d.%d.%d.%d", major, minor, build, revision);
668 }
669 return buf;
670 }
671
672 //1.5, 1.6
673 if(major == 1 && (minor == 5 || minor == 6))
674 {
675 if(build == 0)
676 {
677 if(revision == 0)
678 {
679 swprintf_s(buf, len, L"Java %d.%d", minor, build);
680 }
681 else
682 {
683 swprintf_s(buf, len, L"Java %d.%d.%d", minor, build, revision);
684 }
685 }
686 else
687 {
688 swprintf_s(buf, len, L"Java %d.%d.%d.%d", major, minor, build, revision);
689 }
690 return buf;
691 }
692
693 //1.2, 1.3, 1.4
694 if(major == 1 && (minor == 2 || minor == 3 || minor == 4))
695 {
696 if(revision == 0)
697 {
698 if(build == 0)
699 {
700 swprintf_s(buf, len, L"Java2 %d.%d", major, minor);
701 }
702 else
703 {
704 swprintf_s(buf, len, L"Java2 %d.%d.%d", major, minor, build);
705 }
706 }
707 else
708 {
709 swprintf_s(buf, len, L"Java2 %d.%d.%d.%d", major, minor, build, revision);
710 }
711 return buf;
712 }
713
714 //1.0, 1.1
715 if(major == 1 && (minor == 0 || minor == 1))
716 {
717 if(revision == 0)
718 {
719 if(build == 0)
720 {
721 swprintf_s(buf, len, L"Java %d.%d", major, minor);
722 }
723 else
724 {
725 swprintf_s(buf, len, L"Java %d.%d.%d", major, minor, build);
726 }
727 }
728 else
729 {
730 swprintf_s(buf, len, L"Java %d.%d.%d.%d", major, minor, build, revision);
731 }
732 return buf;
733 }
734
735 //other
736 if(revision == 0)
737 {
738 swprintf_s(buf, len, L"Java %d.%d.%d", major, minor, build);
739 }
740 else
741 {
742 swprintf_s(buf, len, L"Java %d.%d.%d.%d", major, minor, build, revision);
743 }
744 return buf;
745 }
746
747
748 BOOL set_application_properties(SYSTEMTIME* startup)
749 {
750 BOOL succeeded = FALSE;
751 wchar_t* buffer = NULL;
752 jclass System;
753 jmethodID System_setProperty;
754 jstring key;
755 jstring value;
756
757 if(env == NULL)
758 {
759 goto EXIT;
760 }
761 buffer = (wchar_t*)malloc(BUFFER_SIZE * sizeof(wchar_t));
762 if(buffer == NULL)
763 {
764 goto EXIT;
765 }
766 System = (*env)->FindClass(env, "java/lang/System");
767 if(System == NULL)
768 {
769 goto EXIT;
770 }
771 System_setProperty = (*env)->GetStaticMethodID(env, System, "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
772 if(System_setProperty == NULL)
773 {
774 goto EXIT;
775 }
776
777 if(startup != NULL)
778 {
779 swprintf_s(buffer, BUFFER_SIZE, L"%u-%02u-%02uT%02u:%02u:%02u.%03uZ",
780 startup->wYear, startup->wMonth, startup->wDay,
781 startup->wHour, startup->wMinute, startup->wSecond,
782 startup->wMilliseconds);
783 key = to_jstring(env, L"java.application.startup");
784 value = to_jstring(env, buffer);
785 (*env)->CallStaticObjectMethod(env, System, System_setProperty, key, value);
786 }
787
788 // Loaderクラスのコンストラクタ内で実行ファイルのパスを参照する必要があるため、
789 // java.application.path と java.application.name は create_java_vm ないで起動時パラメーターとして指定します。
790 /*
791 if(GetModuleFileName(NULL, buffer, BUFFER_SIZE) != 0)
792 {
793 wchar_t* p = wcsrchr(buffer, L'\\');
794 wchar_t* app_path = buffer;
795 wchar_t* app_name = p + 1;
796
797 *p = L'\0';
798
799 key = to_jstring(env, L"java.application.path");
800 value = to_jstring(env, app_path);
801 (*env)->CallStaticObjectMethod(env, System, System_setProperty, key, value);
802
803 key = to_jstring(env, L"java.application.name");
804 value = to_jstring(env, app_name);
805 (*env)->CallStaticObjectMethod(env, System, System_setProperty, key, value);
806 }
807 */
808
809 if(get_module_version(buffer, BUFFER_SIZE) != NULL)
810 {
811 key = to_jstring(env, L"java.application.version");
812 value = to_jstring(env, buffer);
813 (*env)->CallStaticObjectMethod(env, System, System_setProperty, key, value);
814 }
815
816 succeeded = TRUE;
817
818 EXIT:
819 if(buffer != NULL)
820 {
821 free(buffer);
822 }
823 return succeeded;
824 }
825
826
827 BOOL initialize_path(const wchar_t* relative_classpath, const wchar_t* relative_extdirs, BOOL use_server_vm, DWORD vm_search_locations)
828 {
829 wchar_t* path_env = NULL;
830 wchar_t* module_path = NULL;
831 wchar_t* buffer = NULL;
832 wchar_t* search = NULL;
833 wchar_t* jdk = NULL;
834 WIN32_FIND_DATA fd;
835 HANDLE hSearch;
836 BOOL found = FALSE;
837 wchar_t* token;
838 wchar_t* context;
839
840 path_initialized = FALSE;
841
842 if(kernel32 == NULL)
843 {
844 kernel32 = LoadLibrary(L"kernel32");
845 }
846 if(kernel32 != NULL && _AddDllDirectory == NULL)
847 {
848 _AddDllDirectory = (Kernel32_AddDllDirectory)GetProcAddress(kernel32, "AddDllDirectory");
849 if(_AddDllDirectory != NULL)
850 {
851 is_add_dll_directory_supported = TRUE;
852 }
853 }
854
855 if(binpath == NULL)
856 {
857 binpath = (wchar_t*)malloc(MAX_LONG_PATH * sizeof(wchar_t));
858 if(binpath == NULL)
859 {
860 goto EXIT;
861 }
862 }
863 if(jvmpath == NULL)
864 {
865 jvmpath = (wchar_t*)malloc(MAX_LONG_PATH * sizeof(wchar_t));
866 if(jvmpath == NULL)
867 {
868 goto EXIT;
869 }
870 }
871 if(libpath == NULL)
872 {
873 libpath = (wchar_t*)malloc(BUFFER_SIZE * sizeof(wchar_t));
874 if(libpath == NULL)
875 {
876 goto EXIT;
877 }
878 }
879
880
881 buffer = (wchar_t*)malloc(BUFFER_SIZE * sizeof(wchar_t));
882 if(buffer == NULL)
883 {
884 goto EXIT;
885 }
886 search = (wchar_t*)malloc(MAX_LONG_PATH * sizeof(wchar_t));
887 if(search == NULL)
888 {
889 goto EXIT;
890 }
891 jdk = (wchar_t*)malloc(MAX_LONG_PATH * sizeof(wchar_t));
892 if(jdk == NULL)
893 {
894 goto EXIT;
895 }
896
897 module_path = (wchar_t*)malloc(MAX_LONG_PATH * sizeof(wchar_t));
898 if(module_path == NULL)
899 {
900 goto EXIT;
901 }
902 if(GetModuleFileName(NULL, module_path, MAX_LONG_PATH) == 0)
903 {
904 goto EXIT;
905 }
906 *(wcsrchr(module_path, L'\\')) = L'\0';
907
908 path_env = (wchar_t*)malloc(BUFFER_SIZE * sizeof(wchar_t));
909 if(path_env == NULL)
910 {
911 goto EXIT;
912 }
913 GetEnvironmentVariable(L"PATH", path_env, BUFFER_SIZE);
914
915 jvmpath[0] = L'\0';
916
917 // Find local JDK
918 if((vm_search_locations & VM_SEARCH_APPDIR) && jvmpath[0] == L'\0')
919 {
920 wcscpy_s(buffer, BUFFER_SIZE, module_path);
921 wcscpy_s(search, MAX_LONG_PATH, buffer);
922 wcscat_s(search, MAX_LONG_PATH, L"\\jdk*");
923 hSearch = FindFirstFile(search, &fd);
924 if(hSearch != INVALID_HANDLE_VALUE)
925 {
926 found = FALSE;
927 do
928 {
929 if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
930 {
931 wcscat_s(buffer, BUFFER_SIZE, L"\\");
932 wcscat_s(buffer, BUFFER_SIZE, fd.cFileName);
933 found = TRUE;
934 }
935 } while (!found && FindNextFile(hSearch, &fd));
936 FindClose(hSearch);
937 if(found)
938 {
939 //JDK9以降、jvm.dllの場所が変更になりました。
940 //JDK8までは jdk-8u152/jre/bin/server/jvm.dll のようにjdkの中にjreがありましたが、
941 //JDK9以降は jdk-9/bin/server/jvm.dll のようにjreフォルダなしで直接binが配置されるようになりました。
942 //そのため、jdk に bin/server/jvm.dll があるか探してなければ従来通り、jre/bin/server/jvm.dll を探します。
943 if(find_java_vm(jvmpath, buffer, use_server_vm))
944 {
945 int bits = get_java_vm_bits(jvmpath);
946 if(bits == get_process_architecture())
947 {
948 if(buffer[wcslen(buffer) - 1] != L'\\')
949 {
950 wcscat_s(buffer, BUFFER_SIZE, L"\\");
951 }
952 SetEnvironmentVariable(L"JAVA_HOME", buffer);
953 wcscpy_s(binpath, MAX_LONG_PATH, buffer);
954 wcscat_s(binpath, MAX_LONG_PATH, L"bin");
955 }
956 else
957 {
958 jvmpath[0] = L'\0';
959 }
960 }
961 else
962 {
963 //jdk直下には bin/server/jvm.dll がなかったので、jre を連結して、
964 //jre/bin/server/jvm.dll を探します。
965 wcscpy_s(jdk, MAX_LONG_PATH, buffer);
966 wcscat_s(buffer, BUFFER_SIZE, L"\\jre");
967 if(find_java_vm(jvmpath, buffer, use_server_vm))
968 {
969 int bits = get_java_vm_bits(jvmpath);
970 if(bits == get_process_architecture())
971 {
972 //jdk/jreが見つかってもJAVA_HOMEに設定するのはjdkディレクトリです。
973 if(jdk[wcslen(jdk) - 1] != L'\\')
974 {
975 wcscat_s(jdk, MAX_LONG_PATH, L"\\");
976 }
977 SetEnvironmentVariable(L"JAVA_HOME", jdk);
978 wcscpy_s(binpath, MAX_LONG_PATH, jdk);
979 wcscat_s(binpath, MAX_LONG_PATH, L"bin");
980 }
981 else
982 {
983 jvmpath[0] = L'\0';
984 }
985 }
986 }
987 }
988 }
989 }
990
991 // Find local JRE
992 if((vm_search_locations & VM_SEARCH_APPDIR) && jvmpath[0] == L'\0')
993 {
994 wcscpy_s(buffer, BUFFER_SIZE, module_path);
995 wcscpy_s(search, MAX_LONG_PATH, buffer);
996 wcscat_s(search, MAX_LONG_PATH, L"\\jre*");
997 hSearch = FindFirstFile(search, &fd);
998 if(hSearch != INVALID_HANDLE_VALUE)
999 {
1000 found = FALSE;
1001 do
1002 {
1003 if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1004 {
1005 wcscat_s(buffer, BUFFER_SIZE, L"\\");
1006 wcscat_s(buffer, BUFFER_SIZE, fd.cFileName);
1007 found = TRUE;
1008 }
1009 } while (!found && FindNextFile(hSearch, &fd));
1010 FindClose(hSearch);
1011 if(found)
1012 {
1013 if(find_java_vm(jvmpath, buffer, use_server_vm))
1014 {
1015 int bits = get_java_vm_bits(jvmpath);
1016 if(bits == get_process_architecture())
1017 {
1018 if(buffer[wcslen(buffer) - 1] != L'\\')
1019 {
1020 wcscat_s(buffer, BUFFER_SIZE, L"\\");
1021 }
1022 SetEnvironmentVariable(L"JAVA_HOME", buffer);
1023 wcscpy_s(binpath, MAX_LONG_PATH, buffer);
1024 wcscat_s(binpath, MAX_LONG_PATH, L"bin");
1025 }
1026 else
1027 {
1028 jvmpath[0] = L'\0';
1029 }
1030 }
1031 }
1032 }
1033 }
1034
1035 // Find local JDK (from parent folder)
1036 if((vm_search_locations & VM_SEARCH_PARENTDIR) && jvmpath[0] == L'\0')
1037 {
1038 wcscpy_s(buffer, BUFFER_SIZE, module_path);
1039 wcscpy_s(search, MAX_LONG_PATH, buffer);
1040 wcscat_s(search, MAX_LONG_PATH, L"\\..\\jdk*");
1041 hSearch = FindFirstFile(search, &fd);
1042 if(hSearch != INVALID_HANDLE_VALUE)
1043 {
1044 found = FALSE;
1045 do
1046 {
1047 if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1048 {
1049 wcscat_s(buffer, BUFFER_SIZE, L"\\..\\");
1050 wcscat_s(buffer, BUFFER_SIZE, fd.cFileName);
1051 found = TRUE;
1052 }
1053 } while (!found && FindNextFile(hSearch, &fd));
1054 FindClose(hSearch);
1055 if(found)
1056 {
1057 if(find_java_vm(jvmpath, buffer, use_server_vm))
1058 {
1059 int bits = get_java_vm_bits(jvmpath);
1060 if(bits == get_process_architecture())
1061 {
1062 if(buffer[wcslen(buffer) - 1] != L'\\')
1063 {
1064 wcscat_s(buffer, BUFFER_SIZE, L"\\");
1065 }
1066 SetEnvironmentVariable(L"JAVA_HOME", buffer);
1067 wcscpy_s(binpath, MAX_LONG_PATH, buffer);
1068 wcscat_s(binpath, MAX_LONG_PATH, L"bin");
1069 }
1070 else
1071 {
1072 jvmpath[0] = L'\0';
1073 }
1074 }
1075 }
1076 }
1077 }
1078
1079 // Find local JRE (from parent folder)
1080 if((vm_search_locations & VM_SEARCH_PARENTDIR) && jvmpath[0] == L'\0')
1081 {
1082 wcscpy_s(buffer, BUFFER_SIZE, module_path);
1083 wcscpy_s(search, MAX_LONG_PATH, buffer);
1084 wcscat_s(search, MAX_LONG_PATH, L"\\..\\jre*");
1085 hSearch = FindFirstFile(search, &fd);
1086 if(hSearch != INVALID_HANDLE_VALUE)
1087 {
1088 found = FALSE;
1089 do
1090 {
1091 if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1092 {
1093 wcscat_s(buffer, BUFFER_SIZE, L"\\..\\");
1094 wcscat_s(buffer, BUFFER_SIZE, fd.cFileName);
1095 found = TRUE;
1096 }
1097 } while (!found && FindNextFile(hSearch, &fd));
1098 FindClose(hSearch);
1099 if(found)
1100 {
1101 if(find_java_vm(jvmpath, buffer, use_server_vm))
1102 {
1103 int bits = get_java_vm_bits(jvmpath);
1104 if(bits == get_process_architecture())
1105 {
1106 if(buffer[wcslen(buffer) - 1] != L'\\')
1107 {
1108 wcscat_s(buffer, BUFFER_SIZE, L"\\");
1109 }
1110 SetEnvironmentVariable(L"JAVA_HOME", buffer);
1111 wcscpy_s(binpath, MAX_LONG_PATH, buffer);
1112 wcscat_s(binpath, MAX_LONG_PATH, L"bin");
1113 }
1114 else
1115 {
1116 jvmpath[0] = L'\0';
1117 }
1118 }
1119 }
1120 }
1121 }
1122
1123 // Find JDK/JRE from JAVA_HOME
1124 if((vm_search_locations & VM_SEARCH_JAVAHOME) && jvmpath[0] == L'\0')
1125 {
1126 buffer[0] = L'\0';
1127 if(GetEnvironmentVariable(L"JAVA_HOME", buffer, MAX_LONG_PATH) > 0)
1128 {
1129 // 下位に jre フォルダーがあるか確認します。
1130 if(buffer[wcslen(buffer) - 1] == L'\\')
1131 {
1132 wcscat_s(buffer, BUFFER_SIZE, L"jre");
1133 }
1134 else
1135 {
1136 wcscat_s(buffer, BUFFER_SIZE, L"\\jre");
1137 }
1138 // 下位に jre フォルダーがなければ元のフォルダーに戻します。
1139 if(!is_directory(buffer))
1140 {
1141 *(wcsrchr(buffer, L'\\')) = L'\0';
1142 }
1143 if(is_directory(buffer))
1144 {
1145 if(find_java_vm(jvmpath, buffer, use_server_vm))
1146 {
1147 int bits = get_java_vm_bits(jvmpath);
1148 if(bits == get_process_architecture())
1149 {
1150 if(buffer[wcslen(buffer) - 1] != L'\\')
1151 {
1152 wcscat_s(buffer, BUFFER_SIZE, L"\\");
1153 }
1154 SetEnvironmentVariable(L"JAVA_HOME", buffer);
1155 wcscpy_s(binpath, MAX_LONG_PATH, buffer);
1156 wcscat_s(binpath, MAX_LONG_PATH, L"bin");
1157 }
1158 else
1159 {
1160 jvmpath[0] = L'\0';
1161 }
1162 }
1163 }
1164 }
1165 }
1166
1167 // Find JDK/JRE from registry
1168 if((vm_search_locations & VM_SEARCH_REGISTRY) && jvmpath[0] == L'\0')
1169 {
1170 wchar_t* subkeys_native[] =
1171 {
1172 L"SOFTWARE\\JavaSoft\\JDK", //Java9-
1173 L"SOFTWARE\\JavaSoft\\JRE", //Java9-
1174 L"SOFTWARE\\JavaSoft\\Java Development Kit",
1175 L"SOFTWARE\\JavaSoft\\Java Runtime Environment",
1176 NULL
1177 };
1178
1179 wchar_t* subkeys_wow[] =
1180 {
1181 L"SOFTWARE\\Wow6432Node\\JavaSoft\\JDK", //Java9-
1182 L"SOFTWARE\\Wow6432Node\\JavaSoft\\JRE", //Java9-
1183 L"SOFTWARE\\Wow6432Node\\JavaSoft\\Java Development Kit",
1184 L"SOFTWARE\\Wow6432Node\\JavaSoft\\Java Runtime Environment",
1185 NULL
1186 };
1187
1188 wchar_t** subkeys = subkeys_native;
1189 int i = 0;
1190
1191 //32ビットプロセスを64ビットOSで実行している場合はWowレジストリから検索します。
1192 if(get_process_architecture() == 32 && get_platform_architecture() == 64)
1193 {
1194 subkeys = subkeys_wow;
1195 }
1196
1197 while(subkeys[i] != NULL)
1198 {
1199 if(find_java_home_from_registry(subkeys[i], buffer) != NULL)
1200 {
1201 // JDK/JREをアンインストールしてもレジストリが残ってしまうディストリビューションがあるようです。
1202 // ディレクトリが存在する場合は次の工程に進みます。
1203 if(is_directory(buffer))
1204 {
1205 // 下位に jre フォルダーがあるか確認します。
1206 if(buffer[wcslen(buffer) - 1] == L'\\')
1207 {
1208 wcscat_s(buffer, BUFFER_SIZE, L"jre");
1209 }
1210 else
1211 {
1212 wcscat_s(buffer, BUFFER_SIZE, L"\\jre");
1213 }
1214 // 下位に jre フォルダーがなければ元のフォルダーに戻します。
1215 if(!is_directory(buffer))
1216 {
1217 *(wcsrchr(buffer, L'\\')) = L'\0';
1218 }
1219 if(is_directory(buffer))
1220 {
1221 if(find_java_vm(jvmpath, buffer, use_server_vm))
1222 {
1223 int bits = get_java_vm_bits(jvmpath);
1224 if(bits == get_process_architecture())
1225 {
1226 if(buffer[wcslen(buffer) - 1] != L'\\')
1227 {
1228 wcscat_s(buffer, BUFFER_SIZE, L"\\");
1229 }
1230 SetEnvironmentVariable(L"JAVA_HOME", buffer);
1231 wcscpy_s(binpath, MAX_LONG_PATH, buffer);
1232 wcscat_s(binpath, MAX_LONG_PATH, L"bin");
1233 break; // JavaVM found!!
1234 }
1235 else
1236 {
1237 jvmpath[0] = L'\0';
1238 }
1239 }
1240 }
1241 }
1242 }
1243 i++;
1244 }
1245 }
1246
1247 // Find java.exe from PATH environment
1248 if((vm_search_locations & VM_SEARCH_PATHENV) && jvmpath[0] == L'\0')
1249 {
1250 if(GetEnvironmentVariable(L"PATH", buffer, BUFFER_SIZE))
1251 {
1252 wchar_t* p;
1253 wchar_t* end;
1254
1255 if(buffer[wcslen(buffer) - 1] != L';')
1256 {
1257 wcscat_s(buffer, BUFFER_SIZE, L";");
1258 }
1259 end = buffer + wcslen(buffer);
1260
1261 while((p = wcsrchr(buffer, L';')) != NULL)
1262 {
1263 *p = L'\0';
1264 }
1265 p = buffer;
1266 while(p < end)
1267 {
1268 size_t len = wcslen(p);
1269
1270 if(len > 0)
1271 {
1272 wcscpy_s(search, MAX_LONG_PATH, p);
1273 if(search[wcslen(search) - 1] != L'\\')
1274 {
1275 wcscat_s(search, MAX_LONG_PATH, L"\\");
1276 }
1277 wcscat_s(search, MAX_LONG_PATH, L"java.exe");
1278 if(GetFileAttributes(search) != INVALID_FILE_ATTRIBUTES)
1279 {
1280 wchar_t* p2;
1281
1282 if((p2 = wcsrchr(search, L'\\')) != NULL)
1283 {
1284 *p2 = L'\0'; // remove filename(java.exe)
1285 }
1286 if((p2 = wcsrchr(search, L'\\')) != NULL)
1287 {
1288 *p2 = L'\0'; // remove dirname(bin)
1289 }
1290 if(find_java_vm(jvmpath, search, use_server_vm))
1291 {
1292 int bits = get_java_vm_bits(jvmpath);
1293 if(bits == get_process_architecture())
1294 {
1295 if(search[wcslen(search) - 1] != L'\\')
1296 {
1297 wcscat_s(search, MAX_LONG_PATH, L"\\");
1298 }
1299 SetEnvironmentVariable(L"JAVA_HOME", search);
1300 wcscpy_s(binpath, MAX_LONG_PATH, search);
1301 wcscat_s(binpath, MAX_LONG_PATH, L"bin");
1302 break;
1303 }
1304 else
1305 {
1306 jvmpath[0] = L'\0';
1307 }
1308 }
1309 //JDK8以前はjdk-8u152/jre/bin/server/jvm.dll のようにjdkの中にjreがありました。これも確認します。
1310 wcscat_s(search, MAX_LONG_PATH, L"\\jre");
1311 if(find_java_vm(jvmpath, search, use_server_vm))
1312 {
1313 int bits = get_java_vm_bits(jvmpath);
1314 if(bits == get_process_architecture())
1315 {
1316 if(search[wcslen(search) - 1] != L'\\')
1317 {
1318 wcscat_s(search, BUFFER_SIZE, L"\\");
1319 }
1320 SetEnvironmentVariable(L"JAVA_HOME", search);
1321 wcscpy_s(binpath, MAX_LONG_PATH, search);
1322 wcscat_s(binpath, MAX_LONG_PATH, L"bin");
1323 break;
1324 }
1325 else
1326 {
1327 jvmpath[0] = L'\0';
1328 }
1329 }
1330 }
1331 }
1332 p += len + 1;
1333 }
1334 }
1335 }
1336
1337 // Find .jar association from registry
1338 if((vm_search_locations & VM_SEARCH_JARASSOC) && jvmpath[0] == L'\0')
1339 {
1340 HKEY key1 = NULL;
1341 HKEY key2 = NULL;
1342 DWORD size;
1343
1344 wcscpy_s(search, MAX_LONG_PATH, L".jar");
1345 if(RegOpenKeyEx(HKEY_CLASSES_ROOT, search, 0, KEY_READ, &key1) == ERROR_SUCCESS)
1346 {
1347 size = BUFFER_SIZE;
1348 memset(buffer, 0x00, BUFFER_SIZE * sizeof(wchar_t));
1349 if(RegQueryValueEx(key1, NULL, NULL, NULL, (LPBYTE)buffer, &size) == ERROR_SUCCESS)
1350 {
1351 wcscpy_s(search, MAX_LONG_PATH, buffer);
1352 wcscat_s(search, MAX_LONG_PATH, L"\\shell\\open\\command");
1353 if(RegOpenKeyEx(HKEY_CLASSES_ROOT, search, 0, KEY_READ, &key2) == ERROR_SUCCESS)
1354 {
1355 size = BUFFER_SIZE;
1356 memset(buffer, 0x00, BUFFER_SIZE * sizeof(wchar_t));
1357 if(RegQueryValueEx(key2, NULL, NULL, NULL, (LPBYTE)buffer, &size) == ERROR_SUCCESS)
1358 {
1359 wchar_t* file = NULL;
1360 wchar_t* p;
1361 while((p = wcsrchr(buffer, L'.')) != NULL)
1362 {
1363 if(wcslen(p) >= 4)
1364 {
1365 *(p + 4) = L'\0';
1366 }
1367 if(_wcsicmp(p, L".EXE") == 0)
1368 {
1369 file = buffer + ((buffer[0] == L'"') ? 1 : 0);
1370 break;
1371 }
1372 *p = '\0';
1373 }
1374 if(file != NULL)
1375 {
1376 if((p = wcsrchr(file, L'\\')) != NULL)
1377 {
1378 *p = L'\0'; // remove filename(javaw.exe)
1379 }
1380 if((p = wcsrchr(file, L'\\')) != NULL)
1381 {
1382 *p = L'\0'; // remove dirname(bin)
1383 }
1384 // 下位に jre フォルダーがあるか確認します。
1385 wcscat_s(file, BUFFER_SIZE - 1, L"\\jre");
1386 // 下位に jre フォルダーがなければ元のフォルダーに戻します。
1387 if(!is_directory(file))
1388 {
1389 *(wcsrchr(file, L'\\')) = L'\0';
1390 }
1391 if(is_directory(file))
1392 {
1393 if(find_java_vm(jvmpath, file, use_server_vm))
1394 {
1395 int bits = get_java_vm_bits(jvmpath);
1396 if(bits == get_process_architecture())
1397 {
1398 if(file[wcslen(file) - 1] != L'\\')
1399 {
1400 wcscat_s(file, BUFFER_SIZE - 1, L"\\");
1401 }
1402 SetEnvironmentVariable(L"JAVA_HOME", file);
1403 wcscpy_s(binpath, MAX_LONG_PATH, file);
1404 wcscat_s(binpath, MAX_LONG_PATH, L"bin");
1405 }
1406 else
1407 {
1408 jvmpath[0] = L'\0';
1409 }
1410 }
1411 }
1412 }
1413 }
1414 }
1415 }
1416 }
1417 if(key2 != NULL)
1418 {
1419 RegCloseKey(key2);
1420 }
1421 if(key1 != NULL)
1422 {
1423 RegCloseKey(key1);
1424 }
1425 }
1426
1427
1428 GetModuleFileName(NULL, buffer, BUFFER_SIZE);
1429 wcscpy_s(libpath, BUFFER_SIZE, L".;");
1430 wcscat_s(libpath, BUFFER_SIZE, binpath); // binpathもjava.library.pathに含まれれるようにします。
1431 wcscat_s(libpath, BUFFER_SIZE, L";"); // そうしないと prism_sw.dll など一部のDLLが読み込めないようです…。
1432
1433 if(relative_classpath != NULL)
1434 {
1435 wchar_t* p = buffer;
1436 wchar_t* path = search;
1437
1438 wcscpy_s(p, BUFFER_SIZE, relative_classpath);
1439 while((token = wcstok_s(p, L" ", &context)) != NULL)
1440 {
1441 token = urldecode(search, MAX_LONG_PATH, token);
1442 if(token != NULL)
1443 {
1444 wcscpy_s(path, BUFFER_SIZE, L"");
1445 if(wcsstr(token, L":") == NULL) // パスに : を含んでいない場合は相対パスと見なしてmodule_pathを付加します。
1446 {
1447 wcscat_s(path, BUFFER_SIZE, module_path);
1448 wcscat_s(path, BUFFER_SIZE, L"\\");
1449 }
1450 wcscat_s(path, BUFFER_SIZE, token);
1451 if(is_directory(path))
1452 {
1453 wcscat_s(libpath, BUFFER_SIZE, path);
1454 wcscat_s(libpath, BUFFER_SIZE, L";");
1455 add_path_env(path);
1456 add_dll_directory(path);
1457 }
1458 }
1459 p = NULL;
1460 }
1461 }
1462
1463 if(relative_extdirs != NULL)
1464 {
1465 wchar_t* extdirs = buffer;
1466 wchar_t* extdir = search;
1467
1468 wcscpy_s(extdirs, BUFFER_SIZE, relative_extdirs);
1469 while((token = wcstok_s(extdirs, L";", &context)) != NULL)
1470 {
1471 extdirs = NULL;
1472
1473 if(wcslen(token) == 0)
1474 {
1475 continue;
1476 }
1477
1478 extdir[0] = L'\0';
1479 if(wcsstr(token, L":") == NULL) // パスに : を含んでいない場合は相対パスと見なしてmodule_pathを付加します。
1480 {
1481 wcscpy_s(extdir, MAX_LONG_PATH, module_path);
1482 wcscat_s(extdir, MAX_LONG_PATH, L"\\");
1483 }
1484 wcscat_s(extdir, MAX_LONG_PATH, token);
1485 if(is_directory(extdir))
1486 {
1487 wchar_t* dirs = get_sub_dirs(extdir);
1488 if(dirs != NULL)
1489 {
1490 wchar_t* dir = dirs;
1491 while(*dir)
1492 {
1493 wcscat_s(libpath, BUFFER_SIZE, dir);
1494 wcscat_s(libpath, BUFFER_SIZE, L";");
1495 add_path_env(dir);
1496 add_dll_directory(dir);
1497
1498 dir += wcslen(dir) + 1;
1499 }
1500 free(dirs);
1501 }
1502 }
1503 }
1504 }
1505
1506 // PATH環境変数の内容もjava.library.pathに含めます。
1507 // JPKIなどのライブラリをロードするために必要になります。
1508 if(path_env != NULL)
1509 {
1510 wcscat_s(libpath, BUFFER_SIZE, path_env);
1511 }
1512
1513 add_path_env(binpath);
1514 add_dll_directory(binpath);
1515
1516 add_path_env(jvmpath);
1517 add_dll_directory(jvmpath);
1518
1519 path_initialized = TRUE;
1520
1521 EXIT:
1522 if(path_env != NULL)
1523 {
1524 free(path_env);
1525 }
1526 if(module_path != NULL)
1527 {
1528 free(module_path);
1529 }
1530 if(jdk != NULL)
1531 {
1532 free(jdk);
1533 }
1534 if(search != NULL)
1535 {
1536 free(search);
1537 }
1538 if(buffer != NULL)
1539 {
1540 free(buffer);
1541 }
1542 return path_initialized;
1543 }
1544
1545
1546 /* 指定したJRE BINディレクトリで client\jvm.dll または server\jvm.dll を検索します。
1547 * jvm.dll の見つかったディレクトリを output に格納します。
1548 * jvm.dll が見つからなかった場合は output に client のパスを格納します。
1549 * use_server_vm が TRUE の場合、Server VM を優先検索します。
1550 * jvm.dll が見つかった場合は TRUE, 見つからなかった場合は FALSE を返します。
1551 */
1552 BOOL find_java_vm(wchar_t* output, const wchar_t* jre, BOOL use_server_vm)
1553 {
1554 BOOL found = FALSE;
1555 wchar_t* path = NULL;
1556 wchar_t* buf = NULL;
1557
1558 path = (wchar_t*)malloc(MAX_LONG_PATH * sizeof(wchar_t));
1559 if(path == NULL)
1560 {
1561 goto EXIT;
1562 }
1563
1564 buf = (wchar_t*)malloc(MAX_LONG_PATH * sizeof(wchar_t));
1565 if(buf == NULL)
1566 {
1567 goto EXIT;
1568 }
1569
1570 if(use_server_vm)
1571 {
1572 wcscpy_s(path, MAX_LONG_PATH, jre);
1573 wcscat_s(path, MAX_LONG_PATH, L"\\bin\\server");
1574 wcscpy_s(buf, MAX_LONG_PATH, path);
1575 wcscat_s(buf, MAX_LONG_PATH, L"\\jvm.dll");
1576 if(GetFileAttributes(buf) == INVALID_FILE_ATTRIBUTES)
1577 {
1578 wcscpy_s(path, MAX_LONG_PATH, jre);
1579 wcscat_s(path, MAX_LONG_PATH, L"\\bin\\client");
1580 wcscpy_s(buf, MAX_LONG_PATH, path);
1581 wcscat_s(buf, MAX_LONG_PATH, L"\\jvm.dll");
1582 if(GetFileAttributes(buf) == INVALID_FILE_ATTRIBUTES)
1583 {
1584 path[0] = L'\0';
1585 }
1586 }
1587 }
1588 else
1589 {
1590 wcscpy_s(path, MAX_LONG_PATH, jre);
1591 wcscat_s(path, MAX_LONG_PATH, L"\\bin\\client");
1592 wcscpy_s(buf, MAX_LONG_PATH, path);
1593 wcscat_s(buf, MAX_LONG_PATH, L"\\jvm.dll");
1594 if(GetFileAttributes(buf) == INVALID_FILE_ATTRIBUTES)
1595 {
1596 wcscpy_s(path, MAX_LONG_PATH, jre);
1597 wcscat_s(path, MAX_LONG_PATH, L"\\bin\\server");
1598 wcscpy_s(buf, MAX_LONG_PATH, path);
1599 wcscat_s(buf, MAX_LONG_PATH, L"\\jvm.dll");
1600 if(GetFileAttributes(buf) == INVALID_FILE_ATTRIBUTES)
1601 {
1602 path[0] = L'\0';
1603 }
1604 }
1605 }
1606 if(path[0] != L'\0')
1607 {
1608 wcscpy_s(output, MAX_LONG_PATH, path);
1609 found = TRUE;
1610 }
1611
1612 EXIT:
1613 if(buf != NULL)
1614 {
1615 free(buf);
1616 }
1617 if(path != NULL)
1618 {
1619 free(path);
1620 }
1621 return found;
1622 }
1623
1624
1625 wchar_t* find_java_home_from_registry(const wchar_t* _subkey, wchar_t* output)
1626 {
1627 HKEY key = NULL;
1628 DWORD size;
1629 wchar_t* subkey = NULL;
1630 wchar_t* buf = NULL;
1631
1632 if(output != NULL)
1633 {
1634 output[0] = L'\0';
1635 }
1636
1637 subkey = (wchar_t*)malloc(MAX_LONG_PATH * sizeof(wchar_t));
1638 if(subkey == NULL)
1639 {
1640 goto EXIT;
1641 }
1642 wcscpy_s(subkey, MAX_LONG_PATH, _subkey);
1643
1644 buf = (wchar_t*)malloc(MAX_LONG_PATH * sizeof(wchar_t));
1645 if(buf == NULL)
1646 {
1647 goto EXIT;
1648 }
1649
1650 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, subkey, 0, KEY_READ, &key) != ERROR_SUCCESS)
1651 {
1652 goto EXIT;
1653 }
1654 size = MAX_LONG_PATH;
1655 memset(buf, 0x00, MAX_LONG_PATH * sizeof(wchar_t));
1656 if(RegQueryValueEx(key, L"CurrentVersion", NULL, NULL, (LPBYTE)buf, &size) != ERROR_SUCCESS)
1657 {
1658 goto EXIT;
1659 }
1660 RegCloseKey(key);
1661 key = NULL;
1662
1663 wcscat_s(subkey, MAX_LONG_PATH, L"\\");
1664 wcscat_s(subkey, MAX_LONG_PATH, buf);
1665
1666 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, subkey, 0, KEY_READ, &key) != ERROR_SUCCESS)
1667 {
1668 goto EXIT;
1669 }
1670
1671 size = MAX_LONG_PATH;
1672 memset(buf, 0x00, MAX_LONG_PATH * sizeof(wchar_t));
1673 if(RegQueryValueEx(key, L"JavaHome", NULL, NULL, (LPBYTE)buf, &size) != ERROR_SUCCESS)
1674 {
1675 goto EXIT;
1676 }
1677 RegCloseKey(key);
1678 key = NULL;
1679
1680 wcscpy_s(output, MAX_LONG_PATH, buf);
1681
1682 EXIT:
1683 if(key != NULL)
1684 {
1685 RegCloseKey(key);
1686 }
1687 if(buf != NULL)
1688 {
1689 free(buf);
1690 }
1691 if(subkey != NULL)
1692 {
1693 free(subkey);
1694 }
1695
1696 return (output[0] != L'\0' ? output : NULL);
1697 }
1698
1699 static BOOL add_path_env(const wchar_t* path)
1700 {
1701 BOOL succeeded = FALSE;
1702 wchar_t* buf = NULL;
1703 wchar_t* old = NULL;
1704
1705 if(path == NULL)
1706 {
1707 goto EXIT;
1708 }
1709 buf = (wchar_t*)malloc(BUFFER_SIZE * sizeof(wchar_t));
1710 if(buf == NULL)
1711 {
1712 goto EXIT;
1713 }
1714 old = (wchar_t*)malloc(BUFFER_SIZE * sizeof(wchar_t));
1715 if(old == NULL)
1716 {
1717 goto EXIT;
1718 }
1719
1720 GetEnvironmentVariable(L"PATH", old, BUFFER_SIZE);
1721 wcscpy_s(buf, MAX_LONG_PATH, path);
1722 wcscat_s(buf, MAX_LONG_PATH, L";");
1723 wcscat_s(buf, MAX_LONG_PATH, old);
1724 SetEnvironmentVariable(L"PATH", buf);
1725 succeeded = TRUE;
1726
1727 EXIT:
1728 if(old != NULL)
1729 {
1730 free(old);
1731 }
1732 if(buf != NULL)
1733 {
1734 free(buf);
1735 }
1736 return succeeded;
1737 }
1738
1739
1740 static void add_dll_directory(const wchar_t* path)
1741 {
1742 if(_AddDllDirectory != NULL)
1743 {
1744 _AddDllDirectory(path);
1745 }
1746 }
1747
1748
1749 wchar_t* get_module_version(wchar_t* buf, size_t size)
1750 {
1751 HRSRC hrsrc;
1752 VS_FIXEDFILEINFO* verInfo;
1753
1754 hrsrc = FindResource(NULL, MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
1755 if(hrsrc == NULL)
1756 {
1757 *buf = L'\0';
1758 return NULL;
1759 }
1760
1761 verInfo = (VS_FIXEDFILEINFO*)((char*)LockResource(LoadResource(NULL, hrsrc)) + 40);
1762 swprintf_s(buf, size, L"%d.%d.%d.%d",
1763 verInfo->dwFileVersionMS >> 16,
1764 verInfo->dwFileVersionMS & 0xFFFF,
1765 verInfo->dwFileVersionLS >> 16,
1766 verInfo->dwFileVersionLS & 0xFFFF
1767 );
1768
1769 return buf;
1770 }
1771
1772
1773 static BOOL is_directory(const wchar_t* path)
1774 {
1775 DWORD attr = GetFileAttributes(path);
1776 return (attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY);
1777 }
1778
1779
1780 static wchar_t* get_sub_dirs(const wchar_t* dir)
1781 {
1782 size_t size;
1783 wchar_t* buf;
1784
1785 size = wcslen(dir) + 2;
1786 if(add_sub_dirs(NULL, 0, dir, &size) == FALSE)
1787 {
1788 return NULL;
1789 }
1790 buf = (wchar_t*)calloc(size, sizeof(wchar_t));
1791 if(buf == NULL)
1792 {
1793 return NULL;
1794 }
1795 wcscpy_s(buf, size, dir);
1796 if(add_sub_dirs(buf + wcslen(dir) + 1, size - wcslen(dir) - 1, dir, NULL) == FALSE)
1797 {
1798 free(buf);
1799 return NULL;
1800 }
1801 return buf;
1802 }
1803
1804
1805 static BOOL add_sub_dirs(wchar_t* buf, size_t buf_size, const wchar_t* dir, size_t* size)
1806 {
1807 BOOL succeeded = FALSE;
1808 WIN32_FIND_DATA fd;
1809 HANDLE hSearch;
1810 wchar_t* search = NULL;
1811 wchar_t* child = NULL;
1812
1813 search = (wchar_t*)malloc(MAX_LONG_PATH * sizeof(wchar_t));
1814 if(search == NULL)
1815 {
1816 goto EXIT;
1817 }
1818 child = (wchar_t*)malloc(MAX_LONG_PATH * sizeof(wchar_t));
1819 if(child == NULL)
1820 {
1821 goto EXIT;
1822 }
1823
1824 wcscpy_s(search, MAX_LONG_PATH, dir);
1825 wcscat_s(search, MAX_LONG_PATH, L"\\*");
1826
1827 hSearch = FindFirstFile(search, &fd);
1828 if(hSearch != INVALID_HANDLE_VALUE)
1829 {
1830 do
1831 {
1832 if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1833 {
1834 if (wcscmp(fd.cFileName, L".") == 0 || wcscmp(fd.cFileName, L"..") == 0)
1835 {
1836 continue;
1837 }
1838
1839 wcscpy_s(child, MAX_LONG_PATH, dir);
1840 wcscat_s(child, MAX_LONG_PATH, L"\\");
1841 wcscat_s(child, MAX_LONG_PATH, fd.cFileName);
1842 if(size != NULL)
1843 {
1844 *size = *size + wcslen(child) + 1;
1845 }
1846 if(buf != NULL)
1847 {
1848 wcscpy_s(buf, buf_size, child);
1849 buf += wcslen(child) + 1;
1850 buf_size -= wcslen(child) + 1;
1851 }
1852 add_sub_dirs(buf, buf_size, child, size);
1853 }
1854 } while (FindNextFile(hSearch, &fd));
1855 FindClose(hSearch);
1856 }
1857 succeeded = TRUE;
1858
1859 EXIT:
1860 if(child != NULL)
1861 {
1862 free(child);
1863 }
1864 if(search != NULL)
1865 {
1866 free(search);
1867 }
1868
1869 return succeeded;
1870 }
1871
1872
1873 static wchar_t* get_jars(const wchar_t* dir)
1874 {
1875 size_t size;
1876 wchar_t* buf;
1877
1878 size = wcslen(dir) + 2;
1879 if(add_jars(NULL, 0, dir, &size) == FALSE)
1880 {
1881 return NULL;
1882 }
1883 buf = (wchar_t*)calloc(size, sizeof(wchar_t));
1884 if(buf == NULL)
1885 {
1886 return NULL;
1887 }
1888 if(add_jars(buf, size, dir, NULL) == FALSE)
1889 {
1890 free(buf);
1891 return NULL;
1892 }
1893 return buf;
1894 }
1895
1896
1897 static BOOL add_jars(wchar_t* buf, size_t buf_size, const wchar_t* dir, size_t* size)
1898 {
1899 BOOL succeeded = FALSE;
1900 WIN32_FIND_DATA fd;
1901 HANDLE hSearch;
1902 wchar_t* search = NULL;
1903 wchar_t* child = NULL;
1904
1905 search = (wchar_t*)malloc(MAX_LONG_PATH * sizeof(wchar_t));
1906 if(search == NULL)
1907 {
1908 goto EXIT;
1909 }
1910 child = (wchar_t*)malloc(MAX_LONG_PATH * sizeof(wchar_t));
1911 if(child == NULL)
1912 {
1913 goto EXIT;
1914 }
1915
1916 wcscpy_s(search, MAX_LONG_PATH, dir);
1917 wcscat_s(search, MAX_LONG_PATH, L"\\*");
1918
1919 hSearch = FindFirstFile(search, &fd);
1920 if(hSearch != INVALID_HANDLE_VALUE)
1921 {
1922 do
1923 {
1924 if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1925 {
1926 if (wcscmp(fd.cFileName, L".") == 0 || wcscmp(fd.cFileName, L"..") == 0)
1927 {
1928 continue;
1929 }
1930
1931 wcscpy_s(child, MAX_LONG_PATH, dir);
1932 wcscat_s(child, MAX_LONG_PATH, L"\\");
1933 wcscat_s(child, MAX_LONG_PATH, fd.cFileName);
1934 add_jars(buf, buf_size, child, size);
1935 }
1936 else
1937 {
1938 size_t len = wcslen(fd.cFileName);
1939 if(len >= 4)
1940 {
1941 wchar_t* ext = fd.cFileName + len - 4;
1942 if(_wcsicmp(ext, L".JAR") == 0)
1943 {
1944 wcscpy_s(child, MAX_LONG_PATH, dir);
1945 wcscat_s(child, MAX_LONG_PATH, L"\\");
1946 wcscat_s(child, MAX_LONG_PATH, fd.cFileName);
1947 if(size != NULL)
1948 {
1949 *size = *size + wcslen(child) + 1;
1950 }
1951 if(buf != NULL)
1952 {
1953 wcscpy_s(buf, buf_size, child);
1954 buf += wcslen(child) + 1;
1955 buf_size -= wcslen(child) + 1;
1956 }
1957 }
1958 }
1959 }
1960 } while (FindNextFile(hSearch, &fd));
1961 FindClose(hSearch);
1962 }
1963 succeeded = TRUE;
1964
1965 EXIT:
1966 if(child != NULL)
1967 {
1968 free(child);
1969 }
1970 if(search != NULL)
1971 {
1972 free(search);
1973 }
1974 return succeeded;
1975 }
1976
1977
1978 int get_java_vm_bits(const wchar_t* jvmpath)
1979 {
1980 int bits = 0;
1981 wchar_t* file = NULL;
1982 HANDLE hFile = NULL;
1983 BYTE* buf = NULL;
1984 DWORD size = 512;
1985 DWORD read_size;
1986 UINT i;
1987
1988 file = (wchar_t*)malloc(MAX_LONG_PATH * sizeof(wchar_t));
1989 if(file == NULL)
1990 {
1991 goto EXIT;
1992 }
1993 swprintf_s(file, MAX_LONG_PATH, L"%s\\jvm.dll", jvmpath);
1994
1995 buf = (BYTE*)malloc(size);
1996 if(buf == NULL)
1997 {
1998 goto EXIT;
1999 }
2000
2001 hFile = CreateFile(file, GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2002 if(hFile == INVALID_HANDLE_VALUE)
2003 {
2004 goto EXIT;
2005 }
2006
2007 if(ReadFile(hFile, buf, size, &read_size, NULL) == 0)
2008 {
2009 goto EXIT;
2010 }
2011
2012 for(i = 0; i < size - 6; i++)
2013 {
2014 if(buf[i + 0] == 'P' && buf[i + 1] == 'E' && buf[i + 2] == 0x00 && buf[i + 3] == 0x00)
2015 {
2016 if (buf[i + 4] == 0x4C && buf[i + 5] == 0x01)
2017 {
2018 bits = 32;
2019 goto EXIT;
2020 }
2021 if (buf[i + 4] == 0x64 && buf[i + 5] == 0x86)
2022 {
2023 bits = 64;
2024 goto EXIT;
2025 }
2026 }
2027 }
2028
2029 EXIT:
2030 if(hFile != NULL)
2031 {
2032 CloseHandle(hFile);
2033 }
2034 if(buf != NULL)
2035 {
2036 free(buf);
2037 }
2038 if(file != NULL)
2039 {
2040 free(file);
2041 }
2042 return bits;
2043 }
2044
2045
2046 static wchar_t* urldecode(wchar_t *dst, size_t dst_size, const wchar_t *src)
2047 {
2048 wchar_t* result = NULL;
2049 char* src_utf8 = NULL;
2050 char* dst_utf8 = NULL;
2051 char* src_ptr;
2052 char* dst_ptr;
2053 char a;
2054 char b;
2055 wchar_t* buf = NULL;
2056
2057 src_ptr = src_utf8 = to_utf8(src);
2058 if(src_utf8 == NULL)
2059 {
2060 goto EXIT;
2061 }
2062 dst_ptr = dst_utf8 = (char*)malloc(strlen(src_utf8) + 1);
2063 if(dst_utf8 == NULL)
2064 {
2065 goto EXIT;
2066 }
2067
2068 while(*src_ptr)
2069 {
2070 if(*src_ptr == '%' && (a = src_ptr[1]) != '\0' && (b = src_ptr[2]) != '\0' && isxdigit(a) && isxdigit(b))
2071 {
2072 if(a >= 'a')
2073 {
2074 a -= 'a'-'A';
2075 }
2076
2077 if(a >= 'A')
2078 {
2079 a -= ('A' - 10);
2080 }
2081 else
2082 {
2083 a -= '0';
2084 }
2085
2086 if(b >= 'a')
2087 {
2088 b -= 'a'-'A';
2089 }
2090
2091 if(b >= 'A')
2092 {
2093 b -= ('A' - 10);
2094 }
2095 else
2096 {
2097 b -= '0';
2098 }
2099
2100 *dst_ptr++ = 16 * a + b;
2101 src_ptr += 3;
2102 }
2103 else if(*src_ptr == '+')
2104 {
2105 *dst_ptr++ = ' ';
2106 src_ptr++;
2107 }
2108 else
2109 {
2110 *dst_ptr++ = *src_ptr++;
2111 }
2112 }
2113 *dst_ptr++ = '\0';
2114
2115 buf = from_utf8(dst_utf8);
2116 wcscpy_s(dst, dst_size, buf);
2117 result = dst;
2118
2119 EXIT:
2120 if(buf != NULL)
2121 {
2122 free(buf);
2123 }
2124 if(dst_utf8 != NULL)
2125 {
2126 free(dst_utf8);
2127 }
2128 if(src_utf8 != NULL)
2129 {
2130 free(src_utf8);
2131 }
2132 return result;
2133 }
2134
2135
2136 char* to_platform_encoding(const wchar_t* str)
2137 {
2138 int mb_size;
2139 char* mb_buf;
2140
2141 if(str == NULL)
2142 {
2143 return NULL;
2144 }
2145
2146 mb_size = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
2147 if(mb_size == 0)
2148 {
2149 return NULL;
2150 }
2151 mb_buf = (char*)malloc(mb_size);
2152 if(mb_buf == NULL)
2153 {
2154 return NULL;
2155 }
2156 if(WideCharToMultiByte(CP_ACP, 0, str, -1, mb_buf, mb_size, NULL, NULL) == 0)
2157 {
2158 free(mb_buf);
2159 return NULL;
2160 }
2161 return mb_buf;
2162 }
2163
2164
2165 char* to_utf8(const wchar_t* str)
2166 {
2167 int mb_size;
2168 char* mb_buf;
2169
2170 if(str == NULL)
2171 {
2172 return NULL;
2173 }
2174
2175 mb_size = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
2176 if(mb_size == 0)
2177 {
2178 return NULL;
2179 }
2180 mb_buf = (char*)malloc(mb_size);
2181 if(mb_buf == NULL)
2182 {
2183 return NULL;
2184 }
2185 if(WideCharToMultiByte(CP_UTF8, 0, str, -1, mb_buf, mb_size, NULL, NULL) == 0)
2186 {
2187 free(mb_buf);
2188 return NULL;
2189 }
2190 return mb_buf;
2191 }
2192
2193
2194 wchar_t* from_utf8(const char* utf8)
2195 {
2196 int wc_size;
2197 wchar_t* wc_buf;
2198
2199 if(utf8 == NULL)
2200 {
2201 return NULL;
2202 }
2203
2204 wc_size = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
2205 if(wc_size == 0)
2206 {
2207 return NULL;
2208 }
2209 wc_buf = (wchar_t*)malloc(wc_size * sizeof(wchar_t));
2210 if(wc_buf == NULL)
2211 {
2212 return NULL;
2213 }
2214 if(MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wc_buf, wc_size) == 0)
2215 {
2216 free(wc_buf);
2217 return NULL;
2218 }
2219 return wc_buf;
2220 }
2221
2222
2223 jstring to_jstring(JNIEnv* env, const wchar_t* str)
2224 {
2225 jstring jstr;
2226
2227 if(str == NULL)
2228 {
2229 return NULL;
2230 }
2231 jstr = (*env)->NewString(env, (jchar*)str, (jsize)wcslen(str));
2232 return jstr;
2233 }
2234
2235
2236 wchar_t* from_jstring(JNIEnv* env, jstring jstr)
2237 {
2238 const jchar* unicode;
2239 size_t wc_size;
2240 wchar_t* wc_buf;
2241
2242 if(jstr == NULL)
2243 {
2244 return NULL;
2245 }
2246 unicode = (*env)->GetStringChars(env, jstr, NULL);
2247 if(unicode == NULL)
2248 {
2249 return NULL;
2250 }
2251 wc_size = wcslen(unicode) + 1;
2252 wc_buf = malloc(wc_size * sizeof(wchar_t));
2253 if(wc_buf != NULL)
2254 {
2255 wcscpy_s(wc_buf, wc_size, unicode);
2256 }
2257 (*env)->ReleaseStringChars(env, jstr, unicode);
2258 return wc_buf;
2259 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26