Merge branch 'dg/filter-branch-filter-order-doc'
[git] / compat / win32 / lazyload.h
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