Last active
November 18, 2022 15:33
-
-
Save robleh/2662aab2687ce61cc3e3a8f07f1bbb7b to your computer and use it in GitHub Desktop.
Import functions from default Windows DLLs without redeclaration
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <Windows.h> | |
| #include <assert.h> | |
| #define IMPORT(function) function, #function | |
| auto create_importer(const wchar_t* module_name) { | |
| HMODULE module = ::GetModuleHandleW(module_name); | |
| assert(nullptr != module); | |
| return[=]<typename T>(T declaration, const char* symbol) -> T { | |
| FARPROC address = ::GetProcAddress(module, symbol); | |
| assert(nullptr != address); | |
| return reinterpret_cast<T>(address); | |
| }; | |
| }; | |
| int wmain(int argc, wchar_t* argv[]) { | |
| // Using User32 for the message box example, this would more likely be Kernel32 or NTDLL. | |
| auto user32 = create_importer(L"user32.dll"); | |
| // This call is required for the example. Otherwise, User32.dll will not be loaded. | |
| MessageBoxW(nullptr, L"Load time import", L"User32 Message Box", MB_OK); | |
| auto message_box = user32(IMPORT(MessageBoxW)); // With macro | |
| // auto message_box = user32(MessageBoxW, "MessageBoxW"); // Without macro | |
| message_box(nullptr, L"Run time import", L"User32 Message Box", MB_OK); | |
| return EXIT_SUCCESS; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <Windows.h> | |
| #include <assert.h> | |
| #define IMPORT(function) function, #function | |
| struct RuntimeImporter { | |
| HMODULE m_dll; | |
| public: | |
| RuntimeImporter(const wchar_t* name) { | |
| m_dll = ::GetModuleHandleW(name); | |
| assert(nullptr != m_dll); | |
| } | |
| template<typename T> | |
| // Can't use a template operator() | |
| T import(T declaration, const char* symbol) const { | |
| FARPROC address = ::GetProcAddress(m_dll, symbol); | |
| assert(nullptr != address); | |
| return reinterpret_cast<T>(address); | |
| } | |
| }; | |
| int wmain(int argc, wchar_t* argv[]) { | |
| // Using User32 for the message box example, this would more likely be Kernel32 or NTDLL. | |
| RuntimeImporter user32{ L"user32.dll" }; | |
| // This call is required for the example. Otherwise, User32.dll will not be loaded. | |
| ::MessageBoxW(nullptr, L"Load time import", L"User32 Message Box", MB_OK); | |
| auto message_box = user32.import(IMPORT(MessageBoxW)); | |
| message_box(nullptr, L"Run time import", L"User32 Message Box", MB_OK); | |
| return EXIT_SUCCESS; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment