]>
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 | * | |
4a9b2049 | 7 | * DECLARE_PROC_ADDR(kernel32.dll, BOOL, WINAPI, CreateHardLinkW, |
db2f7c48 JS |
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 | ||
2d84c4ed CMAB |
18 | typedef void (*FARVOIDPROC)(void); |
19 | ||
db2f7c48 JS |
20 | struct proc_addr { |
21 | const char *const dll; | |
22 | const char *const function; | |
2d84c4ed | 23 | FARVOIDPROC pfunction; |
db2f7c48 JS |
24 | unsigned initialized : 1; |
25 | }; | |
26 | ||
27 | /* Declares a function to be loaded dynamically from a DLL. */ | |
4a9b2049 | 28 | #define DECLARE_PROC_ADDR(dll, rettype, convention, function, ...) \ |
db2f7c48 JS |
29 | static struct proc_addr proc_addr_##function = \ |
30 | { #dll, #function, NULL, 0 }; \ | |
4a9b2049 | 31 | typedef rettype (convention *proc_type_##function)(__VA_ARGS__); \ |
d2c470f9 | 32 | static proc_type_##function function |
db2f7c48 JS |
33 | |
34 | /* | |
35 | * Loads a function from a DLL (once-only). | |
36 | * Returns non-NULL function pointer on success. | |
37 | * Returns NULL + errno == ENOSYS on failure. | |
38 | * This function is not thread-safe. | |
39 | */ | |
40 | #define INIT_PROC_ADDR(function) \ | |
d2c470f9 | 41 | (function = (proc_type_##function)get_proc_addr(&proc_addr_##function)) |
db2f7c48 | 42 | |
2d84c4ed | 43 | static inline FARVOIDPROC get_proc_addr(struct proc_addr *proc) |
db2f7c48 JS |
44 | { |
45 | /* only do this once */ | |
46 | if (!proc->initialized) { | |
47 | HANDLE hnd; | |
48 | proc->initialized = 1; | |
49 | hnd = LoadLibraryExA(proc->dll, NULL, | |
50 | LOAD_LIBRARY_SEARCH_SYSTEM32); | |
51 | if (hnd) | |
2d84c4ed CMAB |
52 | proc->pfunction = (FARVOIDPROC)GetProcAddress(hnd, |
53 | proc->function); | |
db2f7c48 JS |
54 | } |
55 | /* set ENOSYS if DLL or function was not found */ | |
56 | if (!proc->pfunction) | |
57 | errno = ENOSYS; | |
58 | return proc->pfunction; | |
59 | } | |
60 | ||
61 | #endif |