• R/O
  • HTTP
  • SSH
  • HTTPS

CharacterManaJ: Commit

キャラクターなんとかJの本体


Commit MetaInfo

Revision4066a93fdc730fb4156d6db7fe2230d679729bc3 (tree)
Time2019-01-13 13:29:53
Authorseraphy <seraphy@user...>
Commiterseraphy

Log Message

カスタムLaunch4jheadの更新

Change Summary

Incremental Difference

Binary files a/src/Launch4JStub/head/guihead.o and b/src/Launch4JStub/head/guihead.o differ
Binary files a/src/Launch4JStub/head/head.o and b/src/Launch4JStub/head/head.o differ
--- a/src/Launch4JStub/head_src/head.c
+++ b/src/Launch4JStub/head_src/head.c
@@ -254,6 +254,52 @@ int loadInt(const int resID)
254254 return atoi(intStr);
255255 }
256256
257+typedef enum __PE6432
258+{
259+ PE_UNKNOWN, // x86, x64のいずれでもない (有効なPEのIA64, ARMなども該当する)
260+ PE_X86,
261+ PE_X64
262+} PE6432;
263+
264+/**
265+ * 指定したPEファイル(EXE, DLL)の32/64ビットを判定する。
266+ * @param pFileName ファイルのパス
267+ * @return 判定結果
268+ */
269+PE6432 CheckPE6432(LPCTSTR pFileName)
270+{
271+ PE6432 result = PE_UNKNOWN;
272+ HANDLE fh = CreateFile(pFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
273+ if (fh != INVALID_HANDLE_VALUE) {
274+ // DOSヘッダ読み取り
275+ IMAGE_DOS_HEADER imageDosHeader = { 0 };
276+ DWORD rd = 0;
277+ if (ReadFile(fh, &imageDosHeader, sizeof(IMAGE_DOS_HEADER), &rd, NULL) &&
278+ rd == sizeof(IMAGE_DOS_HEADER) &&
279+ imageDosHeader.e_magic == IMAGE_DOS_SIGNATURE) { // "MZ"
280+ // NTヘッダ部まで移動
281+ SetFilePointer(fh, imageDosHeader.e_lfanew, NULL, FILE_BEGIN);
282+ if (GetLastError() == NO_ERROR) {
283+ // NTヘッダ読み取り
284+ IMAGE_NT_HEADERS imageNTHeader = { 0 };
285+ if (ReadFile(fh, &imageNTHeader, sizeof(IMAGE_NT_HEADERS), &rd, NULL) &&
286+ rd == sizeof(IMAGE_NT_HEADERS) &&
287+ imageNTHeader.Signature == IMAGE_NT_SIGNATURE) {
288+ // マシンタイプの判定
289+ if (imageNTHeader.FileHeader.Machine == IMAGE_FILE_MACHINE_I386) {
290+ result = PE_X86;
291+ } else if (imageNTHeader.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) {
292+ result = PE_X64;
293+ }
294+ // IA64, ARMなどはUNKNOWNにする
295+ }
296+ }
297+ }
298+ CloseHandle(fh);
299+ }
300+ return result;
301+}
302+
257303 BOOL regQueryValue(const char* regPath, unsigned char* buffer,
258304 unsigned long bufferLength)
259305 {
@@ -666,41 +712,6 @@ BOOL findJavaHome(char* path, const int jdkPreference)
666712 return FALSE;
667713 }
668714
669-BOOL checkJavaExe(char *path)
670-{
671- char path2[MAX_PATH];
672- strcpy(path2, path);
673- strcat(path2, "\\bin\\java.exe");
674-
675- DWORD attr = GetFileAttributes(path2);
676- return attr != -1;
677-}
678-
679-BOOL chooseJavaHome(char *path)
680-{
681- // フォルダ選択ダイアログに表示するメッセージはエラーメッセージを借用する
682- createJreSearchError();
683-
684- BROWSEINFO bInfo = { 0 };
685- bInfo.hwndOwner = NULL;
686- bInfo.pidlRoot = NULL;
687- bInfo.pszDisplayName = path;
688- bInfo.lpszTitle = error.msg;
689- bInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
690-
691- LPITEMIDLIST result = NULL;
692- while (!checkJavaExe(path))
693- {
694- result = SHBrowseForFolder(&bInfo);
695- if (result == NULL)
696- {
697- return FALSE;
698- }
699-
700- SHGetPathFromIDList(result, path);
701- }
702- return TRUE;
703-}
704715
705716 /*
706717 * Extract the executable name, returns path length.
@@ -723,12 +734,17 @@ void getCfgPath(const char *exePath, char *cfgPath)
723734 strcpy(cfgPath + strlen(cfgPath) - 4, ".cfg");
724735 }
725736
726-void appendPath(char* basepath, const char* path)
737+void appendPath(LPTSTR basepath, LPCTSTR path)
727738 {
728- if (basepath[strlen(basepath) - 1] != '\\')
739+ LPCTSTR pLast = basepath;
740+ while (*pLast++); // 末尾まで移動
741+ pLast = CharPrev(basepath, pLast); // 一文字戻る (MBCS文字可)
742+
743+ if (*pLast != '\\')
729744 {
730745 strcat(basepath, "\\");
731746 }
747+
732748 strcat(basepath, path);
733749 }
734750
@@ -754,74 +770,158 @@ void appendAppClasspath(char* dst, const char* src)
754770 * 指定したディレクトリを親にさかのぼって指定したファイル・フォルダ名に一致する
755771 * パスを検索してdstに追記する。存在しない場合は何もしない。
756772 * @param dst 発見されたパスを追記するバッファ
757- * @param dir 最初に指定するのはEXEへのフルパス(*.exe)を指定する。
758- * @param name 検索する名前
773+ * @param dir 末尾が\のディレクトリ、または最初に指定するのはEXEへのフルパス(*.exe)を指定する。
774+ * @param name 検索する名前(A\B\Cのようにフォルダ区切りがあっても良い)
775+ * @return 発見された場合はTRUE、発見されなかった場合はFALSE
759776 */
760-void findAncestor(char* dst, const char *dir, const char* name)
777+BOOL findAncestor(char* dst, const char *dir, const char* name)
761778 {
762779 // 親フォルダを検索
763780 char parent[MAX_PATH];
764781 strcpy(parent, dir);
765782 char *p = parent;
766- while (*p++);
783+ while (*p++); // 末尾に移動
784+
785+ // UNC形式の場合(ネットワークパスの場合)
786+ // 最初のフォルダまでは固定にする。
787+ // (ex.) \\ABC\DEF\XYZ の場合、\\ABC\DEF\ より遡らない
788+ char *top = parent;
789+ if (*top == '\\' && *(top + 1) == '\\')
790+ {
791+ top += 2;
792+ while(*top && *top != '\\') top = CharNext(top);
793+ }
767794
768- while (p > parent)
795+ while (p > top)
769796 {
770- if (*p == '\\' || *p == '/')
797+ if (*p == '\\' && *(p + 1))
771798 {
772- if (*(p + 1))
773- {
774- // 現在の末尾のフォルダ区切り以外であれば、ここを末尾にする
775- *(p + 1) = 0;
776- break;
777- }
799+ // 現在の末尾のフォルダ区切り以外であれば、ここを末尾にする
800+ // C:\a\b\c.exe を開始した場合は、C:\a\b\ がマッチする。
801+ // C:\a\b\ で開始した場合は、C:\a\ がマッチする。
802+ // C:\a\ で開始した場合は、C:\ がマッチする。
803+ // C:\ で開始した場合はマッチするものがないので終了する
804+ // UNC形式で \\ABC\DEF\XYZ.exe で開始した場合は\\ABC\DEF\ がマッチする
805+ // UNC形式で \\ABC\DEF\ で開始した場合は、\\ABC\DEF\より遡れないので終了する
806+ *(p + 1) = 0;
807+ break;
778808 }
779809 p = CharPrev(parent, p);
780810 }
811+
781812 if (strcmp(dir, parent) == 0)
782813 {
783814 // 変化なしなので、すでに検索済みのはず
784- debug("Find End");
785- return;
815+ debug("Not Found\n");
816+ return FALSE;
786817 }
787-
788- // 親フォルダを列挙
789- WIN32_FIND_DATA data = {0};
790-
791- char searchdir[MAX_PATH];
792- strcpy(searchdir, parent);
793- strcat(searchdir, "*.*");
794- debug("FindFirstFile:\t%s\n", searchdir);
795-
796- HANDLE fh = FindFirstFile(searchdir, &data);
797- if (fh == INVALID_HANDLE_VALUE) {
798- debug("FindFirstFile:\tErr=%d\n", GetLastError());
799- return;
818+
819+ // フォルダ + name でフルパスを作成する
820+ char temp[MAX_PATH] = { 0 };
821+ strcpy(temp, parent);
822+ strcat(temp, name);
823+
824+ // ファイルまたはフォルダの実在チェック
825+ debug("check exist: %s\n", temp);
826+ DWORD attr = GetFileAttributes(temp);
827+ if (attr != -1) {
828+ // パスが実在すればOK.
829+ strcat(dst, temp);
830+ debug("Found: %s\n", temp);
831+ return TRUE;
800832 }
801-
802- for (;;)
833+
834+ // 更に、この親を検索する
835+ findAncestor(dst, parent, name);
836+}
837+
838+/**
839+ * 指定したディレクトリを親にさかのぼって、セミコロンで区切られた複数の
840+ * ファイル・フォルダ名に一致するパスを検索してdstに追記する。
841+ * 存在しない場合は何もしない。
842+ * セミコロンで区切った名前は先頭のものから順番に評価され、
843+ * 最初にみつかった時点で完了する。
844+ * @param dst 発見されたパスを追記するバッファ
845+ * @param dir 最初に指定するのはEXEへのフルパス(*.exe)を指定する。
846+ * @param name 検索する名前(A\B\Cのようにフォルダ区切りがあっても良い)
847+ * @return 発見された場合はTRUE、発見されなかった場合はFALSE
848+ */
849+BOOL multiFindAncestor(char* dst, const char *dir, const char* names)
850+{
851+ char name[MAX_PATH];
852+ const char *p = names;
853+ while (*p)
803854 {
804- //debug("cFileName:\t%s\n", data.cFileName);
855+ // セミコロンまたは末尾までの名前を取り出す
856+ char *d = name;
857+ while (*p && *p != ';') *d++ = *p++;
858+ *d = 0;
859+ if (*p) p++; // セミコロンであれば1文字進める
805860
806- if (strcasecmp(data.cFileName, name) == 0) // 大小文字は区別しない
861+ if (*name)
807862 {
808- strcat(dst, parent);
809- strcat(dst, data.cFileName);
810- return;
863+ // 取り出した名前でfindAncestorを試行する
864+ debug("FIND_ANCESTOR: %s\n", name);
865+ if (findAncestor(dst, dir, name))
866+ {
867+ return TRUE;
868+ }
811869 }
812-
813- if (!FindNextFile(fh, &data))
870+ }
871+ // すべて見つからなかった場合
872+ return FALSE;
873+}
874+
875+/**
876+ * javaの実行ファイルが64/32ビットのいずれであるかを示す 文字列を返す。
877+ * 「変数名:X86名,X64名」のように、変数名後にコロンをつけて表示名を指定できる。
878+ * x86, x64 の順にカンマで区切り、省略された場合は「x86」「x64」となる。
879+ * @param dst 変数展開先
880+ * @param args 変数名の後に付与される引数。空でも良い。
881+ */
882+void jreArch(char* dst, const char* args)
883+{
884+ char tempBuf[MAX_PATH] = { 0 };
885+ LPCTSTR displayArchs[] =
886+ {
887+ "x86",
888+ "x64"
889+ };
890+
891+ if (*args == ':')
892+ {
893+ strcpy(tempBuf, args + 1);
894+ displayArchs[0] = tempBuf; // x86用文字列
895+ int idx = 1;
896+ char *p = tempBuf;
897+ while (*p)
814898 {
815- // ERROR_NO_MORE_FILES でエラー有無の判定は、
816- // 結局、ループを打ち切るだけなので省略。
817- break;
899+ if (*p == ',')
900+ {
901+ *p = 0;
902+ displayArchs[1] = p + 1; // カンマ区切りでx64用文字列
903+ break;
904+ }
905+ p = CharNext(p);
818906 }
819907 }
820- FindClose(fh);
821- debug("FindClose:\t%s\n", parent);
822-
823- // 更に、この親を検索する
824- findAncestor(dst, parent, name);
908+
909+ char launcherPath[MAX_PATH] = { 0 };
910+ strcpy(launcherPath, search.foundJavaHome);
911+ appendLauncher(launcherPath);
912+
913+ PE6432 peType = CheckPE6432(launcherPath);
914+
915+ debug("PE Type: %s = %d\n", launcherPath, peType);
916+
917+ if (peType == PE_X64)
918+ {
919+ strcat(dst, displayArchs[1]);
920+ }
921+ else if (peType == PE_X86)
922+ {
923+ strcat(dst, displayArchs[0]);
924+ }
825925 }
826926
827927 /*
@@ -852,8 +952,13 @@ BOOL expandVars(char *dst, const char *src, const char *exePath, const int pathL
852952
853953 if (strstr(varName, "FIND_ANCESTOR:") == varName)
854954 {
855- char *findName = varName + 14;
856- findAncestor(dst, exePath, findName);
955+ char *findNames = varName + 14;
956+ multiFindAncestor(dst, exePath, findNames);
957+ }
958+ else if (strstr(varName, "JRE_ARCH") == varName)
959+ {
960+ char *findName = varName + 8;
961+ jreArch(dst, findName);
857962 }
858963 else if (strcmp(varName, "EXEDIR") == 0)
859964 {
@@ -940,14 +1045,41 @@ void appendHeapSize(char *dst, const int megabytesID, const int percentID,
9401045 }
9411046 }
9421047
943-void setJvmOptions(char *jvmOptions, const char *exePath)
1048+void setJvmOptions(char *jvmOptions, const char *exePath, const int pathLen)
9441049 {
1050+ // リソースに埋め込んだ固定のJVMオプション
9451051 if (loadString(JVM_OPTIONS, jvmOptions))
9461052 {
9471053 strcat(jvmOptions, " ");
9481054 }
9491055
1056+ // *.cfgファイルからオプション引数の読み取り
1057+ char cfgPath[MAX_PATH];
1058+ getCfgPath(exePath, cfgPath);
1059+
1060+ char optbuf[MAX_VAR_SIZE] = { 0 }; // 32kbytes
1061+ char optValue[MAX_ARGS] = { 0 };
1062+ GetPrivateProfileString("JVM_OPTIONS", NULL, "", optbuf, sizeof(optbuf), cfgPath);
1063+
1064+ char *pOpt = optbuf;
1065+ char tmp[MAX_ARGS] = {0};
1066+ while (*pOpt)
1067+ {
1068+ GetPrivateProfileString("JVM_OPTIONS", pOpt, "", optValue, sizeof(optValue), cfgPath);
1069+
1070+ *tmp = 0;
1071+ expandVars(tmp, optValue, exePath, pathLen);
1072+ debug("Set jvm_option:\t%s = %s\n", pOpt, tmp);
1073+
1074+ // 変数展開済みオプションを追記
1075+ strcat(jvmOptions, tmp);
1076+ strcat(jvmOptions, " ");
1077+
1078+ while (*pOpt++);
1079+ }
1080+
9501081 /*
1082+ * ini設定ファイル からのJVMオプション
9511083 * Load additional JVM options from .l4j.ini file
9521084 * Options are separated by spaces or CRLF
9531085 * # starts an inline comment
@@ -956,13 +1088,17 @@ void setJvmOptions(char *jvmOptions, const char *exePath)
9561088
9571089 strncpy(iniFilePath, exePath, strlen(exePath) - 3);
9581090 strcat(iniFilePath, "l4j.ini");
1091+ debug("try loading 1:\t%s\n", iniFilePath);
9591092
9601093 long hFile;
9611094 if ((hFile = _open(iniFilePath, _O_RDONLY)) == -1)
9621095 {
9631096 // *.l4j.iniがなければ *.ini で試す
1097+ memset(iniFilePath, 0, sizeof(iniFilePath));
9641098 strncpy(iniFilePath, exePath, strlen(exePath) - 3);
965- strcat(iniFilePath, ".ini");
1099+ strcat(iniFilePath, "ini");
1100+
1101+ debug("try loading 2:\t%s\n", iniFilePath);
9661102 hFile = _open(iniFilePath, _O_RDONLY);
9671103 }
9681104
@@ -1044,6 +1180,49 @@ void setWorkingDirectory(const char *exePath, const int pathLen)
10441180 }
10451181 }
10461182
1183+BOOL isValidCfgJrePath(LPCTSTR jrePath, PE6432 *pPEType)
1184+{
1185+ // java.exeへのパス
1186+ char launcherPath[MAX_PATH] = { 0 };
1187+ strcpy(launcherPath, jrePath);
1188+ appendLauncher(launcherPath);
1189+
1190+ // 64/32bit判定
1191+ PE6432 peType = CheckPE6432(launcherPath);
1192+ if (pPEType)
1193+ {
1194+ *pPEType = peType;
1195+ }
1196+
1197+ if (peType != PE_UNKNOWN)
1198+ {
1199+ int runtimeBits = loadInt(RUNTIME_BITS);
1200+
1201+ switch (peType)
1202+ {
1203+ case PE_X86:
1204+ if (runtimeBits == USE_64_BIT_RUNTIME) {
1205+ // 64ビットを要求しているのにjava.exeが32ビットなので不可
1206+ return FALSE;
1207+ }
1208+ search.foundJava = FOUND_BUNDLED;
1209+ break;
1210+
1211+ case PE_X64:
1212+ if (!wow64 || runtimeBits == USE_32_BIT_RUNTIME) {
1213+ // 32ビットを要求しているのにjava.exeが64ビットなので不可
1214+ // もしくは現在64ビットOSでないのにjava.exeが64ビットの場合
1215+ // (本headは32ビットでビルドされるため、64ビットOSではwow64で実行される)
1216+ return FALSE;
1217+ }
1218+ search.foundJava = FOUND_BUNDLED | KEY_WOW64_64KEY;
1219+ break;
1220+ }
1221+ return TRUE;
1222+ }
1223+ return FALSE;
1224+}
1225+
10471226 BOOL cfgJreSearch(const char *exePath, int pathLen)
10481227 {
10491228 char tmpPath[MAX_PATH] = { 0 };
@@ -1057,16 +1236,23 @@ BOOL cfgJreSearch(const char *exePath, int pathLen)
10571236 char jrePath[MAX_ARGS] = {0};
10581237 expandVars(jrePath, tmpPath, exePath, pathLen);
10591238 debug("Config JRE:\t%s\n", jrePath);
1060-
1061- if (checkJavaExe(jrePath))
1239+
1240+ PE6432 peType = PE_UNKNOWN;
1241+ if (isValidCfgJrePath(jrePath, &peType))
10621242 {
10631243 strcpy(launcher.cmd, jrePath);
1064-
1065- if (isLauncherPathValid(launcher.cmd))
1244+ strcpy(search.foundJavaHome, launcher.cmd);
10661245 {
1067- search.foundJava = wow64 ? FOUND_BUNDLED | KEY_WOW64_64KEY : FOUND_BUNDLED;
1068- strcpy(search.foundJavaHome, launcher.cmd);
1069- return TRUE;
1246+ switch (peType)
1247+ {
1248+ case PE_X86:
1249+ search.foundJava = FOUND_BUNDLED;
1250+ return TRUE;
1251+
1252+ case PE_X64:
1253+ search.foundJava = FOUND_BUNDLED | KEY_WOW64_64KEY;
1254+ return TRUE;
1255+ }
10701256 }
10711257 }
10721258 }
@@ -1074,6 +1260,36 @@ BOOL cfgJreSearch(const char *exePath, int pathLen)
10741260 return FALSE;
10751261 }
10761262
1263+BOOL chooseJavaHome(char *path, PE6432 *pPEType)
1264+{
1265+ // フォルダ選択ダイアログに表示するメッセージはエラーメッセージを借用する
1266+ createJreSearchError();
1267+
1268+ BROWSEINFO bInfo = { 0 };
1269+ bInfo.hwndOwner = NULL;
1270+ bInfo.pidlRoot = NULL;
1271+ bInfo.pszDisplayName = path;
1272+ bInfo.lpszTitle = error.msg;
1273+ bInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
1274+
1275+ for (;;)
1276+ {
1277+ LPITEMIDLIST result = SHBrowseForFolder(&bInfo);
1278+ if (result == NULL)
1279+ {
1280+ // キャンセル
1281+ return FALSE;
1282+ }
1283+
1284+ SHGetPathFromIDList(result, path);
1285+
1286+ if (isValidCfgJrePath(path, pPEType))
1287+ {
1288+ return TRUE;
1289+ }
1290+ }
1291+}
1292+
10771293 BOOL bundledJreSearch(const char *exePath, const int pathLen)
10781294 {
10791295 debugAll("bundledJreSearch()\n");
@@ -1199,10 +1415,20 @@ BOOL jreSearch(const char *exePath, const int pathLen)
11991415 // バンドルの検索とレジストリの検索も失敗した場合
12001416 // ユーザーにJAVA_HOMEの選択を求める
12011417 char jrePath[MAX_PATH] = { 0 };
1202- if (chooseJavaHome(jrePath))
1418+ PE6432 peType = PE_UNKNOWN;
1419+ if (chooseJavaHome(jrePath, &peType))
12031420 {
1204- // JAVA_HOMEを選択した場合
1205- search.foundJava = wow64 ? FOUND_BUNDLED | KEY_WOW64_64KEY : FOUND_BUNDLED;
1421+ // 有効なJAVA_HOMEを選択した場合
1422+ switch (peType)
1423+ {
1424+ case PE_X86:
1425+ search.foundJava = FOUND_CHOOSED;
1426+ break;
1427+
1428+ case PE_X64:
1429+ search.foundJava = FOUND_CHOOSED | KEY_WOW64_64KEY;
1430+ break;
1431+ }
12061432 strcpy(launcher.cmd, jrePath);
12071433 strcpy(search.foundJavaHome, launcher.cmd);
12081434
@@ -1390,7 +1616,7 @@ void setCommandLineArgs(const char *lpCmdLine,
13901616 // Constant command line arguments
13911617 if (loadString(CMD_LINE, tmp))
13921618 {
1393- char tmp2[MAX_ARGS] = {0};
1619+ char tmp2[MAX_ARGS] = { 0 };
13941620 expandVars(tmp2, tmp, exePath, pathLen);
13951621 debug("constant commandline args: %s\r\n", tmp2);
13961622
@@ -1480,7 +1706,7 @@ int prepare(const char *lpCmdLine)
14801706 appendHeapSizes(launcher.args);
14811707
14821708 char jvmOptions[MAX_ARGS] = {0};
1483- setJvmOptions(jvmOptions, exePath);
1709+ setJvmOptions(jvmOptions, exePath, pathLen);
14841710 expandVars(launcher.args, jvmOptions, exePath, pathLen);
14851711 setMainClassAndClassPath(exePath, pathLen);
14861712 setCommandLineArgs(lpCmdLine, exePath, pathLen);
@@ -1514,35 +1740,40 @@ BOOL execute(const BOOL wait, DWORD *dwExitCode)
15141740 if (CreateProcess(NULL, cmdline, NULL, NULL,
15151741 TRUE, processPriority, NULL, NULL, &si, &processInformation))
15161742 {
1517- // プロセスが起動してすぐにエラーが落ちるかどうかを見極める
1518- WaitForInputIdle(processInformation.hProcess, 10000); // メッセージループのアイドルを待つ
1519- WaitForSingleObject(processInformation.hProcess, 3000); // 3秒まつ
1520-
1521- // 現時点の終了コードを得る
1522- GetExitCodeProcess(processInformation.hProcess, dwExitCode);
1523- debug("Java PreExitCode: %ld\n", *dwExitCode);
1524- if (*dwExitCode == STILL_ACTIVE)
1525- {
1526- // まだ終了していなければ0を仮設定する
1527- *dwExitCode = 0;
1528- }
1529-
1530- if (*dwExitCode == 0)
1743+ if ((search.foundJava & FOUND_CHOOSED) != 0)
15311744 {
1532- // 起動直後にエラーが発生しているのでなければ
1533- // JAVA_HOMEは正しかったものとみなし、
1534- // バンドルまたはレジストリからの検索に成功したJAVA_HOME、
1535- // またはユーザーが選択したJAVA_HOMEを、*.cfgに保存する
1536- // (仮に書き込み禁止等で書き込めなくても特段問題はない)
1537- char exePath[MAX_PATH] = { 0 };
1538- char cfgPath[MAX_PATH] = { 0 };
1539- getExePath(exePath);
1540- getCfgPath(exePath, cfgPath);
1541- int saveJavaHome = GetPrivateProfileInt("Settings", "SaveJavaHome", 1, cfgPath);
1542- if (saveJavaHome)
1745+ // ユーザーがJAVA_HOMEを選択して起動した場合は、
1746+ // プロセスが起動してすぐにエラーが落ちるかどうかを見極める
1747+ WaitForInputIdle(processInformation.hProcess, 10000); // メッセージループのアイドルを待つ
1748+ WaitForSingleObject(processInformation.hProcess, 3000); // 3秒まつ
1749+
1750+ // 現時点の終了コードを得る
1751+ GetExitCodeProcess(processInformation.hProcess, dwExitCode);
1752+ debug("Java PreExitCode: %ld\n", *dwExitCode);
1753+ if (*dwExitCode == STILL_ACTIVE)
15431754 {
1544- // JAVA_HOMEの保存フラグが0でなければ使用したJAVA_HOMEを記録する
1545- WritePrivateProfileString("Settings", "JAVA_HOME", search.foundJavaHome, cfgPath);
1755+ // まだ終了していなければ0を仮設定する
1756+ *dwExitCode = 0;
1757+ }
1758+
1759+ if (*dwExitCode == 0)
1760+ {
1761+ // 起動直後にエラーが発生しているのでなければ
1762+ // JAVA_HOMEは正しかったものとみなし、
1763+ // バンドルまたはレジストリからの検索に成功したJAVA_HOME、
1764+ // またはユーザーが選択したJAVA_HOMEを、*.cfgに保存する
1765+ // (仮に書き込み禁止等で書き込めなくても特段問題はない)
1766+ char exePath[MAX_PATH] = { 0 };
1767+ char cfgPath[MAX_PATH] = { 0 };
1768+ getExePath(exePath);
1769+ getCfgPath(exePath, cfgPath);
1770+
1771+ int saveJavaHome = GetPrivateProfileInt("Settings", "SaveJavaHome", 1, cfgPath);
1772+ if (saveJavaHome)
1773+ {
1774+ // JAVA_HOMEの保存フラグが0でなければ使用したJAVA_HOMEを記録する
1775+ WritePrivateProfileString("Settings", "JAVA_HOME", search.foundJavaHome, cfgPath);
1776+ }
15461777 }
15471778 }
15481779
--- a/src/Launch4JStub/head_src/head.h
+++ b/src/Launch4JStub/head_src/head.h
@@ -64,6 +64,7 @@
6464 #define FOUND_JRE 1
6565 #define FOUND_SDK 2
6666 #define FOUND_BUNDLED 4
67+#define FOUND_CHOOSED 8
6768
6869 #define JRE_ONLY 0
6970 #define PREFER_JRE 1
@@ -94,7 +95,7 @@
9495 #define FALSE_STR "false"
9596
9697 #define ERROR_FORMAT "Error:\t\t%s\n"
97-#define debug(args...) if (hLog != NULL) fprintf(hLog, ## args);
98+#define debug(args...) if (hLog != NULL) { fprintf(hLog, ## args); fflush(hLog); }
9899 #define debugAll(args...) if (debugAll && hLog != NULL) fprintf(hLog, ## args);
99100
100101 typedef void (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
@@ -126,7 +127,7 @@ BOOL expandVars(char *dst, const char *src, const char *exePath, const int pathL
126127 void appendHeapSizes(char *dst);
127128 void appendHeapSize(char *dst, const int megabytesID, const int percentID,
128129 const DWORDLONG availableMemory, const char *option);
129-void setJvmOptions(char *jvmOptions, const char *exePath);
130+void setJvmOptions(char *jvmOptions, const char *exePath, const int pathLen);
130131 BOOL createMutex();
131132 void setWorkingDirectory(const char *exePath, const int pathLen);
132133 BOOL bundledJreSearch(const char *exePath, const int pathLen);
Show on old repository browser