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 typedef void (*FARVOIDPROC)(void); 19 20 struct proc_addr { 21 const char *const dll; 22 const char *const function; 23 FARVOIDPROC pfunction; 24 unsigned initialized : 1; 25 }; 26 27 /* Declares a function to be loaded dynamically from a DLL. */ 28 #define DECLARE_PROC_ADDR(dll, rettype, function, ...) \ 29 static struct proc_addr proc_addr_##function = \ 30 { #dll, #function, NULL, 0 }; \ 31 typedef rettype (WINAPI *proc_type_##function)(__VA_ARGS__); \ 32 static proc_type_##function function 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) \ 41 (function = (proc_type_##function)get_proc_addr(&proc_addr_##function)) 42 43 static inline FARVOIDPROC get_proc_addr(struct proc_addr *proc) 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) 52 proc->pfunction = (FARVOIDPROC)GetProcAddress(hnd, 53 proc->function); 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 62