1
0
Fork 0

Codechange: [WIN32] Add a wrapper around GetProcAddress()

pull/8698/head
glx22 2021-05-14 15:26:03 +02:00 committed by Loïc Guilloux
parent 15f66329c2
commit 744a9e4745
5 changed files with 66 additions and 54 deletions

View File

@ -368,22 +368,7 @@ static const uint MAX_FRAMES = 64;
char *CrashLogWindows::AppendDecodedStacktrace(char *buffer, const char *last) const char *CrashLogWindows::AppendDecodedStacktrace(char *buffer, const char *last) const
{ {
#define M(x) x "\0" DllLoader dbghelp(L"dbghelp.dll");
static const char dbg_import[] =
M("dbghelp.dll")
M("SymInitialize")
M("SymSetOptions")
M("SymCleanup")
M("StackWalk64")
M("SymFunctionTableAccess64")
M("SymGetModuleBase64")
M("SymGetModuleInfo64")
M("SymGetSymFromAddr64")
M("SymGetLineFromAddr64")
M("")
;
#undef M
struct ProcPtrs { struct ProcPtrs {
BOOL (WINAPI * pSymInitialize)(HANDLE, PCSTR, BOOL); BOOL (WINAPI * pSymInitialize)(HANDLE, PCSTR, BOOL);
BOOL (WINAPI * pSymSetOptions)(DWORD); BOOL (WINAPI * pSymSetOptions)(DWORD);
@ -394,12 +379,22 @@ char *CrashLogWindows::AppendDecodedStacktrace(char *buffer, const char *last) c
BOOL (WINAPI * pSymGetModuleInfo64)(HANDLE, DWORD64, PIMAGEHLP_MODULE64); BOOL (WINAPI * pSymGetModuleInfo64)(HANDLE, DWORD64, PIMAGEHLP_MODULE64);
BOOL (WINAPI * pSymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64); BOOL (WINAPI * pSymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64);
BOOL (WINAPI * pSymGetLineFromAddr64)(HANDLE, DWORD64, PDWORD, PIMAGEHLP_LINE64); BOOL (WINAPI * pSymGetLineFromAddr64)(HANDLE, DWORD64, PDWORD, PIMAGEHLP_LINE64);
} proc; } proc = {
dbghelp.GetProcAddress("SymInitialize"),
dbghelp.GetProcAddress("SymSetOptions"),
dbghelp.GetProcAddress("SymCleanup"),
dbghelp.GetProcAddress("StackWalk64"),
dbghelp.GetProcAddress("SymFunctionTableAccess64"),
dbghelp.GetProcAddress("SymGetModuleBase64"),
dbghelp.GetProcAddress("SymGetModuleInfo64"),
dbghelp.GetProcAddress("SymGetSymFromAddr64"),
dbghelp.GetProcAddress("SymGetLineFromAddr64"),
};
buffer += seprintf(buffer, last, "\nDecoded stack trace:\n"); buffer += seprintf(buffer, last, "\nDecoded stack trace:\n");
/* Try to load the functions from the DLL, if that fails because of a too old dbghelp.dll, just skip it. */ /* Try to load the functions from the DLL, if that fails because of a too old dbghelp.dll, just skip it. */
if (LoadLibraryList((Function*)&proc, dbg_import)) { if (dbghelp.Success()) {
/* Initialize symbol handler. */ /* Initialize symbol handler. */
HANDLE hCur = GetCurrentProcess(); HANDLE hCur = GetCurrentProcess();
proc.pSymInitialize(hCur, nullptr, TRUE); proc.pSymInitialize(hCur, nullptr, TRUE);
@ -486,14 +481,14 @@ char *CrashLogWindows::AppendDecodedStacktrace(char *buffer, const char *last) c
/* virtual */ int CrashLogWindows::WriteCrashDump(char *filename, const char *filename_last) const /* virtual */ int CrashLogWindows::WriteCrashDump(char *filename, const char *filename_last) const
{ {
int ret = 0; int ret = 0;
HMODULE dbghelp = LoadLibrary(L"dbghelp.dll"); DllLoader dbghelp(L"dbghelp.dll");
if (dbghelp != nullptr) { if (dbghelp.Success()) {
typedef BOOL (WINAPI *MiniDumpWriteDump_t)(HANDLE, DWORD, HANDLE, typedef BOOL (WINAPI *MiniDumpWriteDump_t)(HANDLE, DWORD, HANDLE,
MINIDUMP_TYPE, MINIDUMP_TYPE,
CONST PMINIDUMP_EXCEPTION_INFORMATION, CONST PMINIDUMP_EXCEPTION_INFORMATION,
CONST PMINIDUMP_USER_STREAM_INFORMATION, CONST PMINIDUMP_USER_STREAM_INFORMATION,
CONST PMINIDUMP_CALLBACK_INFORMATION); CONST PMINIDUMP_CALLBACK_INFORMATION);
MiniDumpWriteDump_t funcMiniDumpWriteDump = (MiniDumpWriteDump_t)GetProcAddress(dbghelp, "MiniDumpWriteDump"); MiniDumpWriteDump_t funcMiniDumpWriteDump = dbghelp.GetProcAddress("MiniDumpWriteDump");
if (funcMiniDumpWriteDump != nullptr) { if (funcMiniDumpWriteDump != nullptr) {
seprintf(filename, filename_last, "%scrash.dmp", _personal_dir.c_str()); seprintf(filename, filename_last, "%scrash.dmp", _personal_dir.c_str());
HANDLE file = CreateFile(OTTD2FS(filename).c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, 0); HANDLE file = CreateFile(OTTD2FS(filename).c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, 0);
@ -519,7 +514,6 @@ char *CrashLogWindows::AppendDecodedStacktrace(char *buffer, const char *last) c
} else { } else {
ret = -1; ret = -1;
} }
FreeLibrary(dbghelp);
} }
return ret; return ret;
} }

View File

@ -620,8 +620,9 @@ void LoadWin32Font(FontSize fs)
if (AddFontResourceEx(fontPath, FR_PRIVATE, 0) != 0) { if (AddFontResourceEx(fontPath, FR_PRIVATE, 0) != 0) {
/* Try a nice little undocumented function first for getting the internal font name. /* Try a nice little undocumented function first for getting the internal font name.
* Some documentation is found at: http://www.undocprint.org/winspool/getfontresourceinfo */ * Some documentation is found at: http://www.undocprint.org/winspool/getfontresourceinfo */
static DllLoader _gdi32(L"gdi32.dll");
typedef BOOL(WINAPI *PFNGETFONTRESOURCEINFO)(LPCTSTR, LPDWORD, LPVOID, DWORD); typedef BOOL(WINAPI *PFNGETFONTRESOURCEINFO)(LPCTSTR, LPDWORD, LPVOID, DWORD);
static PFNGETFONTRESOURCEINFO GetFontResourceInfo = (PFNGETFONTRESOURCEINFO)GetProcAddress(GetModuleHandle(L"Gdi32"), "GetFontResourceInfoW"); static PFNGETFONTRESOURCEINFO GetFontResourceInfo = _gdi32.GetProcAddress("GetFontResourceInfoW");
if (GetFontResourceInfo != nullptr) { if (GetFontResourceInfo != nullptr) {
/* Try to query an array of LOGFONTs that describe the file. */ /* Try to query an array of LOGFONTs that describe the file. */

View File

@ -50,30 +50,6 @@ bool MyShowCursor(bool show, bool toggle)
return !show; return !show;
} }
/**
* Helper function needed by dynamically loading libraries
*/
bool LoadLibraryList(Function proc[], const char *dll)
{
while (*dll != '\0') {
HMODULE lib;
lib = LoadLibrary(OTTD2FS(dll).c_str());
if (lib == nullptr) return false;
for (;;) {
FARPROC p;
while (*dll++ != '\0') { /* Nothing */ }
if (*dll == '\0') break;
p = GetProcAddress(lib, dll);
if (p == nullptr) return false;
*proc++ = (Function)p;
}
dll++;
}
return true;
}
void ShowOSErrorBox(const char *buf, bool system) void ShowOSErrorBox(const char *buf, bool system)
{ {
MyShowCursor(true); MyShowCursor(true);
@ -679,7 +655,8 @@ int OTTDStringCompare(const char *s1, const char *s2)
#endif #endif
if (first_time) { if (first_time) {
_CompareStringEx = (PFNCOMPARESTRINGEX)GetProcAddress(GetModuleHandle(L"Kernel32"), "CompareStringEx"); static DllLoader _kernel32(L"Kernel32.dll");
_CompareStringEx = _kernel32.GetProcAddress("CompareStringEx");
first_time = false; first_time = false;
} }

View File

@ -13,8 +13,47 @@
#include <windows.h> #include <windows.h>
bool MyShowCursor(bool show, bool toggle = false); bool MyShowCursor(bool show, bool toggle = false);
typedef void (*Function)(int); class DllLoader {
bool LoadLibraryList(Function proc[], const char *dll); public:
explicit DllLoader(LPCTSTR filename)
{
this->hmodule = ::LoadLibrary(filename);
if (this->hmodule == nullptr) this->success = false;
}
~DllLoader()
{
::FreeLibrary(this->hmodule);
}
bool Success() { return this->success; }
class ProcAddress {
public:
explicit ProcAddress(void *p) : p(p) {}
template <typename T, typename = std::enable_if_t<std::is_function_v<T>>>
operator T *() const
{
return reinterpret_cast<T *>(this->p);
}
private:
void *p;
};
ProcAddress GetProcAddress(const char *proc_name)
{
void *p = reinterpret_cast<void *>(::GetProcAddress(this->hmodule, proc_name));
if (p == nullptr) this->success = false;
return ProcAddress(p);
}
private:
HMODULE hmodule = nullptr;
bool success = true;
};
char *convert_from_fs(const wchar_t *name, char *utf8_buf, size_t buflen); char *convert_from_fs(const wchar_t *name, char *utf8_buf, size_t buflen);
wchar_t *convert_to_fs(const char *name, wchar_t *utf16_buf, size_t buflen); wchar_t *convert_to_fs(const char *name, wchar_t *utf16_buf, size_t buflen);

View File

@ -956,10 +956,11 @@ float VideoDriver_Win32Base::GetDPIScale()
static bool init_done = false; static bool init_done = false;
if (!init_done) { if (!init_done) {
init_done = true; init_done = true;
static DllLoader _user32(L"user32.dll");
_GetDpiForWindow = (PFNGETDPIFORWINDOW)GetProcAddress(GetModuleHandle(L"User32"), "GetDpiForWindow"); static DllLoader _shcore(L"shcore.dll");
_GetDpiForSystem = (PFNGETDPIFORSYSTEM)GetProcAddress(GetModuleHandle(L"User32"), "GetDpiForSystem"); _GetDpiForWindow = _user32.GetProcAddress("GetDpiForWindow");
_GetDpiForMonitor = (PFNGETDPIFORMONITOR)GetProcAddress(LoadLibrary(L"Shcore.dll"), "GetDpiForMonitor"); _GetDpiForSystem = _user32.GetProcAddress("GetDpiForSystem");
_GetDpiForMonitor = _shcore.GetProcAddress("GetDpiForMonitor");
} }
UINT cur_dpi = 0; UINT cur_dpi = 0;