BOOL apxJavaStart(LPAPXJAVA_THREADARGS pArgs) { LPAPXJAVAVM lpJava; lpJava = APXHANDLE_DATA(pArgs->hJava); if (!lpJava) return FALSE; lpJava->dwWorkerStatus = 0; lpJava->hWorkerInit = CreateEvent(NULL, FALSE, FALSE, NULL); lpJava->hWorkerSync = CreateEvent(NULL, FALSE, FALSE, NULL); lpJava->hWorkerThread = CreateThread(NULL, lpJava->szStackSize, __apxJavaWorkerThread, pArgs, CREATE_SUSPENDED, &lpJava->iWorkerThread); if (IS_INVALID_HANDLE(lpJava->hWorkerThread)) { apxLogWrite(APXLOG_MARK_SYSERR); return FALSE; } ResumeThread(lpJava->hWorkerThread); /* Wait until the worker thread initializes */ WaitForSingleObject(lpJava->hWorkerInit, INFINITE); if (lpJava->dwWorkerStatus == 0) return FALSE; SetEvent(lpJava->hWorkerSync); if (lstrcmpA(lpJava->clWorker.sClazz, "java/lang/System")) { /* Give some time to initialize the thread * Unless we are calling System.exit(0). * This will be hanled by _onexit hook. */ Sleep(1000); } return TRUE; }
BOOL apxDestroyJvm(DWORD dwTimeout) { if (_st_sys_jvm) { DWORD tid; HANDLE hWaiter; BOOL rv = FALSE; JavaVM *lpJvm = _st_sys_jvm; _st_sys_jvm = NULL; (*lpJvm)->DetachCurrentThread(lpJvm); hWaiter = CreateThread(NULL, 0, __apxJavaDestroyThread, (void *)lpJvm, 0, &tid); if (IS_INVALID_HANDLE(hWaiter)) { apxLogWrite(APXLOG_MARK_SYSERR); return FALSE; } if (WaitForSingleObject(hWaiter, dwTimeout) == WAIT_OBJECT_0) rv = TRUE; CloseHandle(hWaiter); return rv; } else return FALSE; }
BOOL apxAddToPathW(APXHANDLE hPool, LPCWSTR szAdd) { LPWSTR wsAdd; DWORD rc; DWORD al; rc = GetEnvironmentVariableW(L"PATH", NULL, 0); if (rc == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) return FALSE; al = lstrlenW(szAdd) + 6; if (!(wsAdd = apxPoolAlloc(hPool, (al + rc + 1) * sizeof(WCHAR)))) return FALSE; lstrcpyW(wsAdd, L"PATH="); lstrcatW(wsAdd, szAdd); lstrcatW(wsAdd, L";"); if (!GetEnvironmentVariableW(L"PATH", wsAdd + al, rc - al)) { apxLogWrite(APXLOG_MARK_SYSERR); apxFree(wsAdd); return FALSE; } SetEnvironmentVariableW(L"PATH", wsAdd + 5); _wputenv(wsAdd); apxFree(wsAdd); return TRUE; }
/* * Environment variables parsing * Each variable is prfixed with PR_ * for example 'set PR_JVM=auto' has a same meaning as providing '--Jvm auto' * on the command line. * Multistring varisables are added to the present conf. */ void apxCmdlineLoadEnvVars( LPAPXCMDLINE lpCmdline) { WCHAR szEnv[64]; int i = 0; if (!lpCmdline || !lpCmdline->lpOptions) return; while (lpCmdline->lpOptions[i].szName) { DWORD l; WCHAR szVar[SIZ_HUGLEN]; lstrlcpyW(szEnv, 64, L"PR_"); lstrlcatW(szEnv, 64, lpCmdline->lpOptions[i].szName); l = GetEnvironmentVariableW(szEnv, szVar, SIZ_HUGMAX); if (l == 0 || l >= SIZ_HUGMAX) { if (l == 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND) { apxLogWrite(APXLOG_MARK_ERROR "Error geting environment variable %S", szEnv); return; } ++i; continue; } if (lpCmdline->lpOptions[i].dwType & APXCMDOPT_STR) { lpCmdline->lpOptions[i].szValue = apxPoolStrdupW(lpCmdline->hPool, szVar); lpCmdline->lpOptions[i].dwType |= APXCMDOPT_FOUND; } else if (lpCmdline->lpOptions[i].dwType & APXCMDOPT_INT) { lpCmdline->lpOptions[i].dwValue = (DWORD)apxAtoulW(szVar); lpCmdline->lpOptions[i].dwType |= APXCMDOPT_FOUND; } else if (lpCmdline->lpOptions[i].dwType & APXCMDOPT_MSZ) { LPWSTR pp; BOOL insquote = FALSE, indquote = FALSE; DWORD sp = 0; lpCmdline->lpOptions[i].dwValue = (lstrlenW(szVar) + 2) * sizeof(WCHAR); lpCmdline->lpOptions[i].szValue = apxPoolCalloc(lpCmdline->hPool, lpCmdline->lpOptions[i].dwValue); pp = szVar; while(*pp) { if (*pp == L'\'') insquote = !insquote; else if (*pp == L'"') { indquote = !indquote; lpCmdline->lpOptions[i].szValue[sp++] = L'"'; } else if ((*pp == L'#' || *pp == L';') && !insquote && !indquote) lpCmdline->lpOptions[i].szValue[sp++] = L'\0'; else lpCmdline->lpOptions[i].szValue[sp++] = *pp; pp++; } lpCmdline->lpOptions[i].dwType |= APXCMDOPT_FOUND | APXCMDOPT_ADD; } ++i; } }
/* a hook for a function that redirects all VM messages. */ static jint JNICALL __apxJniVfprintf(FILE *fp, const char *format, va_list args) { jint rv; CHAR sBuf[1024+16]; rv = wvsprintfA(sBuf, format, args); if (apxLogWrite(APXLOG_MARK_INFO "%s", sBuf) == 0) fputs(sBuf, stdout); return rv; }
/* Call the Java: * System.setOut(new PrintStream(new FileOutputStream(filename))); */ BOOL apxJavaSetOut(APXHANDLE hJava, BOOL setErrorOrOut, LPCWSTR szFilename) { LPAPXJAVAVM lpJava; jobject fs; jobject ps; jstring fn; jclass sys; if (hJava->dwType != APXHANDLE_TYPE_JVM || !szFilename) return FALSE; lpJava = APXHANDLE_DATA(hJava); if (!__apxJvmAttach(lpJava)) return FALSE; if ((fn = apxJavaCreateStringW(hJava, szFilename)) == NULL) return FALSE; if ((fs = apxJavaCreateClass(hJava, "java/io/FileOutputStream", "(Ljava/lang/String;Z)V", fn, JNI_TRUE)) == NULL) return FALSE; if ((ps = apxJavaCreateClass(hJava, "java/io/PrintStream", "(Ljava/io/OutputStream;)V", fs)) == NULL) return FALSE; sys = JNICALL_1(FindClass, "java/lang/System"); if (sys == NULL || (JVM_EXCEPTION_CHECK(lpJava))) { JVM_EXCEPTION_CLEAR(lpJava); apxLogWrite(APXLOG_MARK_ERROR "Could not FindClass java/lang/System"); return FALSE; } if (setErrorOrOut) apxJavaCallStaticMethod(hJava, sys, "setErr", "(Ljava/io/PrintStream;)V", ps); else apxJavaCallStaticMethod(hJava, sys, "setOut", "(Ljava/io/PrintStream;)V", ps); if (JVM_EXCEPTION_CHECK(lpJava)) { JVM_EXCEPTION_CLEAR(lpJava); apxLogWrite(APXLOG_MARK_ERROR "Error calling set method for java/lang/System"); return FALSE; } else return TRUE; }
LPVOID apxJavaCreateClassV(APXHANDLE hJava, LPCSTR szClassName, LPCSTR szSignature, va_list lpArgs) { LPAPXJAVAVM lpJava; jclass clazz; jmethodID ccont; jobject cinst; if (hJava->dwType != APXHANDLE_TYPE_JVM) return NULL; lpJava = APXHANDLE_DATA(hJava); if (!__apxJvmAttach(lpJava)) return NULL; clazz = JNICALL_1(FindClass, szClassName); if (clazz == NULL || (JVM_EXCEPTION_CHECK(lpJava))) { JVM_EXCEPTION_CLEAR(lpJava); apxLogWrite(APXLOG_MARK_ERROR "Could not FindClass %s", szClassName); return NULL; } ccont = JNICALL_3(GetMethodID, clazz, "<init>", szSignature); if (ccont == NULL || (JVM_EXCEPTION_CHECK(lpJava))) { JVM_EXCEPTION_CLEAR(lpJava); apxLogWrite(APXLOG_MARK_ERROR "Could not find Constructor %s for %s", szSignature, szClassName); return NULL; } cinst = JNICALL_3(NewObjectV, clazz, ccont, lpArgs); if (cinst == NULL || (JVM_EXCEPTION_CHECK(lpJava))) { JVM_EXCEPTION_CLEAR(lpJava); apxLogWrite(APXLOG_MARK_ERROR "Could not create instance of %s", szClassName); return NULL; } return cinst; }
LPSTR __apxGetEnvironmentVariableA(APXHANDLE hPool, LPCSTR szName) { LPSTR szRet; DWORD rc; rc = GetEnvironmentVariableA(szName, NULL, 0); if (rc == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) return NULL; if (!(szRet = apxPoolAlloc(hPool, rc + 1))) return NULL; if (!GetEnvironmentVariableA(szName, szRet, rc)) { apxLogWrite(APXLOG_MARK_SYSERR); apxFree(szRet); return NULL; } return szRet; }
LPWSTR __apxGetEnvironmentVariableW(APXHANDLE hPool, LPCWSTR wsName) { LPWSTR wsRet; DWORD rc; rc = GetEnvironmentVariableW(wsName, NULL, 0); if (rc == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) return NULL; if (!(wsRet = apxPoolAlloc(hPool, (rc + 1) * sizeof(WCHAR)))) return NULL; if (!GetEnvironmentVariableW(wsName, wsRet, rc)) { apxLogWrite(APXLOG_MARK_SYSERR); apxFree(wsRet); return NULL; } return wsRet; }
LPVOID apxJavaCreateStringW(APXHANDLE hJava, LPCWSTR szString) { LPAPXJAVAVM lpJava; jstring str; if (hJava->dwType != APXHANDLE_TYPE_JVM) return NULL; lpJava = APXHANDLE_DATA(hJava); str = JNICALL_2(NewString, szString, lstrlenW(szString)); if (str == NULL || (JVM_EXCEPTION_CHECK(lpJava))) { JVM_EXCEPTION_CLEAR(lpJava); apxLogWrite(APXLOG_MARK_ERROR "Could not create string for %S", szString); return NULL; } return str; }
/* * argv parsing. * Parse the argv[0] and split to ExePath and * Executable name. Strip the extension ('.exe'). * Check for command in argv[1] //CMD//Application * Parse the options --option value or --option==value * break on first argument that doesn't start with '--' */ LPAPXCMDLINE apxCmdlineParse( APXHANDLE hPool, APXCMDLINEOPT *lpOptions, LPCWSTR *lpszCommands, LPCWSTR *lpszAltcmds) { LPAPXCMDLINE lpCmdline = NULL; DWORD l, i, s = 1; LPWSTR p; DWORD match; WCHAR mh[SIZ_HUGLEN]; if (_st_sys_argc < 1) return NULL; if (!(lpCmdline = (LPAPXCMDLINE)apxPoolCalloc(hPool, sizeof(APXCMDLINE)))) return NULL; lpCmdline->hPool = hPool; lpCmdline->lpOptions = lpOptions; if (GetModuleFileNameW(GetModuleHandle(NULL), mh, SIZ_HUGLEN)) { GetLongPathNameW(mh, mh, SIZ_HUGLEN); lpCmdline->szExePath = apxPoolStrdupW(hPool, mh); lpCmdline->szArgv0 = apxPoolStrdupW(hPool, mh); if (lpCmdline->szExePath == NULL || lpCmdline->szArgv0 == NULL) return NULL; if ((p = wcsrchr(lpCmdline->szExePath, L'\\'))) *p++ = L'\0'; else return NULL; } else return NULL; lpCmdline->szExecutable = p; p = wcsrchr(lpCmdline->szExecutable, L'.'); if (p && lstrcmpiW(p, EXE_SUFFIX) == 0) *p = L'\0'; if ((p = wcsrchr(lpCmdline->szExecutable, L'.'))) { if (lstrcmpiW(p, X86_SUFFIX) == 0) { *p = L'\0'; } else if (lstrcmpiW(p, X64_SUFFIX) == 0) { *p = L'\0'; } else if (lstrcmpiW(p, A64_SUFFIX) == 0) { *p = L'\0'; } } if (_st_sys_argc > 1 && lstrlenW(_st_sys_argvw[1]) > 2) { LPWSTR cp = _st_sys_argvw[1]; LPWSTR cn = _st_sys_argc > 2 ? _st_sys_argvw[2] : NULL; LPWSTR ca = cp; i = 0; if (ca[0] == L'/' && ca[1] == L'/') { ca += 2; if ((cn = wcschr(ca, L'/'))) { *cn++ = L'\0'; while (*cn == L'/') cn++; if (*cn == L'\0') cn = NULL; } if (cn == NULL) cn = lpCmdline->szExecutable; while (lpszCommands[i]) { if (lstrcmpW(lpszCommands[i++], ca) == 0) { lpCmdline->dwCmdIndex = i; break; } } if (lpCmdline->dwCmdIndex) { lpCmdline->szApplication = cn; s = 2; } else { apxLogWrite(APXLOG_MARK_ERROR "Unrecognized cmd option %S", cp); return NULL; } } else { while (lpszAltcmds[i]) { if (lstrcmpW(lpszAltcmds[i++], ca) == 0) { lpCmdline->dwCmdIndex = i; break; } } if (lpCmdline->dwCmdIndex) { s = 2; if (cn && iswalnum(*cn)) { s++; lpCmdline->szApplication = cn; } else lpCmdline->szApplication = lpCmdline->szExecutable; } else { apxLogWrite(APXLOG_MARK_ERROR "Unrecognized cmd option %S", cp); return NULL; } } } else { lpCmdline->szApplication = lpCmdline->szExecutable; lpCmdline->dwCmdIndex = 1; return lpCmdline; } for (i = s; i < (DWORD)_st_sys_argc; i++) { LPWSTR e = NULL; LPWSTR a = _st_sys_argvw[i]; BOOL add = FALSE; if (a[0] == L'+' && a[1] == L'+') add = TRUE; else if (a[0] != L'-' || a[1] != L'-') break; p = a + 2; /* Find if the option has '=' char * for --option==value or --option value cases. */ while (*p) { if (*p == L'=') { *p = L'\0'; e = p + 1; break; } else p++; } match = 0; for (l = 0; lpOptions[l].szName; l++) { if (lstrcmpW(lpOptions[l].szName, a + 2) == 0) { LPWSTR val; /* check if arg is needed */ if (e) val = e; else if ((i + 1) < (DWORD)_st_sys_argc) val = _st_sys_argvw[++i]; else { lpOptions[l].dwValue = 0; lpOptions[l].szValue = NULL; lpOptions[l].dwType |= APXCMDOPT_FOUND; break; } if (add) { if (!(lpOptions[l].dwType & APXCMDOPT_FOUND)) { /* Only set add flag in case there was no --option */ lpOptions[l].dwType |= APXCMDOPT_ADD; } } else if (lpOptions[l].dwType & APXCMDOPT_ADD) { /* We have ++option --option ... * Discard earlier values and go over. */ lpOptions[l].dwType &= ~APXCMDOPT_ADD; lpOptions[l].dwValue = 0; lpOptions[l].szValue = 0; } if (lpOptions[l].dwType & APXCMDOPT_STR) lpOptions[l].szValue = val; else if (lpOptions[l].dwType & APXCMDOPT_INT) lpOptions[l].dwValue = (DWORD)apxAtoulW(val); else if (lpOptions[l].dwType & APXCMDOPT_MSZ) { LPWSTR pp; BOOL insquote = FALSE, indquote=FALSE; DWORD sp = 0; LPWSTR ov = lpOptions[l].szValue; if (lpOptions[l].dwValue > 2) { sp = (lpOptions[l].dwValue - sizeof(WCHAR)) / sizeof(WCHAR); } lpOptions[l].dwValue = (sp + lstrlenW(val) + 2) * sizeof(WCHAR); lpOptions[l].szValue = (LPWSTR)apxPoolCalloc(hPool, lpOptions[l].dwValue); if (sp) { AplMoveMemory(lpOptions[l].szValue, ov, sp * sizeof(WCHAR)); apxFree(ov); } pp = val; while(*pp) { if (*pp == L'\'') insquote = !insquote; else if (*pp == L'"') { indquote = !indquote; lpOptions[l].szValue[sp++] = L'"'; } else if ((*pp == L'#' || *pp == L';') && !insquote && !indquote) lpOptions[l].szValue[sp++] = L'\0'; else lpOptions[l].szValue[sp++] = *pp; pp++; } } lpOptions[l].dwType |= APXCMDOPT_FOUND; match = l + 1; break; } } if (match == 0) { /* --unknown option * */ apxLogWrite(APXLOG_MARK_ERROR "Unrecognized program option %S", _st_sys_argvw[i]); return NULL; } } if (i < (DWORD)_st_sys_argc) { lpCmdline->dwArgc = _st_sys_argc - i; lpCmdline->lpArgvw = &_st_sys_argvw[i]; } return lpCmdline; }
int apxLogWrite( HANDLE hFile, DWORD dwLevel, BOOL bTimeStamp, LPCSTR szFile, DWORD dwLine, LPCSTR szFormat, ...) { va_list args; CHAR buffer[1024+32] = ""; LPSTR szBp; int len = 0; LPCSTR f = szFile; CHAR sb[SIZ_PATHLEN]; DWORD wr; DWORD err; BOOL dolock = TRUE; apx_logfile_st *lf = (apx_logfile_st *)hFile; err = GetLastError(); /* save the last Error code */ if (IS_INVALID_HANDLE(lf)) lf = _st_sys_loghandle; if (IS_INVALID_HANDLE(lf)) { lf = &_st_sys_errhandle; lf->hFile = GetStdHandle(STD_ERROR_HANDLE); dolock = FALSE; } if (dwLevel < lf->dwLogLevel) return 0; if (f && (lf->dwLogLevel == APXLOG_LEVEL_DEBUG || dwLevel == APXLOG_LEVEL_ERROR)) { f = (szFile + lstrlenA(szFile) - 1); while(f != szFile && '\\' != *f && '/' != *f) f--; if(f != szFile) f++; } else f = NULL; szBp = buffer; if (!szFormat) { if (err == 0) { lstrcpyA(szBp, "Unknown error code"); if (dwLevel == APXLOG_LEVEL_ERROR) { szBp += 18; wsprintfA(szBp, " occured in (%s:%d) ", f, dwLine); } } else FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), szBp, 1000, NULL); } else { va_start(args, szFormat); wvsprintfA(szBp, szFormat, args); va_end(args); } len = lstrlenA(buffer); if (len > 0) { /* Remove trailing line separator */ if (buffer[len - 1] == '\n') buffer[--len] = '\0'; if (len > 0 && buffer[len - 1] == '\r') buffer[--len] = '\0'; if (!IS_INVALID_HANDLE(lf->hFile)) { SYSTEMTIME t; GetLocalTime(&t); if (dolock) { APX_LOGLOCK(lf->hFile); logRotate(lf, &t); } if (bTimeStamp) { wsprintfA(sb, "[%d-%02d-%02d %02d:%02d:%02d] ", t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond); WriteFile(lf->hFile, sb, lstrlenA(sb), &wr, NULL); } WriteFile(lf->hFile, _log_level[dwLevel], lstrlenA(_log_level[dwLevel]), &wr, NULL); if (f && lf->dwLogLevel == APXLOG_LEVEL_DEBUG) { wsprintfA(sb, "(%10s:%-4d) ", f, dwLine); WriteFile(lf->hFile, sb, lstrlenA(sb), &wr, NULL); } if (len) WriteFile(lf->hFile, buffer, len, &wr, NULL); /* Terminate the line */ WriteFile(lf->hFile, LINE_SEP, sizeof(LINE_SEP) - 1, &wr, NULL); #ifdef _DEBUG_FULL FlushFileBuffers(lf->hFile); #endif if (dolock) { APX_LOGUNLOCK(lf->hFile); } } #ifdef _DEBUG_FULL { char tid[1024 + 16]; wsprintfA(tid, "[%04d] %s", GetCurrentThreadId(), buffer); OutputDebugStringA(tid); } #endif } /* Restore the last Error code */ SetLastError(err); if (szFormat && err != 0 && dwLevel == APXLOG_LEVEL_ERROR) { /* Print the System error description */ apxLogWrite(hFile, dwLevel, bTimeStamp, szFile, dwLine, NULL); } return len; }
/* Main java application worker thread * It will launch Java main and wait until * it finishes. */ static DWORD WINAPI __apxJavaWorkerThread(LPVOID lpParameter) { #define WORKER_EXIT(x) do { rv = x; goto finished; } while(0) DWORD rv = 0; LPAPXJAVAVM lpJava = NULL; LPAPXJAVA_THREADARGS pArgs = (LPAPXJAVA_THREADARGS)lpParameter; APXHANDLE hJava; hJava = (APXHANDLE)pArgs->hJava; if (hJava->dwType != APXHANDLE_TYPE_JVM) WORKER_EXIT(1); lpJava = APXHANDLE_DATA(pArgs->hJava); if (!lpJava) WORKER_EXIT(1); if (!apxJavaInitialize(pArgs->hJava, pArgs->szClassPath, pArgs->lpOptions, pArgs->dwMs, pArgs->dwMx, pArgs->dwSs, pArgs->bJniVfprintf)) { WORKER_EXIT(2); } if (pArgs->szLibraryPath && *pArgs->szLibraryPath) { DYNLOAD_FPTR_ADDRESS(SetDllDirectoryW, KERNEL32); DYNLOAD_CALL(SetDllDirectoryW)(pArgs->szLibraryPath); apxLogWrite(APXLOG_MARK_DEBUG "DLL search path set to '%S'", pArgs->szLibraryPath); } if (!apxJavaLoadMainClass(pArgs->hJava, pArgs->szClassName, pArgs->szMethodName, pArgs->lpArguments)) { WORKER_EXIT(3); } apxJavaSetOut(pArgs->hJava, TRUE, pArgs->szStdErrFilename); apxJavaSetOut(pArgs->hJava, FALSE, pArgs->szStdOutFilename); /* Check if we have a class and a method */ if (!lpJava->clWorker.jClazz || !lpJava->clWorker.jMethod) WORKER_EXIT(4); if (!__apxJvmAttach(lpJava)) WORKER_EXIT(5); apxLogWrite(APXLOG_MARK_DEBUG "Java Worker thread started %s:%s", lpJava->clWorker.sClazz, lpJava->clWorker.sMethod); lpJava->dwWorkerStatus = 1; SetEvent(lpJava->hWorkerInit); /* Ensure apxJavaStart worker has read our status */ WaitForSingleObject(lpJava->hWorkerSync, INFINITE); JNICALL_3(CallStaticVoidMethod, lpJava->clWorker.jClazz, lpJava->clWorker.jMethod, lpJava->clWorker.jArgs); if (JVM_EXCEPTION_CHECK(lpJava)) { apxLogWrite(APXLOG_MARK_DEBUG "Exception has been thrown"); vmExitCode = 1; (*((lpJava)->lpEnv))->ExceptionDescribe((lpJava)->lpEnv); __apxJvmDetach(lpJava); WORKER_EXIT(6); } else { __apxJvmDetach(lpJava); } finished: if (lpJava) { lpJava->dwWorkerStatus = 0; apxLogWrite(APXLOG_MARK_DEBUG "Java Worker thread finished %s:%s with status=%d", lpJava->clWorker.sClazz, lpJava->clWorker.sMethod, rv); SetEvent(lpJava->hWorkerInit); } ExitThread(rv); /* never gets here but keep the compiler happy */ return rv; }
BOOL apxJavaLoadMainClass(APXHANDLE hJava, LPCSTR szClassName, LPCSTR szMethodName, LPCVOID lpArguments) { LPWSTR *lpArgs = NULL; DWORD nArgs; LPAPXJAVAVM lpJava; jclass jClazz; LPCSTR szSignature = "([Ljava/lang/String;)V"; if (hJava->dwType != APXHANDLE_TYPE_JVM) return FALSE; lpJava = APXHANDLE_DATA(hJava); if (!lpJava) return FALSE; if (IS_EMPTY_STRING(szMethodName)) szMethodName = "main"; if (lstrcmpA(szClassName, "java/lang/System") == 0) { /* Usable only for exit method, so force */ szSignature = "(I)V"; szMethodName = "exit"; } lstrlcpyA(lpJava->clWorker.sClazz, 1024, szClassName); lstrlcpyA(lpJava->clWorker.sMethod, 512, szMethodName); jClazz = JNICALL_1(FindClass, JAVA_CLASSSTRING); if (!jClazz) { JVM_EXCEPTION_CLEAR(lpJava); apxLogWrite(APXLOG_MARK_ERROR "FindClass " JAVA_CLASSSTRING " failed"); return FALSE; } lpJava->clString.jClazz = JNICALL_1(NewGlobalRef, jClazz); JNI_LOCAL_UNREF(jClazz); /* Find the class */ jClazz = JNICALL_1(FindClass, szClassName); if (!jClazz) { JVM_EXCEPTION_CLEAR(lpJava); apxLogWrite(APXLOG_MARK_ERROR "FindClass %s failed", szClassName); return FALSE; } /* Make the class global so that worker thread can attach */ lpJava->clWorker.jClazz = JNICALL_1(NewGlobalRef, jClazz); JNI_LOCAL_UNREF(jClazz); lpJava->clWorker.jMethod = JNICALL_3(GetStaticMethodID, lpJava->clWorker.jClazz, szMethodName, szSignature); if (!lpJava->clWorker.jMethod) { JVM_EXCEPTION_CLEAR(lpJava); apxLogWrite(APXLOG_MARK_ERROR "Method 'static void %s(String[])' not found in Class %s", szMethodName, szClassName); return FALSE; } if (lstrcmpA(szClassName, "java/lang/System")) { nArgs = apxMultiSzToArrayW(hJava->hPool, lpArguments, &lpArgs); lpJava->clWorker.jArgs = JNICALL_3(NewObjectArray, nArgs, lpJava->clString.jClazz, NULL); if (nArgs) { DWORD i; for (i = 0; i < nArgs; i++) { jstring arg = JNICALL_2(NewString, lpArgs[i], lstrlenW(lpArgs[i])); JNICALL_3(SetObjectArrayElement, lpJava->clWorker.jArgs, i, arg); apxLogWrite(APXLOG_MARK_DEBUG "argv[%d] = %S", i, lpArgs[i]); } } apxFree(lpArgs); } return TRUE; }
/* ANSI version only */ BOOL apxJavaInitialize(APXHANDLE hJava, LPCSTR szClassPath, LPCVOID lpOptions, DWORD dwMs, DWORD dwMx, DWORD dwSs, DWORD bJniVfprintf) { LPAPXJAVAVM lpJava; JavaVMInitArgs vmArgs; JavaVMOption *lpJvmOptions; DWORD i, nOptions, sOptions = 0; BOOL rv = FALSE; if (hJava->dwType != APXHANDLE_TYPE_JVM) return FALSE; lpJava = APXHANDLE_DATA(hJava); if (lpJava->iVmCount) { if (!lpJava->lpEnv && !__apxJvmAttach(lpJava)) { if (lpJava->iVersion == JNI_VERSION_1_2) { apxLogWrite(APXLOG_MARK_ERROR "Unable To Attach the JVM"); return FALSE; } else lpJava->iVersion = JNI_VERSION_1_2; if (!__apxJvmAttach(lpJava)) { apxLogWrite(APXLOG_MARK_ERROR "Unable To Attach the JVM"); return FALSE; } } lpJava->iVersion = JNICALL_0(GetVersion); if (lpJava->iVersion < JNI_VERSION_1_2) { apxLogWrite(APXLOG_MARK_ERROR "Unsupported JNI version %#08x", lpJava->iVersion); return FALSE; } rv = TRUE; } else { CHAR iB[3][64]; LPSTR szCp = NULL; lpJava->iVersion = JNI_VERSION_DEFAULT; if (dwMs) ++sOptions; if (dwMx) ++sOptions; if (dwSs) ++sOptions; if (bJniVfprintf) ++sOptions; if (szClassPath && *szClassPath) ++sOptions; sOptions++; /* unconditionally set for extraInfo exit */ nOptions = __apxMultiSzToJvmOptions(hJava->hPool, lpOptions, &lpJvmOptions, sOptions); if (szClassPath && *szClassPath) { szCp = __apxEvalClasspath(hJava->hPool, szClassPath); if (szCp == NULL) { apxLogWrite(APXLOG_MARK_ERROR "Invalid classpath %s", szClassPath); return FALSE; } lpJvmOptions[nOptions - sOptions].optionString = szCp; --sOptions; } if (bJniVfprintf) { /* default JNI error printer */ lpJvmOptions[nOptions - sOptions].optionString = "vfprintf"; lpJvmOptions[nOptions - sOptions].extraInfo = __apxJniVfprintf; --sOptions; } /* unconditionally add hook for System.exit() in order to store exit code */ lpJvmOptions[nOptions - sOptions].optionString = "exit"; lpJvmOptions[nOptions - sOptions].extraInfo = __apxJniExit; --sOptions; if (dwMs) { wsprintfA(iB[0], "-Xms%dm", dwMs); lpJvmOptions[nOptions - sOptions].optionString = iB[0]; --sOptions; } if (dwMx) { wsprintfA(iB[1], "-Xmx%dm", dwMx); lpJvmOptions[nOptions - sOptions].optionString = iB[1]; --sOptions; } if (dwSs) { wsprintfA(iB[2], "-Xss%dk", dwSs); lpJvmOptions[nOptions - sOptions].optionString = iB[2]; --sOptions; } for (i = 0; i < nOptions; i++) { apxLogWrite(APXLOG_MARK_DEBUG "Jvm Option[%d] %s", i, lpJvmOptions[i].optionString); } vmArgs.options = lpJvmOptions; vmArgs.nOptions = nOptions; vmArgs.version = lpJava->iVersion; vmArgs.ignoreUnrecognized = JNI_FALSE; if (DYNLOAD_FPTR(JNI_CreateJavaVM)(&(lpJava->lpJvm), (void **)&(lpJava->lpEnv), &vmArgs) != JNI_OK) { apxLogWrite(APXLOG_MARK_ERROR "CreateJavaVM Failed"); rv = FALSE; } else { rv = TRUE; if (!_st_sys_jvm) _st_sys_jvm = lpJava->lpJvm; } apxFree(szCp); apxFree(lpJvmOptions); } if (rv) return TRUE; else return FALSE; }
static void JNICALL __apxJniExit(jint exitCode) { apxLogWrite(APXLOG_MARK_DEBUG "Exit hook with exit code %d", exitCode); vmExitCode = exitCode; return; }
static BOOL __apxLoadJvmDll(LPCWSTR szJvmDllPath) { UINT errMode; WCHAR jreAltPath[SIZ_PATHLEN]; LPWSTR dllJvmPath = (LPWSTR)szJvmDllPath; DYNLOAD_FPTR_DECLARE(SetDllDirectoryW); if (!IS_INVALID_HANDLE(_st_sys_jvmDllHandle)) return TRUE; /* jvm.dll is already loaded */ if (dllJvmPath && *dllJvmPath) { /* Explicit JVM path. * Check if provided argument is valid */ if (GetFileAttributesW(dllJvmPath) == INVALID_FILE_ATTRIBUTES) { /* DAEMON-247: Invalid RuntimeLib explicitly specified is error. */ apxLogWrite(APXLOG_MARK_DEBUG "Invalid RuntimeLib specified '%S'", dllJvmPath); return FALSE; } } else { dllJvmPath = apxGetJavaSoftRuntimeLib(NULL); if (!dllJvmPath) return FALSE; } if (GetFileAttributesW(dllJvmPath) == INVALID_FILE_ATTRIBUTES) { /* DAEMON-184: RuntimeLib registry key is invalid. * Check from Jre JavaHome directly */ LPWSTR szJreHome = apxGetJavaSoftHome(NULL, TRUE); apxLogWrite(APXLOG_MARK_DEBUG "Invalid RuntimeLib '%S'", dllJvmPath); if (szJreHome) { apxLogWrite(APXLOG_MARK_DEBUG "Using Jre JavaHome '%S'", szJreHome); lstrlcpyW(jreAltPath, SIZ_PATHLEN, szJreHome); lstrlcatW(jreAltPath, SIZ_PATHLEN, L"\\bin\\server\\jvm.dll"); dllJvmPath = jreAltPath; } } /* Suppress the not found system popup message */ errMode = SetErrorMode(SEM_FAILCRITICALERRORS); apxLogWrite(APXLOG_MARK_DEBUG "loading jvm '%S'", dllJvmPath); _st_sys_jvmDllHandle = LoadLibraryExW(dllJvmPath, NULL, 0); if (IS_INVALID_HANDLE(_st_sys_jvmDllHandle) && GetFileAttributesW(dllJvmPath) != INVALID_FILE_ATTRIBUTES) { /* There is a file but cannot be loaded. * Try to load the MSVCRTxx.dll before JVM.dll */ WCHAR jreBinPath[SIZ_PATHLEN]; WCHAR crtBinPath[SIZ_PATHLEN]; DWORD i, l = 0; lstrlcpyW(jreBinPath, SIZ_PATHLEN, dllJvmPath); for (i = lstrlenW(jreBinPath); i > 0, l < 2; i--) { if (jreBinPath[i] == L'\\' || jreBinPath[i] == L'/') { jreBinPath[i] = L'\0'; lstrlcpyW(crtBinPath, SIZ_PATHLEN, jreBinPath); lstrlcatW(crtBinPath, SIZ_PATHLEN, MSVCRT71_DLLNAME); if (GetFileAttributesW(crtBinPath) != INVALID_FILE_ATTRIBUTES) { if (LoadLibraryW(crtBinPath)) { /* Found MSVCRTxx.dll */ apxLogWrite(APXLOG_MARK_DEBUG "preloaded '%S'", crtBinPath); break; } } l++; } } } /* This shuldn't happen, but try to search in %PATH% */ if (IS_INVALID_HANDLE(_st_sys_jvmDllHandle)) _st_sys_jvmDllHandle = LoadLibraryExW(dllJvmPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (IS_INVALID_HANDLE(_st_sys_jvmDllHandle)) { WCHAR jreBinPath[SIZ_PATHLEN]; DWORD i, l = 0; lstrlcpyW(jreBinPath, SIZ_PATHLEN, dllJvmPath); DYNLOAD_FPTR_ADDRESS(SetDllDirectoryW, KERNEL32); for (i = lstrlenW(jreBinPath); i > 0, l < 2; i--) { if (jreBinPath[i] == L'\\' || jreBinPath[i] == L'/') { jreBinPath[i] = L'\0'; DYNLOAD_CALL(SetDllDirectoryW)(jreBinPath); apxLogWrite(APXLOG_MARK_DEBUG "Setting DLL search path to '%S'", jreBinPath); l++; } } _st_sys_jvmDllHandle = LoadLibraryExW(dllJvmPath, NULL, 0); if (IS_INVALID_HANDLE(_st_sys_jvmDllHandle)) _st_sys_jvmDllHandle = LoadLibraryExW(dllJvmPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); } /* Restore the error mode signalization */ SetErrorMode(errMode); if (IS_INVALID_HANDLE(_st_sys_jvmDllHandle)) { apxLogWrite(APXLOG_MARK_SYSERR); return FALSE; } DYNLOAD_FPTR_LOAD(JNI_GetDefaultJavaVMInitArgs, _st_sys_jvmDllHandle); DYNLOAD_FPTR_LOAD(JNI_CreateJavaVM, _st_sys_jvmDllHandle); DYNLOAD_FPTR_LOAD(JNI_GetCreatedJavaVMs, _st_sys_jvmDllHandle); DYNLOAD_FPTR_LOAD(JVM_DumpAllStacks, _st_sys_jvmDllHandle); if (!DYNLOAD_FPTR(JNI_GetDefaultJavaVMInitArgs) || !DYNLOAD_FPTR(JNI_CreateJavaVM) || !DYNLOAD_FPTR(JNI_GetCreatedJavaVMs)) { apxLogWrite(APXLOG_MARK_SYSERR); FreeLibrary(_st_sys_jvmDllHandle); _st_sys_jvmDllHandle = NULL; return FALSE; } /* Real voodo ... */ return TRUE; }
jvalue apxJavaCallStaticMethodV(APXHANDLE hJava, jclass lpClass, LPCSTR szMethodName, LPCSTR szSignature, va_list lpArgs) { LPAPXJAVAVM lpJava; jmethodID method; jvalue rv; LPCSTR s = szSignature; rv.l = 0; if (hJava->dwType != APXHANDLE_TYPE_JVM) return rv; lpJava = APXHANDLE_DATA(hJava); while (*s && *s != ')') ++s; if (*s != ')') { return rv; } else ++s; method = JNICALL_3(GetStaticMethodID, lpClass, szMethodName, szSignature); if (method == NULL || (JVM_EXCEPTION_CHECK(lpJava))) { JVM_EXCEPTION_CLEAR(lpJava); apxLogWrite(APXLOG_MARK_ERROR "Could not find method %s with signature %s", szMethodName, szSignature); return rv; } switch (*s) { case 'V': JNICALL_3(CallStaticVoidMethodV, lpClass, method, lpArgs); break; case 'L': case '[': rv.l = JNICALL_3(CallStaticObjectMethodV, lpClass, method, lpArgs); break; case 'Z': rv.z = JNICALL_3(CallStaticBooleanMethodV, lpClass, method, lpArgs); break; case 'B': rv.b = JNICALL_3(CallStaticByteMethodV, lpClass, method, lpArgs); break; case 'C': rv.c = JNICALL_3(CallStaticCharMethodV, lpClass, method, lpArgs); break; case 'S': rv.i = JNICALL_3(CallStaticShortMethodV, lpClass, method, lpArgs); break; case 'I': rv.i = JNICALL_3(CallStaticIntMethodV, lpClass, method, lpArgs); break; case 'J': rv.j = JNICALL_3(CallStaticLongMethodV, lpClass, method, lpArgs); break; case 'F': rv.f = JNICALL_3(CallStaticFloatMethodV, lpClass, method, lpArgs); break; case 'D': rv.d = JNICALL_3(CallStaticDoubleMethodV, lpClass, method, lpArgs); break; default: apxLogWrite(APXLOG_MARK_ERROR "Invalid signature %s for method %s", szSignature, szMethodName); return rv; break; } return rv; }