diff options
-rw-r--r-- | win32/PlatWin.cxx | 48 | ||||
-rw-r--r-- | win32/PlatWin.h | 14 | ||||
-rw-r--r-- | win32/ScintillaWin.cxx | 7 |
3 files changed, 38 insertions, 31 deletions
diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 2206c026e..f09cdfcf1 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -81,7 +81,7 @@ bool LoadD2D() { static bool triedLoadingD2D = false; if (!triedLoadingD2D) { DWORD loadLibraryFlags = 0; - HMODULE kernel32 = ::GetModuleHandle(TEXT("kernel32.dll")); + HMODULE kernel32 = ::GetModuleHandleW(L"kernel32.dll"); if (kernel32) { if (::GetProcAddress(kernel32, "SetDefaultDllDirectories")) { // Availability of SetDefaultDllDirectories implies Windows 8+ or @@ -97,34 +97,30 @@ bool LoadD2D() { IUnknown **factory); hDLLD2D = ::LoadLibraryEx(TEXT("D2D1.DLL"), 0, loadLibraryFlags); - if (hDLLD2D) { - D2D1CFSig fnD2DCF = reinterpret_cast<D2D1CFSig>(::GetProcAddress(hDLLD2D, "D2D1CreateFactory")); - if (fnD2DCF) { - // A single threaded factory as Scintilla always draw on the GUI thread - fnD2DCF(D2D1_FACTORY_TYPE_SINGLE_THREADED, - __uuidof(ID2D1Factory), - nullptr, - reinterpret_cast<IUnknown**>(&pD2DFactory)); - } + D2D1CFSig fnD2DCF = DLLFunction<D2D1CFSig>(hDLLD2D, "D2D1CreateFactory"); + if (fnD2DCF) { + // A single threaded factory as Scintilla always draw on the GUI thread + fnD2DCF(D2D1_FACTORY_TYPE_SINGLE_THREADED, + __uuidof(ID2D1Factory), + nullptr, + reinterpret_cast<IUnknown**>(&pD2DFactory)); } hDLLDWrite = ::LoadLibraryEx(TEXT("DWRITE.DLL"), 0, loadLibraryFlags); - if (hDLLDWrite) { - DWriteCFSig fnDWCF = reinterpret_cast<DWriteCFSig>(::GetProcAddress(hDLLDWrite, "DWriteCreateFactory")); - if (fnDWCF) { - const GUID IID_IDWriteFactory2 = // 0439fc60-ca44-4994-8dee-3a9af7b732ec - { 0x0439fc60, 0xca44, 0x4994, { 0x8d, 0xee, 0x3a, 0x9a, 0xf7, 0xb7, 0x32, 0xec } }; - - const HRESULT hr = fnDWCF(DWRITE_FACTORY_TYPE_SHARED, - IID_IDWriteFactory2, + DWriteCFSig fnDWCF = DLLFunction<DWriteCFSig>(hDLLDWrite, "DWriteCreateFactory"); + if (fnDWCF) { + const GUID IID_IDWriteFactory2 = // 0439fc60-ca44-4994-8dee-3a9af7b732ec + { 0x0439fc60, 0xca44, 0x4994, { 0x8d, 0xee, 0x3a, 0x9a, 0xf7, 0xb7, 0x32, 0xec } }; + + const HRESULT hr = fnDWCF(DWRITE_FACTORY_TYPE_SHARED, + IID_IDWriteFactory2, + reinterpret_cast<IUnknown**>(&pIDWriteFactory)); + if (SUCCEEDED(hr)) { + // D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT + d2dDrawTextOptions = static_cast<D2D1_DRAW_TEXT_OPTIONS>(0x00000004); + } else { + fnDWCF(DWRITE_FACTORY_TYPE_SHARED, + __uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>(&pIDWriteFactory)); - if (SUCCEEDED(hr)) { - // D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT - d2dDrawTextOptions = static_cast<D2D1_DRAW_TEXT_OPTIONS>(0x00000004); - } else { - fnDWCF(DWRITE_FACTORY_TYPE_SHARED, - __uuidof(IDWriteFactory), - reinterpret_cast<IUnknown**>(&pIDWriteFactory)); - } } } diff --git a/win32/PlatWin.h b/win32/PlatWin.h index d7e544da6..9d17dff69 100644 --- a/win32/PlatWin.h +++ b/win32/PlatWin.h @@ -38,6 +38,20 @@ inline HWND HwndFromWindow(const Window &w) noexcept { void *PointerFromWindow(HWND hWnd) noexcept; void SetWindowPointer(HWND hWnd, void *ptr) noexcept; +/// Find a function in a DLL and convert to a function pointer. +/// This avoids undefined and conditionally defined behaviour. +template<typename T> +T DLLFunction(HMODULE hModule, LPCSTR lpProcName) noexcept { + if (!hModule) { + return nullptr; + } + FARPROC function = ::GetProcAddress(hModule, lpProcName); + static_assert(sizeof(T) == sizeof(function)); + T fp; + memcpy(&fp, &function, sizeof(T)); + return fp; +} + #if defined(USE_D2D) extern bool LoadD2D(); extern ID2D1Factory *pD2DFactory; diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index 9f6066cb9..01ffcbe76 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -527,11 +527,8 @@ void ScintillaWin::Init() { hrOle = ::OleInitialize(nullptr); // Find SetCoalescableTimer which is only available from Windows 8+ - HMODULE user32 = ::GetModuleHandle(TEXT("user32.dll")); - if (user32) { - SetCoalescableTimerFn = reinterpret_cast<SetCoalescableTimerSig>( - ::GetProcAddress(user32, "SetCoalescableTimer")); - } + HMODULE user32 = ::GetModuleHandleW(L"user32.dll"); + SetCoalescableTimerFn = DLLFunction<SetCoalescableTimerSig>(user32, "SetCoalescableTimer"); vs.indicators[SC_INDICATOR_UNKNOWN] = Indicator(INDIC_HIDDEN, ColourDesired(0, 0, 0xff)); vs.indicators[SC_INDICATOR_INPUT] = Indicator(INDIC_DOTS, ColourDesired(0, 0, 0xff)); |