[PATCH] Win32: simplify loading of DLL functions
- From
Johannes Schindelin <johannes.schindelin@gmx.de>
- Date
- Sep 19, 2017, 15:24 UTC
- Message-ID
- <f5a3add27206df3e7f39efeac8a3c3b47f2b79f2.1505834586.git.johannes.schindelin@gmx.de>
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> ---
So far, there are no users (except in Git for Windows). Ben promised to make use of it in his fsmonitor patch series.
Published-As: https://github.com/dscho/git/releases/tag/lazyload-v1 Fetch-It-Via: git fetch https://github.com/dscho/git lazyload-v1 compat/win32/lazyload.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 compat/win32/lazyload.h
diff --git a/compat/win32/lazyload.h b/compat/win32/lazyload.h new file mode 100644 index 00000000000..91c10dad2fb --- /dev/null +++ b/compat/win32/lazyload.h @@ -0,0 +1,44 @@ +#ifndef LAZYLOAD_H +#define LAZYLOAD_H + +/* simplify loading of DLL functions */ + +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. + */ +#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 base-commit: 9ddaf86b06a8078420f59aec8cab6daa93cf1a91
-- 2.14.1.windows.1.1020.g03faabc8bc8.dirty