#include #define WIN32_LEAN_AND_MEAN #include #include "angiotool2_jar.h" #ifdef _WIN64 #define ALT_BITS "32" #else #define ALT_BITS "64" #endif #define bail(message) { MessageBoxA(NULL, message, "Error", MB_OK); return 1; } #define IS_FOLDER(bits) (bits) != INVALID_FILE_ATTRIBUTES && ((bits) & FILE_ATTRIBUTE_DIRECTORY) #define IS_FILE(bits) (bits) != INVALID_FILE_ATTRIBUTES && (((bits) & FILE_ATTRIBUTE_DIRECTORY) == 0) #define PATH_SIZE 1024 #define MAIN_CLASS_NAME "AngioTool/AngioTool" #define MAIN_METHOD_NAME "main" BOOL addString(char *str, int *strPos, int strSize, const char *toAdd); BOOL addHexNum(char *str, int *strPos, int strSize, unsigned int value); BOOL stripFromLast(char *str, int *strPos, char ch); BOOL checkIsFolder(char *path); BOOL checkIsFile(char *path); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) { BOOL (WINAPI *func_SetProcessDPIAware)() = GetProcAddress(GetModuleHandle("user32.dll"), "SetProcessDPIAware"); if (func_SetProcessDPIAware != NULL) func_SetProcessDPIAware(); char path[PATH_SIZE]; int pos = 0; addString(path, &pos, PATH_SIZE, "C:\\Program Files\\Java"); if (!checkIsFolder(path)) { stripFromLast(path, &pos, '\\'); addString(path, &pos, PATH_SIZE, " (x86)\\Java"); if (!checkIsFolder(path)) bail("Could not find path to Java installation"); } addString(path, &pos, PATH_SIZE, "\\*"); WIN32_FIND_DATAA pathInfo = {0}; HANDLE javaFolderHandle = FindFirstFileA(path, &pathInfo); if (javaFolderHandle == INVALID_HANDLE_VALUE) bail("Java installation was empty"); int highestVersion = 0; char javaVersion[PATH_SIZE]; javaVersion[0] = 0; while (TRUE) { if (IS_FOLDER(pathInfo.dwFileAttributes)) { int n = 0; char *p = pathInfo.cFileName; char prev = 0; BOOL stoppedAdding = FALSE; while (*p) { char c = *p; if (!stoppedAdding && c >= '0' && c <= '9') { BOOL skip = c == '1' && (prev < '0' || prev > '9') && p[1] && (p[1] < '0' || p[1] > '9'); if (!skip) n = n * 10 + (c - '0'); } else if (n > 0) { stoppedAdding = TRUE; } prev = c; p++; } int len = p - pathInfo.cFileName; if (n >= highestVersion && len < PATH_SIZE) { highestVersion = n; for (int i = 0; i < len; i++) javaVersion[i] = pathInfo.cFileName[i]; javaVersion[len] = 0; } } if (!FindNextFileA(javaFolderHandle, &pathInfo)) break; } CloseHandle(javaFolderHandle); if (javaVersion[0] == 0) bail("Could not find Java version in Java installation path"); path[--pos] = 0; BOOL isPathBuilt = addString(path, &pos, PATH_SIZE, javaVersion); if (isPathBuilt) isPathBuilt = addString(path, &pos, PATH_SIZE, "\\bin\\server\\jvm.dll"); if (!isPathBuilt) bail("Failed to build path to jvm.dll"); HMODULE javaServer = LoadLibraryA(path); int dllsNotLoadable = 0; if (javaServer == NULL) { dllsNotLoadable |= checkIsFile(path); stripFromLast(path, &pos, '\\'); stripFromLast(path, &pos, '\\'); addString(path, &pos, PATH_SIZE, "\\client\\jvm.dll"); javaServer = LoadLibraryA(path); } if (javaServer == NULL) { dllsNotLoadable |= checkIsFile(path) << 1; stripFromLast(path, &pos, '\\'); stripFromLast(path, &pos, '\\'); addString(path, &pos, PATH_SIZE, "\\jvm.dll"); javaServer = LoadLibraryA(path); } if (javaServer == NULL) { dllsNotLoadable |= checkIsFile(path) << 2; stripFromLast(path, &pos, '\\'); char errorMsg[PATH_SIZE + 128]; int errorPos = 0; if (dllsNotLoadable & 1) { addString(errorMsg, &errorPos, 96, "Found but could not load JVM dll, try using the " ALT_BITS "-bit EXE ("); addString(errorMsg, &errorPos, PATH_SIZE + 96, path); addString(errorMsg, &errorPos, PATH_SIZE + 128, "\\server\\jvm.dll)"); } else if (dllsNotLoadable & 2) { addString(errorMsg, &errorPos, 96, "Found but could not load JVM dll, try using the " ALT_BITS "-bit EXE ("); addString(errorMsg, &errorPos, PATH_SIZE + 96, path); addString(errorMsg, &errorPos, PATH_SIZE + 128, "\\client\\jvm.dll)"); } else if (dllsNotLoadable & 4) { addString(errorMsg, &errorPos, 96, "Found but could not load JVM dll, try using the " ALT_BITS "-bit EXE ("); addString(errorMsg, &errorPos, PATH_SIZE + 96, path); addString(errorMsg, &errorPos, PATH_SIZE + 128, "\\jvm.dll)"); } else { addString(errorMsg, &errorPos, 128, "Failed to open server\\jvm.dll, client\\jvm.dll or jvm.dll in "); addString(errorMsg, &errorPos, PATH_SIZE + 128, path); } bail(errorMsg); } jint (*func_JNI_CreateJavaVM)(JavaVM**, void**, JavaVMInitArgs*) = GetProcAddress(javaServer, "JNI_CreateJavaVM"); if (func_JNI_CreateJavaVM == NULL) bail("Failed to obtain function pointer to JNI_CreateJavaVM"); path[0] = 0; { DWORD size = GetTempPathA(PATH_SIZE, path); pos = (int)size; } if (pos <= 0) bail("Failed to obtain temporary path"); addString(path, &pos, PATH_SIZE, "AngioTool2"); if (!checkIsFolder(path)) { if (!CreateDirectoryA(path, NULL)) bail("Failed to create temporary directory"); } addString(path, &pos, PATH_SIZE, "\\AngioTool2.jar"); HANDLE jarFileHandle = CreateFileA(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (jarFileHandle != INVALID_HANDLE_VALUE) { DWORD filePos = 0; while (TRUE) { if (!WriteFile(jarFileHandle, AngioTool2_jar, AngioTool2_jar_len - filePos, &filePos, NULL)) bail("Failed to write to temporary .jar"); if (filePos >= AngioTool2_jar_len) break; } CloseHandle(jarFileHandle); } /* else { bail("Failed to create temporary .jar in temp directory"); } */ char javaClassPath[PATH_SIZE]; int javaClassPathPos = 0; addString(javaClassPath, &javaClassPathPos, PATH_SIZE, "-Djava.class.path="); for (int i = 0; i < pos; i++) javaClassPath[javaClassPathPos++] = path[i]; // == '\\' ? '/' : path[i]; //javaClassPath[javaClassPathPos++] = '\\'; javaClassPath[javaClassPathPos] = 0; JavaVMOption jvmOption = {0}; jvmOption.optionString = &javaClassPath[0]; JavaVMInitArgs vmArgs = {0}; vmArgs.version = JNI_VERSION_1_8; vmArgs.nOptions = 1; vmArgs.options = &jvmOption; JavaVM *vm; JNIEnv *env; jint res = func_JNI_CreateJavaVM(&vm, (void **)&env, &vmArgs); if (res != JNI_OK) bail("Failed to create Java VM"); jclass mainClass = (*env)->FindClass(env, MAIN_CLASS_NAME); if (mainClass == NULL) bail("Failed to find " MAIN_CLASS_NAME " class"); // (javaClassPath); jmethodID mainMethodId = (*env)->GetStaticMethodID(env, mainClass, MAIN_METHOD_NAME, "([Ljava/lang/String;)V"); if (mainMethodId == NULL) bail("Failed to find " MAIN_METHOD_NAME " function"); jobjectArray mainArgs = (*env)->NewObjectArray(env, 0, (*env)->FindClass(env, "java/lang/String"), NULL); if (mainArgs == NULL) bail("Failed to construct main args"); (*env)->CallStaticVoidMethod(env, mainClass, mainMethodId, mainArgs); (*vm)->DestroyJavaVM(vm); return 0; } BOOL addString(char *str, int *strPos, int strSize, const char *toAdd) { int pos = *strPos; int lenToAdd = strlen(toAdd); if (pos + lenToAdd >= strSize) return FALSE; for (int i = 0; i < lenToAdd; i++) str[pos+i] = toAdd[i]; pos += lenToAdd; str[pos] = 0; *strPos = pos; return TRUE; } BOOL addHexNum(char *str, int *strPos, int strSize, unsigned int value) { if (value == 0) return addString(str, strPos, strSize, "0"); char temp[16]; int len = 0; while (value > 0) { temp[len++] = (char)(value & 0xf); value >>= 4; } int pos = *strPos; if (pos + 2 + len >= strSize) return FALSE; str[pos++] = '0'; str[pos++] = 'x'; for (int i = len - 1; i >= 0; i--) { char d = temp[i]; d += d < 10 ? 0x30 : 0x57; str[pos++] = d; } str[pos] = 0; *strPos = pos; return TRUE; } BOOL stripFromLast(char *str, int *strPos, char ch) { int pos = *strPos; int i; for (i = pos-1; i >= 0; i--) { if (str[i] == ch) break; } if (i < 0) return FALSE; str[i] = 0; *strPos = i; return TRUE; } BOOL checkIsFolder(char *path) { DWORD bits = GetFileAttributesA(path); return IS_FOLDER(bits); } BOOL checkIsFile(char *path) { DWORD bits = GetFileAttributesA(path); return IS_FILE(bits); }