static BOOL __apxLoadJvmDll()

in src/native/windows/src/javajni.c [194:365]


static BOOL __apxLoadJvmDll(APXHANDLE hPool, LPCWSTR szJvmDllPath, LPCWSTR szJavaHome)
{
    UINT errMode;
    WCHAR  jreAltPath[SIZ_PATHLEN];
    LPWSTR dllJvmPath = (LPWSTR)szJvmDllPath;
    DYNLOAD_FPTR_DECLARE(SetDllDirectoryW);
    DWORD  i, l = 0;
    WCHAR  jreBinPath[SIZ_PATHLEN];

    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_ERROR "Invalid RuntimeLib specified '%S'", dllJvmPath);
            return FALSE;
        }
        apxLogWrite(APXLOG_MARK_DEBUG "Explicit RuntimeLib specified '%S'", dllJvmPath);
    }
    else {
        // No explicit JVM path. Use the standard registry locations.
        dllJvmPath = apxGetJavaSoftRuntimeLib(NULL);
        apxLogWrite(APXLOG_MARK_DEBUG "No explicit RuntimeLib specified. Checking registry. Found '%S'", dllJvmPath);
    }

    if (GetFileAttributesW(dllJvmPath) == INVALID_FILE_ATTRIBUTES) {
        /* DAEMON-184: RuntimeLib registry key is invalid.
         * Check from Jre JavaHome registry key directly
         */
        LPWSTR szJreHome = apxGetJavaSoftHome(NULL, TRUE);
        if (szJreHome) {
            apxLogWrite(APXLOG_MARK_DEBUG "Invalid RuntimeLib '%S', Checking registry for JRE home. Found '%S'", dllJvmPath, szJreHome);
            lstrlcpyW(jreAltPath, SIZ_PATHLEN, szJreHome);
            lstrlcatW(jreAltPath, SIZ_PATHLEN, L"\\bin\\server\\jvm.dll");
            dllJvmPath = jreAltPath;
        } else {
            apxLogWrite(APXLOG_MARK_DEBUG "Invalid RuntimeLib '%S', Checking registry for JRE home. None found.", dllJvmPath);
        }
    }

    if (GetFileAttributesW(dllJvmPath) == INVALID_FILE_ATTRIBUTES) {
        /* DAEMON-247: JavaSoft JRE registry keys are invalid / not present
         * Check from Procrun's JavaHome registry key
         */
        if (szJavaHome) {
            apxLogWrite(APXLOG_MARK_DEBUG "Using explicitly configured JavaHome '%S'", szJavaHome);
            lstrlcpyW(jreAltPath, SIZ_PATHLEN, szJavaHome);
            lstrlcatW(jreAltPath, SIZ_PATHLEN, L"\\bin\\server\\jvm.dll");
            dllJvmPath = jreAltPath;
        }
    }

    if (GetFileAttributesW(dllJvmPath) == INVALID_FILE_ATTRIBUTES) {
        /* DAEMON-404: JRE home in registry invalid / not present.
         * Explicit JavaHome invalid / not present
         * Check from JDK JavaHome registry key directly
         */
        LPWSTR szJdkHome = apxGetJavaSoftHome(NULL, FALSE);
        if (szJdkHome) {
            apxLogWrite(APXLOG_MARK_DEBUG "Invalid RuntimeLib '%S', Checking registry for JDK home. Found '%S'", dllJvmPath, szJdkHome);
            lstrlcpyW(jreAltPath, SIZ_PATHLEN, szJdkHome);
            lstrlcatW(jreAltPath, SIZ_PATHLEN, L"\\bin\\server\\jvm.dll");
            dllJvmPath = jreAltPath;
        } else {
            apxLogWrite(APXLOG_MARK_DEBUG "Invalid RuntimeLib '%S', Checking registry for JDK home. None found.", dllJvmPath);
        }
    }

    if (!dllJvmPath) {
        apxLogWrite(APXLOG_MARK_ERROR "No JVM configured or found in registry. Unable to start service.");
        return FALSE;
    }

    /* Suppress the not found system popup message */
    errMode = SetErrorMode(SEM_FAILCRITICALERRORS);

    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';
            l++;
        }
    }

    /* Add Java bin path to the PATH to fix loading of awt.dll */
    apxLogWrite(APXLOG_MARK_DEBUG "Adding Java bin path to the PATH to fix loading of awt.dll: '%S'", jreBinPath);
    apxAddToPathW(hPool, jreBinPath);

    /* Set the environment using putenv, so JVM can use it */
    apxSetInprocEnvironment();

    apxLogWrite(APXLOG_MARK_DEBUG "Loading JVM DLL '%S'", dllJvmPath);
    _st_sys_jvmDllHandle = LoadLibraryExW(dllJvmPath, NULL, 0);
    if (IS_INVALID_HANDLE(_st_sys_jvmDllHandle) &&
        GetFileAttributesW(dllJvmPath) != INVALID_FILE_ATTRIBUTES) {
        WCHAR  crtBinPath[SIZ_PATHLEN];

        /* There is a file but cannot be loaded.
         * Try to load the MSVCRTxx.dll before JVM.dll
         */
        apxLogWrite(APXLOG_MARK_ERROR "Found '%S' but couldn't load it.", dllJvmPath);

        lstrlcpyW(jreBinPath, SIZ_PATHLEN, dllJvmPath);
        if(l == 2) {
            lstrlcpyW(crtBinPath, SIZ_PATHLEN, jreBinPath);
            lstrlcatW(crtBinPath, SIZ_PATHLEN, MSVCRT71_DLLNAME);
            if (GetFileAttributesW(crtBinPath) != INVALID_FILE_ATTRIBUTES) {
                apxLogWrite(APXLOG_MARK_DEBUG "Loading '%S'.", crtBinPath);
                if (LoadLibraryW(crtBinPath)) {
                    /* Found MSVCRTxx.dll
                     */
                    apxLogWrite(APXLOG_MARK_DEBUG "Preloaded '%S'", crtBinPath);
                }
                else {
                    apxLogWrite(APXLOG_MARK_DEBUG "Failed preloading '%S'.", crtBinPath);
                }
            }
        }
    }
    /* This shouldn't happen, but try to search in %PATH% */
    if (IS_INVALID_HANDLE(_st_sys_jvmDllHandle)) {
        apxLogWrite(APXLOG_MARK_DEBUG "Invalid JVM DLL handle.");
        apxLogWrite(APXLOG_MARK_DEBUG "Loading JVM DLL '%S' using LOAD_WITH_ALTERED_SEARCH_PATH.", dllJvmPath);
        _st_sys_jvmDllHandle = LoadLibraryExW(dllJvmPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
    }
    if (IS_INVALID_HANDLE(_st_sys_jvmDllHandle)) {
        apxLogWrite(APXLOG_MARK_DEBUG "Invalid JVM DLL handle.");
        DYNLOAD_FPTR_ADDRESS(SetDllDirectoryW, KERNEL32);
        if (l == 2) {
            apxLogWrite(APXLOG_MARK_DEBUG "Setting DLL search path to '%S'", jreBinPath);
            DYNLOAD_CALL(SetDllDirectoryW)(jreBinPath);
        }
        apxLogWrite(APXLOG_MARK_DEBUG "Loading JVM DLL '%S'.", dllJvmPath);
        _st_sys_jvmDllHandle = LoadLibraryExW(dllJvmPath, NULL, 0);
        if (IS_INVALID_HANDLE(_st_sys_jvmDllHandle)) {
            apxLogWrite(APXLOG_MARK_DEBUG "Invalid JVM DLL handle.");
            apxLogWrite(APXLOG_MARK_DEBUG "Loading JVM DLL '%S' using LOAD_WITH_ALTERED_SEARCH_PATH.", dllJvmPath);
            _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_ERROR "Invalid JVM DLL handle.");
        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);
        apxLogWrite(APXLOG_MARK_DEBUG "Freeing JVM DLL.");
        FreeLibrary(_st_sys_jvmDllHandle);
        _st_sys_jvmDllHandle = NULL;
        apxLogWrite(APXLOG_MARK_ERROR "Failed loading JNI function pointers.");
        return FALSE;
    }

    /* Real voodoo ... */
    return TRUE;
}