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;
}
Пример #3
0
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;
}
Пример #8
0
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;
}
Пример #9
0
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;
}
Пример #12
0
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;
}