You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-29 16:16:38 +00:00
[Windows] Detect missing DLL dependencies and list them in the open_dynamic_library error message.
This commit is contained in:
@@ -47,9 +47,6 @@
|
|||||||
|
|
||||||
#include <psapi.h>
|
#include <psapi.h>
|
||||||
|
|
||||||
#pragma comment(lib, "psapi.lib")
|
|
||||||
#pragma comment(lib, "dbghelp.lib")
|
|
||||||
|
|
||||||
// Some versions of imagehlp.dll lack the proper packing directives themselves
|
// Some versions of imagehlp.dll lack the proper packing directives themselves
|
||||||
// so we need to do it.
|
// so we need to do it.
|
||||||
#pragma pack(push, before_imagehlp, 8)
|
#pragma pack(push, before_imagehlp, 8)
|
||||||
|
|||||||
@@ -409,6 +409,9 @@ def configure_msvc(env, vcvars_msvc_config):
|
|||||||
"wbemuuid",
|
"wbemuuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if env.debug_features:
|
||||||
|
LIBS += ["psapi", "dbghelp"]
|
||||||
|
|
||||||
if env["vulkan"]:
|
if env["vulkan"]:
|
||||||
env.AppendUnique(CPPDEFINES=["VULKAN_ENABLED"])
|
env.AppendUnique(CPPDEFINES=["VULKAN_ENABLED"])
|
||||||
if not env["use_volk"]:
|
if not env["use_volk"]:
|
||||||
@@ -587,6 +590,9 @@ def configure_mingw(env):
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if env.debug_features:
|
||||||
|
env.Append(LIBS=["psapi", "dbghelp"])
|
||||||
|
|
||||||
if env["vulkan"]:
|
if env["vulkan"]:
|
||||||
env.Append(CPPDEFINES=["VULKAN_ENABLED"])
|
env.Append(CPPDEFINES=["VULKAN_ENABLED"])
|
||||||
if not env["use_volk"]:
|
if not env["use_volk"]:
|
||||||
|
|||||||
@@ -55,6 +55,12 @@
|
|||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#include <wbemcli.h>
|
#include <wbemcli.h>
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
#pragma pack(push, before_imagehlp, 8)
|
||||||
|
#include <imagehlp.h>
|
||||||
|
#pragma pack(pop, before_imagehlp)
|
||||||
|
#endif
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
__declspec(dllexport) DWORD NvOptimusEnablement = 1;
|
__declspec(dllexport) DWORD NvOptimusEnablement = 1;
|
||||||
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
||||||
@@ -88,7 +94,7 @@ static String format_error_message(DWORD id) {
|
|||||||
|
|
||||||
LocalFree(messageBuffer);
|
LocalFree(messageBuffer);
|
||||||
|
|
||||||
return msg;
|
return msg.replace("\r", "").replace("\n", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void RedirectStream(const char *p_file_name, const char *p_mode, FILE *p_cpp_stream, const DWORD p_std_handle) {
|
void RedirectStream(const char *p_file_name, const char *p_mode, FILE *p_cpp_stream, const DWORD p_std_handle) {
|
||||||
@@ -277,6 +283,73 @@ Error OS_Windows::get_entropy(uint8_t *r_buffer, int p_bytes) {
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
void debug_dynamic_library_check_dependencies(const String &p_root_path, const String &p_path, HashSet<String> &r_checked, HashSet<String> &r_missing) {
|
||||||
|
if (r_checked.has(p_path)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
r_checked.insert(p_path);
|
||||||
|
|
||||||
|
LOADED_IMAGE loaded_image;
|
||||||
|
HANDLE file = CreateFileW((LPCWSTR)p_path.utf16().get_data(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||||
|
if (file != INVALID_HANDLE_VALUE) {
|
||||||
|
HANDLE file_mapping = CreateFileMappingW(file, nullptr, PAGE_READONLY | SEC_COMMIT, 0, 0, nullptr);
|
||||||
|
if (file_mapping != INVALID_HANDLE_VALUE) {
|
||||||
|
PVOID mapping = MapViewOfFile(file_mapping, FILE_MAP_READ, 0, 0, 0);
|
||||||
|
if (mapping) {
|
||||||
|
PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)mapping;
|
||||||
|
PIMAGE_NT_HEADERS nt_header = nullptr;
|
||||||
|
if (dos_header->e_magic == IMAGE_DOS_SIGNATURE) {
|
||||||
|
PCHAR nt_header_ptr;
|
||||||
|
nt_header_ptr = ((PCHAR)mapping) + dos_header->e_lfanew;
|
||||||
|
nt_header = (PIMAGE_NT_HEADERS)nt_header_ptr;
|
||||||
|
if (nt_header->Signature != IMAGE_NT_SIGNATURE) {
|
||||||
|
nt_header = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nt_header) {
|
||||||
|
loaded_image.ModuleName = nullptr;
|
||||||
|
loaded_image.hFile = file;
|
||||||
|
loaded_image.MappedAddress = (PUCHAR)mapping;
|
||||||
|
loaded_image.FileHeader = nt_header;
|
||||||
|
loaded_image.Sections = (PIMAGE_SECTION_HEADER)((LPBYTE)&nt_header->OptionalHeader + nt_header->FileHeader.SizeOfOptionalHeader);
|
||||||
|
loaded_image.NumberOfSections = nt_header->FileHeader.NumberOfSections;
|
||||||
|
loaded_image.SizeOfImage = GetFileSize(file, nullptr);
|
||||||
|
loaded_image.Characteristics = nt_header->FileHeader.Characteristics;
|
||||||
|
loaded_image.LastRvaSection = loaded_image.Sections;
|
||||||
|
loaded_image.fSystemImage = false;
|
||||||
|
loaded_image.fDOSImage = false;
|
||||||
|
loaded_image.Links.Flink = &loaded_image.Links;
|
||||||
|
loaded_image.Links.Blink = &loaded_image.Links;
|
||||||
|
|
||||||
|
ULONG size = 0;
|
||||||
|
const IMAGE_IMPORT_DESCRIPTOR *import_desc = (const IMAGE_IMPORT_DESCRIPTOR *)ImageDirectoryEntryToData((HMODULE)loaded_image.MappedAddress, false, IMAGE_DIRECTORY_ENTRY_IMPORT, &size);
|
||||||
|
if (import_desc) {
|
||||||
|
for (; import_desc->Name && import_desc->FirstThunk; import_desc++) {
|
||||||
|
char16_t full_name_wc[MAX_PATH];
|
||||||
|
const char *name_cs = (const char *)ImageRvaToVa(loaded_image.FileHeader, loaded_image.MappedAddress, import_desc->Name, 0);
|
||||||
|
String name = String(name_cs);
|
||||||
|
if (name.begins_with("api-ms-win-")) {
|
||||||
|
r_checked.insert(name);
|
||||||
|
} else if (SearchPathW(nullptr, (LPCWSTR)name.utf16().get_data(), nullptr, MAX_PATH, (LPWSTR)full_name_wc, nullptr)) {
|
||||||
|
debug_dynamic_library_check_dependencies(p_root_path, String::utf16(full_name_wc), r_checked, r_missing);
|
||||||
|
} else if (SearchPathW((LPCWSTR)(p_path.get_base_dir().utf16().get_data()), (LPCWSTR)name.utf16().get_data(), nullptr, MAX_PATH, (LPWSTR)full_name_wc, nullptr)) {
|
||||||
|
debug_dynamic_library_check_dependencies(p_root_path, String::utf16(full_name_wc), r_checked, r_missing);
|
||||||
|
} else {
|
||||||
|
r_missing.insert(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UnmapViewOfFile(mapping);
|
||||||
|
}
|
||||||
|
CloseHandle(file_mapping);
|
||||||
|
}
|
||||||
|
CloseHandle(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
|
Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
|
||||||
String path = p_path.replace("/", "\\");
|
String path = p_path.replace("/", "\\");
|
||||||
|
|
||||||
@@ -299,7 +372,29 @@ Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_han
|
|||||||
}
|
}
|
||||||
|
|
||||||
p_library_handle = (void *)LoadLibraryExW((LPCWSTR)(path.utf16().get_data()), nullptr, (p_also_set_library_path && has_dll_directory_api) ? LOAD_LIBRARY_SEARCH_DEFAULT_DIRS : 0);
|
p_library_handle = (void *)LoadLibraryExW((LPCWSTR)(path.utf16().get_data()), nullptr, (p_also_set_library_path && has_dll_directory_api) ? LOAD_LIBRARY_SEARCH_DEFAULT_DIRS : 0);
|
||||||
ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + p_path + ", error: " + format_error_message(GetLastError()) + ".");
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (!p_library_handle) {
|
||||||
|
DWORD err_code = GetLastError();
|
||||||
|
|
||||||
|
HashSet<String> checekd_libs;
|
||||||
|
HashSet<String> missing_libs;
|
||||||
|
debug_dynamic_library_check_dependencies(path, path, checekd_libs, missing_libs);
|
||||||
|
if (!missing_libs.is_empty()) {
|
||||||
|
String missing;
|
||||||
|
for (const String &E : missing_libs) {
|
||||||
|
if (!missing.is_empty()) {
|
||||||
|
missing += ", ";
|
||||||
|
}
|
||||||
|
missing += E;
|
||||||
|
}
|
||||||
|
ERR_FAIL_V_MSG(ERR_CANT_OPEN, vformat("Can't open dynamic library: %s, missing dependencies: (%s), error: \"%s\".", p_path, missing, format_error_message(err_code)));
|
||||||
|
} else {
|
||||||
|
ERR_FAIL_V_MSG(ERR_CANT_OPEN, vformat("Can't open dynamic library: %s, error: \"%s\"." + p_path, format_error_message(err_code)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s, error: \"%s\"." + p_path, format_error_message(GetLastError())));
|
||||||
|
#endif
|
||||||
|
|
||||||
if (cookie) {
|
if (cookie) {
|
||||||
remove_dll_directory(cookie);
|
remove_dll_directory(cookie);
|
||||||
@@ -323,7 +418,7 @@ Error OS_Windows::get_dynamic_library_symbol_handle(void *p_library_handle, cons
|
|||||||
p_symbol_handle = (void *)GetProcAddress((HMODULE)p_library_handle, p_name.utf8().get_data());
|
p_symbol_handle = (void *)GetProcAddress((HMODULE)p_library_handle, p_name.utf8().get_data());
|
||||||
if (!p_symbol_handle) {
|
if (!p_symbol_handle) {
|
||||||
if (!p_optional) {
|
if (!p_optional) {
|
||||||
ERR_FAIL_V_MSG(ERR_CANT_RESOLVE, "Can't resolve symbol " + p_name + ", error: " + String::num(GetLastError()) + ".");
|
ERR_FAIL_V_MSG(ERR_CANT_RESOLVE, vformat("Can't resolve symbol %s, error: \"%s\".", p_name, format_error_message(GetLastError())));
|
||||||
} else {
|
} else {
|
||||||
return ERR_CANT_RESOLVE;
|
return ERR_CANT_RESOLVE;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user