Upgrade to launch4j 3.0.1 2008-07-20.
The license is BSD for launch4j and MIT for the wrapper code in head/ Changelog is in installer/lib/launch4j/web/changelog.html Hopefully this will fix installs for 64-bit JRE on 64-bit windows. The previous version was 2.0-RC3 2005-08-13. The previous license was GPLv2 for launch4j and LGPLv2.1 for the wrapper code in head/ The bin/ld.exe and bin/windres.exe files were contributed by i2p users in 2005 so the i2p installer could be built on windows. They have not been updated for 3.0.1, so pkg builds on windows will presumably still get 2.0-RC3.
This commit is contained in:
@ -1,43 +1,85 @@
|
||||
/*
|
||||
Launch4j (http://launch4j.sourceforge.net/)
|
||||
Cross-platform Java application wrapper for creating Windows native executables.
|
||||
|
||||
launch4j :: Cross-platform Java application wrapper for creating Windows native executables
|
||||
Copyright (C) 2004-2005 Grzegorz Kowal
|
||||
Copyright (c) 2004, 2008 Grzegorz Kowal,
|
||||
Ian Roberts (jdk preference patch)
|
||||
Sylvain Mina (single instance patch)
|
||||
|
||||
Compiled with Mingw port of GCC, Bloodshed Dev-C++ IDE (http://www.bloodshed.net/devcpp.html)
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Except as contained in this notice, the name(s) of the above copyright holders
|
||||
shall not be used in advertising or otherwise to promote the sale, use or other
|
||||
dealings in this Software without prior written authorization.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "resource.h"
|
||||
#include "head.h"
|
||||
|
||||
HMODULE hModule;
|
||||
FILE* hLog;
|
||||
BOOL console = FALSE;
|
||||
BOOL wow64 = FALSE;
|
||||
int foundJava = NO_JAVA_FOUND;
|
||||
|
||||
struct _stat statBuf;
|
||||
PROCESS_INFORMATION pi;
|
||||
DWORD priority;
|
||||
|
||||
char errTitle[STR] = "launch4j";
|
||||
char javaMinVer[STR] = "";
|
||||
char javaMaxVer[STR] = "";
|
||||
char foundJavaVer[STR] = "";
|
||||
char mutexName[STR] = {0};
|
||||
|
||||
char workingDir[_MAX_PATH] = "";
|
||||
char cmd[_MAX_PATH] = "";
|
||||
char args[BIG_STR * 2] = "";
|
||||
char errUrl[256] = {0};
|
||||
char errTitle[STR] = "Launch4j";
|
||||
char errMsg[BIG_STR] = {0};
|
||||
|
||||
char javaMinVer[STR] = {0};
|
||||
char javaMaxVer[STR] = {0};
|
||||
char foundJavaVer[STR] = {0};
|
||||
char foundJavaKey[_MAX_PATH] = {0};
|
||||
|
||||
char oldPwd[_MAX_PATH] = {0};
|
||||
char workingDir[_MAX_PATH] = {0};
|
||||
char cmd[_MAX_PATH] = {0};
|
||||
char args[MAX_ARGS] = {0};
|
||||
|
||||
FILE* openLogFile(const char* exePath, const int pathLen) {
|
||||
char path[_MAX_PATH] = {0};
|
||||
strncpy(path, exePath, pathLen);
|
||||
strcat(path, "\\launch4j.log");
|
||||
return fopen(path, "a");
|
||||
}
|
||||
|
||||
void closeLogFile() {
|
||||
if (hLog != NULL) {
|
||||
fclose(hLog);
|
||||
}
|
||||
}
|
||||
|
||||
void setWow64Flag() {
|
||||
LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(
|
||||
GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
|
||||
|
||||
if (fnIsWow64Process != NULL) {
|
||||
fnIsWow64Process(GetCurrentProcess(), &wow64);
|
||||
}
|
||||
debug("WOW64:\t\t%s\n", wow64 ? "yes" : "no");
|
||||
}
|
||||
|
||||
void setConsoleFlag() {
|
||||
console = TRUE;
|
||||
@ -51,19 +93,43 @@ void msgBox(const char* text) {
|
||||
}
|
||||
}
|
||||
|
||||
void showJavaWebPage() {
|
||||
ShellExecute(NULL, "open", "http://java.com", NULL, NULL, SW_SHOWNORMAL);
|
||||
void signalError() {
|
||||
DWORD err = GetLastError();
|
||||
if (err) {
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
||||
| FORMAT_MESSAGE_FROM_SYSTEM
|
||||
| FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
err,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL);
|
||||
debug("Error:\t\t%s\n", (LPCTSTR) lpMsgBuf);
|
||||
strcat(errMsg, "\n\n");
|
||||
strcat(errMsg, (LPCTSTR) lpMsgBuf);
|
||||
msgBox(errMsg);
|
||||
LocalFree(lpMsgBuf);
|
||||
} else {
|
||||
msgBox(errMsg);
|
||||
}
|
||||
if (*errUrl) {
|
||||
debug("Open URL:\t%s\n", errUrl);
|
||||
ShellExecute(NULL, "open", errUrl, NULL, NULL, SW_SHOWNORMAL);
|
||||
}
|
||||
closeLogFile();
|
||||
}
|
||||
|
||||
BOOL loadString(HMODULE hLibrary, int resID, char* buffer) {
|
||||
BOOL loadString(const int resID, char* buffer) {
|
||||
HRSRC hResource;
|
||||
HGLOBAL hResourceLoaded;
|
||||
LPBYTE lpBuffer;
|
||||
|
||||
hResource = FindResourceEx(hLibrary, RT_RCDATA, MAKEINTRESOURCE(resID),
|
||||
hResource = FindResourceEx(hModule, RT_RCDATA, MAKEINTRESOURCE(resID),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT));
|
||||
if (NULL != hResource) {
|
||||
hResourceLoaded = LoadResource(hLibrary, hResource);
|
||||
hResourceLoaded = LoadResource(hModule, hResource);
|
||||
if (NULL != hResourceLoaded) {
|
||||
lpBuffer = (LPBYTE) LockResource(hResourceLoaded);
|
||||
if (NULL != lpBuffer) {
|
||||
@ -71,24 +137,76 @@ BOOL loadString(HMODULE hLibrary, int resID, char* buffer) {
|
||||
do {
|
||||
buffer[x] = (char) lpBuffer[x];
|
||||
} while (buffer[x++] != 0);
|
||||
// debug("Resource %d:\t%s\n", resID, buffer);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SetLastError(0);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL loadBoolString(HMODULE hLibrary, int resID) {
|
||||
char boolStr[10] = "";
|
||||
loadString(hLibrary, resID, boolStr);
|
||||
BOOL loadBool(const int resID) {
|
||||
char boolStr[20] = {0};
|
||||
loadString(resID, boolStr);
|
||||
return strcmp(boolStr, TRUE_STR) == 0;
|
||||
}
|
||||
|
||||
void regSearch(HKEY hKey, char* keyName, int searchType) {
|
||||
int loadInt(const int resID) {
|
||||
char intStr[20] = {0};
|
||||
loadString(resID, intStr);
|
||||
return atoi(intStr);
|
||||
}
|
||||
|
||||
BOOL regQueryValue(const char* regPath, unsigned char* buffer,
|
||||
unsigned long bufferLength) {
|
||||
HKEY hRootKey;
|
||||
char* key;
|
||||
char* value;
|
||||
if (strstr(regPath, HKEY_CLASSES_ROOT_STR) == regPath) {
|
||||
hRootKey = HKEY_CLASSES_ROOT;
|
||||
} else if (strstr(regPath, HKEY_CURRENT_USER_STR) == regPath) {
|
||||
hRootKey = HKEY_CURRENT_USER;
|
||||
} else if (strstr(regPath, HKEY_LOCAL_MACHINE_STR) == regPath) {
|
||||
hRootKey = HKEY_LOCAL_MACHINE;
|
||||
} else if (strstr(regPath, HKEY_USERS_STR) == regPath) {
|
||||
hRootKey = HKEY_USERS;
|
||||
} else if (strstr(regPath, HKEY_CURRENT_CONFIG_STR) == regPath) {
|
||||
hRootKey = HKEY_CURRENT_CONFIG;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
key = strchr(regPath, '\\') + 1;
|
||||
value = strrchr(regPath, '\\') + 1;
|
||||
*(value - 1) = 0;
|
||||
|
||||
HKEY hKey;
|
||||
unsigned long datatype;
|
||||
BOOL result = FALSE;
|
||||
if ((wow64 && RegOpenKeyEx(hRootKey,
|
||||
key,
|
||||
0,
|
||||
KEY_READ | KEY_WOW64_64KEY,
|
||||
&hKey) == ERROR_SUCCESS)
|
||||
|| RegOpenKeyEx(hRootKey,
|
||||
key,
|
||||
0,
|
||||
KEY_READ,
|
||||
&hKey) == ERROR_SUCCESS) {
|
||||
result = RegQueryValueEx(hKey, value, NULL, &datatype, buffer, &bufferLength)
|
||||
== ERROR_SUCCESS;
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
*(value - 1) = '\\';
|
||||
return result;
|
||||
}
|
||||
|
||||
void regSearch(const HKEY hKey, const char* keyName, const int searchType) {
|
||||
DWORD x = 0;
|
||||
unsigned long size = BIG_STR;
|
||||
FILETIME time;
|
||||
char buffer[BIG_STR] = "";
|
||||
char buffer[BIG_STR] = {0};
|
||||
while (RegEnumKeyEx(
|
||||
hKey, // handle to key to enumerate
|
||||
x++, // index of subkey to enumerate
|
||||
@ -98,61 +216,92 @@ void regSearch(HKEY hKey, char* keyName, int searchType) {
|
||||
NULL, // address of buffer for class string
|
||||
NULL, // address for size of class buffer
|
||||
&time) == ERROR_SUCCESS) {
|
||||
|
||||
if (strcmp(buffer, javaMinVer) >= 0
|
||||
&& (javaMaxVer[0] == 0 || strcmp(buffer, javaMaxVer) <= 0)
|
||||
&& (!*javaMaxVer || strcmp(buffer, javaMaxVer) <= 0)
|
||||
&& strcmp(buffer, foundJavaVer) > 0) {
|
||||
strcpy(foundJavaVer, buffer);
|
||||
strcpy(foundJavaKey, keyName);
|
||||
appendPath(foundJavaKey, buffer);
|
||||
foundJava = searchType;
|
||||
debug("Match:\t\t%s\\%s\n", keyName, buffer);
|
||||
} else {
|
||||
debug("Ignore:\t\t%s\\%s\n", keyName, buffer);
|
||||
}
|
||||
size = BIG_STR;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL findJavaHome(char* path) {
|
||||
void regSearchWow(const char* keyName, const int searchType) {
|
||||
HKEY hKey;
|
||||
char jre[] = "SOFTWARE\\JavaSoft\\Java Runtime Environment";
|
||||
char sdk[] = "SOFTWARE\\JavaSoft\\Java Development Kit";
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||
TEXT(jre),
|
||||
debug("64-bit search:\t%s...\n", keyName);
|
||||
if (wow64 && RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||
keyName,
|
||||
0,
|
||||
KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
|
||||
KEY_READ | KEY_WOW64_64KEY,
|
||||
&hKey) == ERROR_SUCCESS) {
|
||||
regSearch(hKey, jre, FOUND_JRE);
|
||||
|
||||
regSearch(hKey, keyName, searchType | KEY_WOW64_64KEY);
|
||||
RegCloseKey(hKey);
|
||||
if ((foundJava & KEY_WOW64_64KEY) != NO_JAVA_FOUND)
|
||||
{
|
||||
debug("Using 64-bit runtime.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
debug("32-bit search:\t%s...\n", keyName);
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||
keyName,
|
||||
0,
|
||||
KEY_READ,
|
||||
&hKey) == ERROR_SUCCESS) {
|
||||
regSearch(hKey, keyName, searchType);
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||
TEXT(sdk),
|
||||
0,
|
||||
KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
|
||||
&hKey) == ERROR_SUCCESS) {
|
||||
regSearch(hKey, sdk, FOUND_SDK);
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
void regSearchJreSdk(const char* jreKeyName, const char* sdkKeyName,
|
||||
const int jdkPreference) {
|
||||
if (jdkPreference == JDK_ONLY || jdkPreference == PREFER_JDK) {
|
||||
regSearchWow(sdkKeyName, FOUND_SDK);
|
||||
if (jdkPreference != JDK_ONLY) {
|
||||
regSearchWow(jreKeyName, FOUND_JRE);
|
||||
}
|
||||
} else { // jdkPreference == JRE_ONLY or PREFER_JRE
|
||||
regSearchWow(jreKeyName, FOUND_JRE);
|
||||
if (jdkPreference != JRE_ONLY) {
|
||||
regSearchWow(sdkKeyName, FOUND_SDK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL findJavaHome(char* path, const int jdkPreference) {
|
||||
regSearchJreSdk("SOFTWARE\\JavaSoft\\Java Runtime Environment",
|
||||
"SOFTWARE\\JavaSoft\\Java Development Kit",
|
||||
jdkPreference);
|
||||
if (foundJava == NO_JAVA_FOUND) {
|
||||
regSearchJreSdk("SOFTWARE\\IBM\\Java2 Runtime Environment",
|
||||
"SOFTWARE\\IBM\\Java Development Kit",
|
||||
jdkPreference);
|
||||
}
|
||||
if (foundJava != NO_JAVA_FOUND) {
|
||||
char keyBuffer[BIG_STR];
|
||||
unsigned long datatype;
|
||||
unsigned long bufferlength = BIG_STR;
|
||||
if (foundJava == FOUND_JRE) {
|
||||
strcpy(keyBuffer, jre);
|
||||
} else {
|
||||
strcpy(keyBuffer, sdk);
|
||||
}
|
||||
strcat(keyBuffer, "\\");
|
||||
strcat(keyBuffer, foundJavaVer);
|
||||
HKEY hKey;
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||
TEXT(keyBuffer),
|
||||
0,
|
||||
KEY_QUERY_VALUE,
|
||||
&hKey) == ERROR_SUCCESS) {
|
||||
unsigned char buffer[BIG_STR];
|
||||
if (RegQueryValueEx(hKey, "JavaHome", NULL, &datatype, buffer, &bufferlength)
|
||||
== ERROR_SUCCESS) {
|
||||
foundJavaKey,
|
||||
0,
|
||||
KEY_READ | (foundJava & KEY_WOW64_64KEY),
|
||||
&hKey) == ERROR_SUCCESS) {
|
||||
unsigned char buffer[BIG_STR] = {0};
|
||||
unsigned long bufferlength = BIG_STR;
|
||||
unsigned long datatype;
|
||||
if (RegQueryValueEx(hKey, "JavaHome", NULL, &datatype, buffer,
|
||||
&bufferlength) == ERROR_SUCCESS) {
|
||||
int i = 0;
|
||||
do {
|
||||
path[i] = buffer[i];
|
||||
} while (path[i++] != 0);
|
||||
if (foundJava == FOUND_SDK) {
|
||||
strcat(path, "\\jre");
|
||||
if (foundJava & FOUND_SDK) {
|
||||
appendPath(path, "jre");
|
||||
}
|
||||
RegCloseKey(hKey);
|
||||
return TRUE;
|
||||
@ -164,66 +313,93 @@ BOOL findJavaHome(char* path) {
|
||||
}
|
||||
|
||||
/*
|
||||
* extract the executable name, returns path length.
|
||||
* Extract the executable name, returns path length.
|
||||
*/
|
||||
int getExePath(char* exePath) {
|
||||
HMODULE hModule = GetModuleHandle(NULL);
|
||||
if (hModule == 0
|
||||
|| GetModuleFileName(hModule, exePath, _MAX_PATH) == 0) {
|
||||
if (GetModuleFileName(hModule, exePath, _MAX_PATH) == 0) {
|
||||
return -1;
|
||||
}
|
||||
return strrchr(exePath, '\\') - exePath;
|
||||
}
|
||||
|
||||
void appendPath(char* basepath, const char* path) {
|
||||
if (basepath[strlen(basepath) - 1] != '\\') {
|
||||
strcat(basepath, "\\");
|
||||
}
|
||||
strcat(basepath, path);
|
||||
}
|
||||
|
||||
void appendJavaw(char* jrePath) {
|
||||
if (console) {
|
||||
strcat(jrePath, "\\bin\\java.exe");
|
||||
appendPath(jrePath, "bin\\java.exe");
|
||||
} else {
|
||||
strcat(jrePath, "\\bin\\javaw.exe");
|
||||
appendPath(jrePath, "bin\\javaw.exe");
|
||||
}
|
||||
}
|
||||
|
||||
void appendLauncher(BOOL setProcName, char* exePath, int pathLen, char* cmd) {
|
||||
void appendLauncher(const BOOL setProcName, char* exePath,
|
||||
const int pathLen, char* cmd) {
|
||||
if (setProcName) {
|
||||
char tmpspec[_MAX_PATH] = "";
|
||||
char tmpfile[_MAX_PATH] = "";
|
||||
char tmpspec[_MAX_PATH];
|
||||
char tmpfile[_MAX_PATH];
|
||||
strcpy(tmpspec, cmd);
|
||||
strcat(tmpspec, LAUNCH4J_TMP_DIR);
|
||||
tmpspec[strlen(tmpspec) - 1] = 0;
|
||||
if (_stat(tmpspec, &statBuf) == 0) {
|
||||
// remove temp launchers
|
||||
// Remove temp launchers and manifests
|
||||
struct _finddata_t c_file;
|
||||
long hFile;
|
||||
strcat(tmpspec, "\\*.exe");
|
||||
appendPath(tmpspec, "*.exe");
|
||||
strcpy(tmpfile, cmd);
|
||||
strcat(tmpfile, LAUNCH4J_TMP_DIR);
|
||||
char* filename = tmpfile + strlen(tmpfile);
|
||||
if ((hFile = _findfirst(tmpspec, &c_file)) != -1L) {
|
||||
do {
|
||||
strcpy(filename, c_file.name);
|
||||
debug("Unlink:\t\t%s\n", tmpfile);
|
||||
_unlink(tmpfile);
|
||||
strcat(tmpfile, MANIFEST);
|
||||
debug("Unlink:\t\t%s\n", tmpfile);
|
||||
_unlink(tmpfile);
|
||||
} while (_findnext(hFile, &c_file) == 0);
|
||||
}
|
||||
_findclose(hFile);
|
||||
} else {
|
||||
if (_mkdir(tmpspec) != 0) {
|
||||
debug("Mkdir failed:\t%s\n", tmpspec);
|
||||
appendJavaw(cmd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
char javaw[_MAX_PATH] = "";
|
||||
char javaw[_MAX_PATH];
|
||||
strcpy(javaw, cmd);
|
||||
appendJavaw(javaw);
|
||||
strcpy(tmpfile, cmd);
|
||||
strcat(tmpfile, LAUNCH4J_TMP_DIR);
|
||||
char* tmpfilename = tmpfile + strlen(tmpfile);
|
||||
char* exeFilePart = exePath + pathLen + 1;
|
||||
strcat(tmpfile, exeFilePart);
|
||||
|
||||
// Copy manifest
|
||||
char manifest[_MAX_PATH] = {0};
|
||||
strcpy(manifest, exePath);
|
||||
strcat(manifest, MANIFEST);
|
||||
if (_stat(manifest, &statBuf) == 0) {
|
||||
strcat(tmpfile, exeFilePart);
|
||||
strcat(tmpfile, MANIFEST);
|
||||
debug("Copy:\t\t%s -> %s\n", manifest, tmpfile);
|
||||
CopyFile(manifest, tmpfile, FALSE);
|
||||
}
|
||||
|
||||
// Copy launcher
|
||||
strcpy(tmpfilename, exeFilePart);
|
||||
debug("Copy:\t\t%s -> %s\n", javaw, tmpfile);
|
||||
if (CopyFile(javaw, tmpfile, FALSE)) {
|
||||
strcpy(cmd, tmpfile);
|
||||
return;
|
||||
} else {
|
||||
} else if (_stat(javaw, &statBuf) == 0) {
|
||||
long fs = statBuf.st_size;
|
||||
if (_stat(tmpfile, &statBuf) == 0 && fs == statBuf.st_size) {
|
||||
debug("Reusing:\t\t%s\n", tmpfile);
|
||||
strcpy(cmd, tmpfile);
|
||||
return;
|
||||
}
|
||||
@ -232,123 +408,396 @@ void appendLauncher(BOOL setProcName, char* exePath, int pathLen, char* cmd) {
|
||||
appendJavaw(cmd);
|
||||
}
|
||||
|
||||
BOOL isJrePathOk(char* path) {
|
||||
if (!*path) {
|
||||
return FALSE;
|
||||
void appendAppClasspath(char* dst, const char* src, const char* classpath) {
|
||||
strcat(dst, src);
|
||||
if (*classpath) {
|
||||
strcat(dst, ";");
|
||||
}
|
||||
char javaw[_MAX_PATH];
|
||||
strcpy(javaw, path);
|
||||
appendJavaw(javaw);
|
||||
return _stat(javaw, &statBuf) == 0;
|
||||
}
|
||||
|
||||
BOOL prepare(HMODULE hLibrary, char *lpCmdLine) {
|
||||
// open executable
|
||||
char exePath[_MAX_PATH] = "";
|
||||
BOOL isJrePathOk(const char* path) {
|
||||
char javaw[_MAX_PATH];
|
||||
BOOL result = FALSE;
|
||||
if (*path) {
|
||||
strcpy(javaw, path);
|
||||
appendJavaw(javaw);
|
||||
result = _stat(javaw, &statBuf) == 0;
|
||||
}
|
||||
debug("Check launcher:\t%s %s\n", javaw, result ? "(OK)" : "(n/a)");
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand environment %variables%
|
||||
*/
|
||||
BOOL expandVars(char *dst, const char *src, const char *exePath, const int pathLen) {
|
||||
char varName[STR];
|
||||
char varValue[MAX_VAR_SIZE];
|
||||
while (strlen(src) > 0) {
|
||||
char *start = strchr(src, '%');
|
||||
if (start != NULL) {
|
||||
char *end = strchr(start + 1, '%');
|
||||
if (end == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
// Copy content up to %VAR%
|
||||
strncat(dst, src, start - src);
|
||||
// Insert value of %VAR%
|
||||
*varName = 0;
|
||||
strncat(varName, start + 1, end - start - 1);
|
||||
// Remember value start for logging
|
||||
char *varValue = dst + strlen(dst);
|
||||
if (strcmp(varName, "EXEDIR") == 0) {
|
||||
strncat(dst, exePath, pathLen);
|
||||
} else if (strcmp(varName, "EXEFILE") == 0) {
|
||||
strcat(dst, exePath);
|
||||
} else if (strcmp(varName, "PWD") == 0) {
|
||||
GetCurrentDirectory(_MAX_PATH, dst + strlen(dst));
|
||||
} else if (strcmp(varName, "OLDPWD") == 0) {
|
||||
strcat(dst, oldPwd);
|
||||
} else if (strstr(varName, HKEY_STR) == varName) {
|
||||
regQueryValue(varName, dst + strlen(dst), BIG_STR);
|
||||
} else if (GetEnvironmentVariable(varName, varValue, MAX_VAR_SIZE) > 0) {
|
||||
strcat(dst, varValue);
|
||||
}
|
||||
debug("Substitute:\t%s = %s\n", varName, varValue);
|
||||
src = end + 1;
|
||||
} else {
|
||||
// Copy remaining content
|
||||
strcat(dst, src);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void appendHeapSizes(char *dst) {
|
||||
MEMORYSTATUS m;
|
||||
memset(&m, 0, sizeof(m));
|
||||
GlobalMemoryStatus(&m);
|
||||
|
||||
appendHeapSize(dst, INITIAL_HEAP_SIZE, INITIAL_HEAP_PERCENT,
|
||||
m.dwAvailPhys, "-Xms");
|
||||
appendHeapSize(dst, MAX_HEAP_SIZE, MAX_HEAP_PERCENT,
|
||||
m.dwAvailPhys, "-Xmx");
|
||||
}
|
||||
|
||||
void appendHeapSize(char *dst, const int absID, const int percentID,
|
||||
const DWORD freeMemory, const char *option) {
|
||||
|
||||
const int mb = 1048576; // 1 MB
|
||||
int abs = loadInt(absID);
|
||||
int percent = loadInt(percentID);
|
||||
int free = (long long) freeMemory * percent / (100 * mb); // 100% * 1 MB
|
||||
int size = free > abs ? free : abs;
|
||||
if (size > 0) {
|
||||
debug("Heap %s:\t%d MB / %d%%, Free: %d MB, Heap size: %d MB\n",
|
||||
option, abs, percent, freeMemory / mb, size);
|
||||
strcat(dst, option);
|
||||
_itoa(size, dst + strlen(dst), 10); // 10 -- radix
|
||||
strcat(dst, "m ");
|
||||
}
|
||||
}
|
||||
|
||||
int prepare(const char *lpCmdLine) {
|
||||
char tmp[MAX_ARGS] = {0};
|
||||
hModule = GetModuleHandle(NULL);
|
||||
if (hModule == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Get executable path
|
||||
char exePath[_MAX_PATH] = {0};
|
||||
int pathLen = getExePath(exePath);
|
||||
if (pathLen == -1) {
|
||||
msgBox("Cannot determinate exe file name.");
|
||||
return FALSE;
|
||||
}
|
||||
hLibrary = LoadLibrary(exePath);
|
||||
if (hLibrary == NULL) {
|
||||
char msg[BIG_STR] = "Cannot find file: ";
|
||||
strcat(msg, exePath);
|
||||
msgBox(msg);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// error message box title
|
||||
loadString(hLibrary, ERR_TITLE, errTitle);
|
||||
|
||||
// working dir
|
||||
char tmp_path[_MAX_PATH] = "";
|
||||
if (loadString(hLibrary, CHDIR, tmp_path)) {
|
||||
strncpy(workingDir, exePath, pathLen);
|
||||
strcat(workingDir, "/");
|
||||
strcat(workingDir, tmp_path);
|
||||
_chdir(workingDir);
|
||||
}
|
||||
|
||||
// custom process name
|
||||
const BOOL setProcName = loadBoolString(hLibrary, SET_PROC_NAME);
|
||||
|
||||
// use bundled jre or find java
|
||||
if (loadString(hLibrary, JRE_PATH, tmp_path)) {
|
||||
strncpy(cmd, exePath, pathLen);
|
||||
strcat(cmd, "/");
|
||||
strcat(cmd, tmp_path);
|
||||
}
|
||||
if (!isJrePathOk(cmd)) {
|
||||
if (!loadString(hLibrary, JAVA_MIN_VER, javaMinVer)) {
|
||||
msgBox("Cannot find bundled JRE or javaw.exe is missing.");
|
||||
// Initialize logging
|
||||
if (strstr(lpCmdLine, "--l4j-debug") != NULL) {
|
||||
hLog = openLogFile(exePath, pathLen);
|
||||
if (hLog == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
loadString(hLibrary, JAVA_MAX_VER, javaMaxVer);
|
||||
if (!findJavaHome(cmd)) {
|
||||
char txt[BIG_STR] = "Cannot find Java ";
|
||||
strcat(txt, javaMinVer);
|
||||
debug("\n\nCmdLine:\t%s %s\n", exePath, lpCmdLine);
|
||||
}
|
||||
|
||||
setWow64Flag();
|
||||
|
||||
// Set default error message, title and optional support web site url.
|
||||
loadString(SUPPORT_URL, errUrl);
|
||||
loadString(ERR_TITLE, errTitle);
|
||||
if (!loadString(STARTUP_ERR, errMsg)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Single instance
|
||||
loadString(MUTEX_NAME, mutexName);
|
||||
if (*mutexName) {
|
||||
SECURITY_ATTRIBUTES security;
|
||||
security.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
security.bInheritHandle = TRUE;
|
||||
security.lpSecurityDescriptor = NULL;
|
||||
CreateMutexA(&security, FALSE, mutexName);
|
||||
if (GetLastError() == ERROR_ALREADY_EXISTS) {
|
||||
debug("Instance already exists.");
|
||||
return ERROR_ALREADY_EXISTS;
|
||||
}
|
||||
}
|
||||
|
||||
// Working dir
|
||||
char tmp_path[_MAX_PATH] = {0};
|
||||
GetCurrentDirectory(_MAX_PATH, oldPwd);
|
||||
if (loadString(CHDIR, tmp_path)) {
|
||||
strncpy(workingDir, exePath, pathLen);
|
||||
appendPath(workingDir, tmp_path);
|
||||
_chdir(workingDir);
|
||||
debug("Working dir:\t%s\n", workingDir);
|
||||
}
|
||||
|
||||
// Use bundled jre or find java
|
||||
if (loadString(JRE_PATH, tmp_path)) {
|
||||
char jrePath[MAX_ARGS] = {0};
|
||||
expandVars(jrePath, tmp_path, exePath, pathLen);
|
||||
debug("Bundled JRE:\t%s\n", jrePath);
|
||||
if (jrePath[0] == '\\' || jrePath[1] == ':') {
|
||||
// Absolute
|
||||
strcpy(cmd, jrePath);
|
||||
} else {
|
||||
// Relative
|
||||
strncpy(cmd, exePath, pathLen);
|
||||
appendPath(cmd, jrePath);
|
||||
}
|
||||
}
|
||||
if (!isJrePathOk(cmd)) {
|
||||
if (!loadString(JAVA_MIN_VER, javaMinVer)) {
|
||||
loadString(BUNDLED_JRE_ERR, errMsg);
|
||||
return FALSE;
|
||||
}
|
||||
loadString(JAVA_MAX_VER, javaMaxVer);
|
||||
if (!findJavaHome(cmd, loadInt(JDK_PREFERENCE))) {
|
||||
loadString(JRE_VERSION_ERR, errMsg);
|
||||
strcat(errMsg, " ");
|
||||
strcat(errMsg, javaMinVer);
|
||||
if (*javaMaxVer) {
|
||||
strcat(txt, " - ");
|
||||
strcat(txt, javaMaxVer);
|
||||
strcat(errMsg, " - ");
|
||||
strcat(errMsg, javaMaxVer);
|
||||
}
|
||||
msgBox(txt);
|
||||
showJavaWebPage();
|
||||
loadString(DOWNLOAD_URL, errUrl);
|
||||
return FALSE;
|
||||
}
|
||||
if (!isJrePathOk(cmd)) {
|
||||
msgBox("Java found, but javaw.exe seems to be missing.");
|
||||
loadString(LAUNCHER_ERR, errMsg);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Append a path to the Path environment variable
|
||||
char jreBinPath[_MAX_PATH];
|
||||
strcpy(jreBinPath, cmd);
|
||||
strcat(jreBinPath, "\\bin");
|
||||
if (!appendToPathVar(jreBinPath)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Set environment variables
|
||||
char envVars[MAX_VAR_SIZE] = {0};
|
||||
loadString(ENV_VARIABLES, envVars);
|
||||
char *var = strtok(envVars, "\t");
|
||||
while (var != NULL) {
|
||||
char *varValue = strchr(var, '=');
|
||||
*varValue++ = 0;
|
||||
*tmp = 0;
|
||||
expandVars(tmp, varValue, exePath, pathLen);
|
||||
debug("Set var:\t%s = %s\n", var, tmp);
|
||||
SetEnvironmentVariable(var, tmp);
|
||||
var = strtok(NULL, "\t");
|
||||
}
|
||||
*tmp = 0;
|
||||
|
||||
// Process priority
|
||||
priority = loadInt(PRIORITY_CLASS);
|
||||
|
||||
// Custom process name
|
||||
const BOOL setProcName = loadBool(SET_PROC_NAME)
|
||||
&& strstr(lpCmdLine, "--l4j-default-proc") == NULL;
|
||||
const BOOL wrapper = loadBool(WRAPPER);
|
||||
|
||||
appendLauncher(setProcName, exePath, pathLen, cmd);
|
||||
|
||||
char jarArgs[BIG_STR] = "";
|
||||
loadString(hLibrary, JAR_ARGS, jarArgs);
|
||||
loadString(hLibrary, JVM_ARGS, args);
|
||||
if (*args) {
|
||||
strcat(args, " ");
|
||||
}
|
||||
strcat(args, "-jar \"");
|
||||
strcat(args, exePath);
|
||||
strcat(args, "\"");
|
||||
if (*jarArgs) {
|
||||
strcat(args, " ");
|
||||
strcat(args, jarArgs);
|
||||
}
|
||||
if (*lpCmdLine) {
|
||||
strcat(args, " ");
|
||||
strcat(args, lpCmdLine);
|
||||
// Heap sizes
|
||||
appendHeapSizes(args);
|
||||
|
||||
// JVM options
|
||||
if (loadString(JVM_OPTIONS, tmp)) {
|
||||
strcat(tmp, " ");
|
||||
} else {
|
||||
*tmp = 0;
|
||||
}
|
||||
/*
|
||||
* Load additional JVM options from .l4j.ini file
|
||||
* Options are separated by spaces or CRLF
|
||||
* # starts an inline comment
|
||||
*/
|
||||
strncpy(tmp_path, exePath, strlen(exePath) - 3);
|
||||
strcat(tmp_path, "l4j.ini");
|
||||
long hFile;
|
||||
if ((hFile = _open(tmp_path, _O_RDONLY)) != -1) {
|
||||
const int jvmOptLen = strlen(tmp);
|
||||
char* src = tmp + jvmOptLen;
|
||||
char* dst = src;
|
||||
const int len = _read(hFile, src, MAX_ARGS - jvmOptLen - BIG_STR);
|
||||
BOOL copy = TRUE;
|
||||
int i;
|
||||
for (i = 0; i < len; i++, src++) {
|
||||
if (*src == '#') {
|
||||
copy = FALSE;
|
||||
} else if (*src == 13 || *src == 10) {
|
||||
copy = TRUE;
|
||||
if (dst > tmp && *(dst - 1) != ' ') {
|
||||
*dst++ = ' ';
|
||||
}
|
||||
} else if (copy) {
|
||||
*dst++ = *src;
|
||||
}
|
||||
}
|
||||
*dst = 0;
|
||||
if (len > 0 && *(dst - 1) != ' ') {
|
||||
strcat(tmp, " ");
|
||||
}
|
||||
_close(hFile);
|
||||
}
|
||||
|
||||
// msgBox(cmd);
|
||||
// msgBox(args);
|
||||
// msgBox(workingDir);
|
||||
// Expand environment %variables%
|
||||
expandVars(args, tmp, exePath, pathLen);
|
||||
|
||||
// MainClass + Classpath or Jar
|
||||
char mainClass[STR] = {0};
|
||||
char jar[_MAX_PATH] = {0};
|
||||
loadString(JAR, jar);
|
||||
if (loadString(MAIN_CLASS, mainClass)) {
|
||||
if (!loadString(CLASSPATH, tmp)) {
|
||||
return FALSE;
|
||||
}
|
||||
char exp[MAX_ARGS] = {0};
|
||||
expandVars(exp, tmp, exePath, pathLen);
|
||||
strcat(args, "-classpath \"");
|
||||
if (wrapper) {
|
||||
appendAppClasspath(args, exePath, exp);
|
||||
} else if (*jar) {
|
||||
appendAppClasspath(args, jar, exp);
|
||||
}
|
||||
|
||||
// Deal with wildcards or >> strcat(args, exp); <<
|
||||
char* cp = strtok(exp, ";");
|
||||
while(cp != NULL) {
|
||||
debug("Add classpath:\t%s\n", cp);
|
||||
if (strpbrk(cp, "*?") != NULL) {
|
||||
int len = strrchr(cp, '\\') - cp + 1;
|
||||
strncpy(tmp_path, cp, len);
|
||||
char* filename = tmp_path + len;
|
||||
*filename = 0;
|
||||
struct _finddata_t c_file;
|
||||
long hFile;
|
||||
if ((hFile = _findfirst(cp, &c_file)) != -1L) {
|
||||
do {
|
||||
strcpy(filename, c_file.name);
|
||||
strcat(args, tmp_path);
|
||||
strcat(args, ";");
|
||||
debug(" \" :\t%s\n", tmp_path);
|
||||
} while (_findnext(hFile, &c_file) == 0);
|
||||
}
|
||||
_findclose(hFile);
|
||||
} else {
|
||||
strcat(args, cp);
|
||||
strcat(args, ";");
|
||||
}
|
||||
cp = strtok(NULL, ";");
|
||||
}
|
||||
*(args + strlen(args) - 1) = 0;
|
||||
|
||||
strcat(args, "\" ");
|
||||
strcat(args, mainClass);
|
||||
} else if (wrapper) {
|
||||
strcat(args, "-jar \"");
|
||||
strcat(args, exePath);
|
||||
strcat(args, "\"");
|
||||
} else {
|
||||
strcat(args, "-jar \"");
|
||||
strncat(args, exePath, pathLen);
|
||||
appendPath(args, jar);
|
||||
strcat(args, "\"");
|
||||
}
|
||||
|
||||
// Constant command line args
|
||||
if (loadString(CMD_LINE, tmp)) {
|
||||
strcat(args, " ");
|
||||
strcat(args, tmp);
|
||||
}
|
||||
|
||||
// Command line args
|
||||
if (*lpCmdLine) {
|
||||
strcpy(tmp, lpCmdLine);
|
||||
char* dst;
|
||||
while ((dst = strstr(tmp, "--l4j-")) != NULL) {
|
||||
char* src = strchr(dst, ' ');
|
||||
if (src == NULL || *(src + 1) == 0) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
strcpy(dst, src + 1);
|
||||
}
|
||||
}
|
||||
if (*tmp) {
|
||||
strcat(args, " ");
|
||||
strcat(args, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
debug("Launcher:\t%s\n", cmd);
|
||||
debug("Launcher args:\t%s\n", args);
|
||||
debug("Args length:\t%d/32768 chars\n", strlen(args));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void closeHandles() {
|
||||
CloseHandle(pi.hThread);
|
||||
CloseHandle(pi.hProcess);
|
||||
closeLogFile();
|
||||
}
|
||||
|
||||
DWORD execute(BOOL wait) {
|
||||
/*
|
||||
* Append a path to the Path environment variable
|
||||
*/
|
||||
BOOL appendToPathVar(const char* path) {
|
||||
char chBuf[MAX_VAR_SIZE] = {0};
|
||||
|
||||
const int pathSize = GetEnvironmentVariable("Path", chBuf, MAX_VAR_SIZE);
|
||||
if (MAX_VAR_SIZE - pathSize - 1 < strlen(path)) {
|
||||
return FALSE;
|
||||
}
|
||||
strcat(chBuf, ";");
|
||||
strcat(chBuf, path);
|
||||
return SetEnvironmentVariable("Path", chBuf);
|
||||
}
|
||||
|
||||
DWORD execute(const BOOL wait) {
|
||||
STARTUPINFO si;
|
||||
memset(&pi, 0, sizeof(pi));
|
||||
memset(&si, 0, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
|
||||
DWORD dwExitCode = -1;
|
||||
char cmdline[_MAX_PATH + BIG_STR] = "\"";
|
||||
char cmdline[MAX_ARGS];
|
||||
strcpy(cmdline, "\"");
|
||||
strcat(cmdline, cmd);
|
||||
strcat(cmdline, "\" ");
|
||||
strcat(cmdline, args);
|
||||
if (CreateProcess(NULL, cmdline, NULL, NULL,
|
||||
FALSE, 0, NULL, NULL, &si, &pi)) {
|
||||
TRUE, priority, NULL, NULL, &si, &pi)) {
|
||||
if (wait) {
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
GetExitCodeProcess(pi.hProcess, &dwExitCode);
|
||||
debug("Exit code:\t%d\n", dwExitCode);
|
||||
closeHandles();
|
||||
} else {
|
||||
dwExitCode = 0;
|
||||
|
Reference in New Issue
Block a user