8244634: LoadLibraryW failed from tools/jpackage tests after JDK-8242302

Reviewed-by: herrick, almatvee
This commit is contained in:
Alexey Semenyuk 2020-05-12 19:34:59 -04:00
parent dc54da232d
commit e48410a466
4 changed files with 96 additions and 3 deletions

View File

@ -46,6 +46,10 @@ public:
return *this;
}
tstring getPath() const {
return jvmPath;
}
void launch();
private:

View File

@ -28,10 +28,14 @@
#include <windows.h>
#include "AppLauncher.h"
#include "JvmLauncher.h"
#include "Log.h"
#include "Dll.h"
#include "Toolbox.h"
#include "FileUtils.h"
#include "UniqueHandle.h"
#include "ErrorHandling.h"
#include "WinSysInfo.h"
#include "WinErrorHandling.h"
@ -41,6 +45,61 @@
namespace {
std::unique_ptr<Dll> loadDllWithAlteredPATH(const tstring& dllFullPath) {
LOG_TRACE_FUNCTION();
const tstring vanillaPathEnvVariable = SysInfo::getEnvVariable(_T("PATH"));
tstring pathEnvVariable = vanillaPathEnvVariable
+ _T(";")
+ FileUtils::dirname(dllFullPath);
SysInfo::setEnvVariable(_T("PATH"), pathEnvVariable);
LOG_TRACE(tstrings::any() << "New value of PATH: " << pathEnvVariable);
// Schedule restore of PATH after attempt to load the given dll
const auto resetPATH = runAtEndOfScope([&vanillaPathEnvVariable]() -> void {
SysInfo::setEnvVariable(_T("PATH"), vanillaPathEnvVariable);
});
return std::unique_ptr<Dll>(new Dll(dllFullPath));
}
std::unique_ptr<Dll> loadDllWithAddDllDirectory(const tstring& dllFullPath) {
LOG_TRACE_FUNCTION();
const tstring dirPath = FileUtils::dirname(dllFullPath);
typedef DLL_DIRECTORY_COOKIE(WINAPI *AddDllDirectoryFunc)(PCWSTR);
DllFunction<AddDllDirectoryFunc> _AddDllDirectory(
Dll("kernel32.dll", Dll::System()), "AddDllDirectory");
AddDllDirectoryFunc func = _AddDllDirectory;
DLL_DIRECTORY_COOKIE res = func(dirPath.c_str());
if (!res) {
JP_THROW(SysError(tstrings::any()
<< "AddDllDirectory(" << dirPath << ") failed", func));
}
LOG_TRACE(tstrings::any() << "AddDllDirectory(" << dirPath << "): OK");
// Important: use LOAD_LIBRARY_SEARCH_DEFAULT_DIRS flag,
// but not LOAD_LIBRARY_SEARCH_USER_DIRS!
HMODULE dllHandle = LoadLibraryEx(dllFullPath.c_str(), NULL,
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
LOG_TRACE(tstrings::any() << "LoadLibraryEx(" << dllFullPath
<< ", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS): " << dllHandle);
const auto freeDll = runAtEndOfScope([&dllHandle]() -> void {
Dll::freeLibrary(dllHandle);
});
return std::unique_ptr<Dll>(new Dll(dllFullPath));
}
void launchApp() {
// [RT-31061] otherwise UI can be left in back of other windows.
::AllowSetForegroundWindow(ASFW_ANY);
@ -48,13 +107,31 @@ void launchApp() {
const tstring launcherPath = SysInfo::getProcessModulePath();
const tstring appImageRoot = FileUtils::dirname(launcherPath);
AppLauncher()
std::unique_ptr<Jvm> jvm(AppLauncher()
.setImageRoot(appImageRoot)
.addJvmLibName(_T("bin\\jli.dll"))
.setAppDir(FileUtils::mkpath() << appImageRoot << _T("app"))
.setDefaultRuntimePath(FileUtils::mkpath() << appImageRoot
<< _T("runtime"))
.launch();
.createJvmLauncher());
std::unique_ptr<Dll> jvmDll;
try {
// Try load JVM DLL.
jvmDll = std::unique_ptr<Dll>(new Dll(jvm->getPath()));
} catch (const std::exception&) {
// JVM DLL load failed, though it exists in file system.
try {
// Try adjust the DLL search paths with AddDllDirectory() WINAPI CALL
jvmDll = loadDllWithAddDllDirectory(jvm->getPath());
} catch (const std::exception&) {
// AddDllDirectory() didn't work. Try altering PATH environment
// variable as the last resort.
jvmDll = loadDllWithAlteredPATH(jvm->getPath());
}
}
jvm->launch();
}
} // namespace

View File

@ -114,6 +114,16 @@ HMODULE getCurrentModuleHandle()
return hmodule;
}
void setEnvVariable(const tstring& name, const tstring& value)
{
if (!SetEnvironmentVariable(name.c_str(), value.c_str())) {
JP_THROW(SysError(tstrings::any()
<< "SetEnvironmentVariable("
<< name << ", " << value
<< ") failed", SetEnvironmentVariable));
}
}
tstring getCurrentModulePath()
{
return getModulePath(getCurrentModuleHandle());

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -43,6 +43,8 @@ namespace SysInfo {
// Returns handle of the current module (exe or dll).
// The function assumes this code is statically linked to the module.
HMODULE getCurrentModuleHandle();
void setEnvVariable(const tstring& name, const tstring& value);
}