Skip to content

Commit db2f7c4

Browse files
dschogitster
authored andcommitted
Win32: simplify loading of DLL functions
Dynamic loading of DLL functions is duplicated in several places in Git for Windows' source code. This patch adds a pair of macros to simplify the process: the DECLARE_PROC_ADDR(<dll>, <return-type>, <function-name>, ...<function-parameter-types>...) macro to be used at the beginning of a code block, and the INIT_PROC_ADDR(<function-name>) macro to call before using the declared function. The return value of the INIT_PROC_ADDR() call has to be checked; If it is NULL, the function was not found in the specified DLL. 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); return 0; Signed-off-by: Karsten Blees <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]> Reviewed-by: Jonathan Nieder <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 94c9fd2 commit db2f7c4

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed

compat/win32/lazyload.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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

0 commit comments

Comments
 (0)