]>
Commit | Line | Data |
---|---|---|
db2f7c48 JS |
1 | #ifndef LAZYLOAD_H |
2 | #define LAZYLOAD_H | |
3 | ||
4 | /* | |
5 | * A pair of macros to simplify loading of DLL functions. Example: | |
6 | * | |
7 | * DECLARE_PROC_ADDR(kernel32.dll, BOOL, CreateHardLinkW, | |
8 | * LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES); | |
9 | * | |
10 | * if (!INIT_PROC_ADDR(CreateHardLinkW)) | |
11 | * return error("Could not find CreateHardLinkW() function"; | |
12 | * | |
13 | * if (!CreateHardLinkW(source, target, NULL)) | |
14 | * return error("could not create hardlink from %S to %S", | |
15 | * source, target); | |
16 | */ | |
17 | ||
18 | struct proc_addr { | |
19 | const char *const dll; | |
20 | const char *const function; | |
21 | FARPROC pfunction; | |
22 | unsigned initialized : 1; | |
23 | }; | |
24 | ||
25 | /* Declares a function to be loaded dynamically from a DLL. */ | |
26 | #define DECLARE_PROC_ADDR(dll, rettype, function, ...) \ | |
27 | static struct proc_addr proc_addr_##function = \ | |
28 | { #dll, #function, NULL, 0 }; \ | |
29 | static rettype (WINAPI *function)(__VA_ARGS__) | |
30 | ||
31 | /* | |
32 | * Loads a function from a DLL (once-only). | |
33 | * Returns non-NULL function pointer on success. | |
34 | * Returns NULL + errno == ENOSYS on failure. | |
35 | * This function is not thread-safe. | |
36 | */ | |
37 | #define INIT_PROC_ADDR(function) \ | |
38 | (function = get_proc_addr(&proc_addr_##function)) | |
39 | ||
40 | static inline void *get_proc_addr(struct proc_addr *proc) | |
41 | { | |
42 | /* only do this once */ | |
43 | if (!proc->initialized) { | |
44 | HANDLE hnd; | |
45 | proc->initialized = 1; | |
46 | hnd = LoadLibraryExA(proc->dll, NULL, | |
47 | LOAD_LIBRARY_SEARCH_SYSTEM32); | |
48 | if (hnd) | |
49 | proc->pfunction = GetProcAddress(hnd, proc->function); | |
50 | } | |
51 | /* set ENOSYS if DLL or function was not found */ | |
52 | if (!proc->pfunction) | |
53 | errno = ENOSYS; | |
54 | return proc->pfunction; | |
55 | } | |
56 | ||
57 | #endif |