You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
57 lines
1.6 KiB
57 lines
1.6 KiB
#ifndef LAZYLOAD_H |
|
#define LAZYLOAD_H |
|
|
|
/* |
|
* A pair of macros to simplify loading of DLL functions. Example: |
|
* |
|
* DECLARE_PROC_ADDR(kernel32.dll, BOOL, CreateHardLinkW, |
|
* LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES); |
|
* |
|
* if (!INIT_PROC_ADDR(CreateHardLinkW)) |
|
* return error("Could not find CreateHardLinkW() function"; |
|
* |
|
* if (!CreateHardLinkW(source, target, NULL)) |
|
* return error("could not create hardlink from %S to %S", |
|
* source, target); |
|
*/ |
|
|
|
struct proc_addr { |
|
const char *const dll; |
|
const char *const function; |
|
FARPROC pfunction; |
|
unsigned initialized : 1; |
|
}; |
|
|
|
/* Declares a function to be loaded dynamically from a DLL. */ |
|
#define DECLARE_PROC_ADDR(dll, rettype, function, ...) \ |
|
static struct proc_addr proc_addr_##function = \ |
|
{ #dll, #function, NULL, 0 }; \ |
|
static rettype (WINAPI *function)(__VA_ARGS__) |
|
|
|
/* |
|
* Loads a function from a DLL (once-only). |
|
* Returns non-NULL function pointer on success. |
|
* Returns NULL + errno == ENOSYS on failure. |
|
* This function is not thread-safe. |
|
*/ |
|
#define INIT_PROC_ADDR(function) \ |
|
(function = get_proc_addr(&proc_addr_##function)) |
|
|
|
static inline void *get_proc_addr(struct proc_addr *proc) |
|
{ |
|
/* only do this once */ |
|
if (!proc->initialized) { |
|
HANDLE hnd; |
|
proc->initialized = 1; |
|
hnd = LoadLibraryExA(proc->dll, NULL, |
|
LOAD_LIBRARY_SEARCH_SYSTEM32); |
|
if (hnd) |
|
proc->pfunction = GetProcAddress(hnd, proc->function); |
|
} |
|
/* set ENOSYS if DLL or function was not found */ |
|
if (!proc->pfunction) |
|
errno = ENOSYS; |
|
return proc->pfunction; |
|
} |
|
|
|
#endif
|
|
|