Browse Source
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 <blees@dcon.de> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Reviewed-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
Johannes Schindelin
7 years ago
committed by
Junio C Hamano
1 changed files with 57 additions and 0 deletions
@ -0,0 +1,57 @@ |
|||||||
|
#ifndef LAZYLOAD_H |
||||||
|
#define LAZYLOAD_H |
||||||
|
|
||||||
|
/* |
||||||
|
* A pair of macros to simplify loading of DLL functions. 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); |
||||||
|
*/ |
||||||
|
|
||||||
|
struct proc_addr { |
||||||
|
const char *const dll; |
||||||
|
const char *const function; |
||||||
|
FARPROC pfunction; |
||||||
|
unsigned initialized : 1; |
||||||
|
}; |
||||||
|
|
||||||
|
/* Declares a function to be loaded dynamically from a DLL. */ |
||||||
|
#define DECLARE_PROC_ADDR(dll, rettype, function, ...) \ |
||||||
|
static struct proc_addr proc_addr_##function = \ |
||||||
|
{ #dll, #function, NULL, 0 }; \ |
||||||
|
static rettype (WINAPI *function)(__VA_ARGS__) |
||||||
|
|
||||||
|
/* |
||||||
|
* Loads a function from a DLL (once-only). |
||||||
|
* Returns non-NULL function pointer on success. |
||||||
|
* Returns NULL + errno == ENOSYS on failure. |
||||||
|
* This function is not thread-safe. |
||||||
|
*/ |
||||||
|
#define INIT_PROC_ADDR(function) \ |
||||||
|
(function = get_proc_addr(&proc_addr_##function)) |
||||||
|
|
||||||
|
static inline void *get_proc_addr(struct proc_addr *proc) |
||||||
|
{ |
||||||
|
/* only do this once */ |
||||||
|
if (!proc->initialized) { |
||||||
|
HANDLE hnd; |
||||||
|
proc->initialized = 1; |
||||||
|
hnd = LoadLibraryExA(proc->dll, NULL, |
||||||
|
LOAD_LIBRARY_SEARCH_SYSTEM32); |
||||||
|
if (hnd) |
||||||
|
proc->pfunction = GetProcAddress(hnd, proc->function); |
||||||
|
} |
||||||
|
/* set ENOSYS if DLL or function was not found */ |
||||||
|
if (!proc->pfunction) |
||||||
|
errno = ENOSYS; |
||||||
|
return proc->pfunction; |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
Loading…
Reference in new issue