Skip to content

Instantly share code, notes, and snippets.

@robleh
Last active November 18, 2022 15:33
Show Gist options
  • Select an option

  • Save robleh/2662aab2687ce61cc3e3a8f07f1bbb7b to your computer and use it in GitHub Desktop.

Select an option

Save robleh/2662aab2687ce61cc3e3a8f07f1bbb7b to your computer and use it in GitHub Desktop.
Import functions from default Windows DLLs without redeclaration
#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;
}
#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