Skip to content

Commit 42b78a1

Browse files
kbleesdscho
authored andcommitted
Win32: simplify loading of DLL functions
Dynamic loading of DLL functions is duplicated in several places. Add a set of macros to simplify the process. Signed-off-by: Karsten Blees <[email protected]>
1 parent 41c6ef4 commit 42b78a1

File tree

3 files changed

+53
-33
lines changed

3 files changed

+53
-33
lines changed

compat/mingw.c

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2017,23 +2017,16 @@ static const char *make_backslash_path(const char *path)
20172017
void mingw_open_html(const char *unixpath)
20182018
{
20192019
const char *htmlpath = make_backslash_path(unixpath);
2020-
typedef HINSTANCE (WINAPI *T)(HWND, const char *,
2021-
const char *, const char *, const char *, INT);
2022-
T ShellExecute;
2023-
HMODULE shell32;
20242020
int r;
2021+
DECLARE_PROC_ADDR(shell32.dll, HINSTANCE, ShellExecuteA,
2022+
HWND, LPCSTR, LPCSTR, LPCSTR, LPCSTR, INT);
20252023

2026-
shell32 = LoadLibrary("shell32.dll");
2027-
if (!shell32)
2024+
if (!INIT_PROC_ADDR(ShellExecuteA))
20282025
die("cannot load shell32.dll");
2029-
ShellExecute = (T)GetProcAddress(shell32, "ShellExecuteA");
2030-
if (!ShellExecute)
2031-
die("cannot run browser");
20322026

20332027
printf("Launching default browser to display HTML ...\n");
2034-
r = HCAST(int, ShellExecute(NULL, "open", htmlpath,
2028+
r = HCAST(int, ShellExecuteA(NULL, "open", htmlpath,
20352029
NULL, "\\", SW_SHOWNORMAL));
2036-
FreeLibrary(shell32);
20372030
/* see the MSDN documentation referring to the result codes here */
20382031
if (r <= 32) {
20392032
die("failed to launch browser for %.*s", MAX_PATH, unixpath);
@@ -2042,24 +2035,18 @@ void mingw_open_html(const char *unixpath)
20422035

20432036
int link(const char *oldpath, const char *newpath)
20442037
{
2045-
typedef BOOL (WINAPI *T)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES);
2046-
static T create_hard_link = NULL;
2038+
DECLARE_PROC_ADDR(kernel32.dll, BOOL, CreateHardLinkW,
2039+
LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES);
20472040
wchar_t woldpath[MAX_LONG_PATH], wnewpath[MAX_LONG_PATH];
2041+
2042+
if (!INIT_PROC_ADDR(CreateHardLinkW))
2043+
return -1;
2044+
20482045
if (xutftowcs_long_path(woldpath, oldpath) < 0 ||
20492046
xutftowcs_long_path(wnewpath, newpath) < 0)
20502047
return -1;
20512048

2052-
if (!create_hard_link) {
2053-
create_hard_link = (T) GetProcAddress(
2054-
GetModuleHandle("kernel32.dll"), "CreateHardLinkW");
2055-
if (!create_hard_link)
2056-
create_hard_link = (T)-1;
2057-
}
2058-
if (create_hard_link == (T)-1) {
2059-
errno = ENOSYS;
2060-
return -1;
2061-
}
2062-
if (!create_hard_link(wnewpath, woldpath, NULL)) {
2049+
if (!CreateHardLinkW(wnewpath, woldpath, NULL)) {
20632050
errno = err_win_to_posix(GetLastError());
20642051
return -1;
20652052
}

compat/win32.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,41 @@ static inline int get_file_attr(const char *fname, WIN32_FILE_ATTRIBUTE_DATA *fd
4040
}
4141
}
4242

43+
/* simplify loading of DLL functions */
44+
45+
struct proc_addr {
46+
const char *const dll;
47+
const char *const function;
48+
FARPROC pfunction;
49+
unsigned initialized : 1;
50+
};
51+
52+
/* Declares a function to be loaded dynamically from a DLL. */
53+
#define DECLARE_PROC_ADDR(dll, rettype, function, ...) \
54+
static struct proc_addr proc_addr_##function = \
55+
{ #dll, #function, NULL, 0 }; \
56+
static rettype (WINAPI *function)(__VA_ARGS__)
57+
58+
/*
59+
* Loads a function from a DLL (once-only).
60+
* Returns non-NULL function pointer on success.
61+
* Returns NULL + errno == ENOSYS on failure.
62+
*/
63+
#define INIT_PROC_ADDR(function) (function = get_proc_addr(&proc_addr_##function))
64+
65+
static inline void *get_proc_addr(struct proc_addr *proc)
66+
{
67+
/* only do this once */
68+
if (!proc->initialized) {
69+
proc->initialized = 1;
70+
HANDLE hnd = LoadLibraryA(proc->dll);
71+
if (hnd)
72+
proc->pfunction = GetProcAddress(hnd, proc->function);
73+
}
74+
/* set ENOSYS if DLL or function was not found */
75+
if (!proc->pfunction)
76+
errno = ENOSYS;
77+
return proc->pfunction;
78+
}
79+
4380
#endif

compat/winansi.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "../git-compat-util.h"
77
#include <wingdi.h>
88
#include <winreg.h>
9+
#include "win32.h"
910

1011
/*
1112
ANSI codes used by git: m, K
@@ -35,26 +36,21 @@ typedef struct _CONSOLE_FONT_INFOEX {
3536
#endif
3637
#endif
3738

38-
typedef BOOL (WINAPI *PGETCURRENTCONSOLEFONTEX)(HANDLE, BOOL,
39-
PCONSOLE_FONT_INFOEX);
40-
4139
static void warn_if_raster_font(void)
4240
{
4341
DWORD fontFamily = 0;
44-
PGETCURRENTCONSOLEFONTEX pGetCurrentConsoleFontEx;
42+
DECLARE_PROC_ADDR(kernel32.dll, BOOL, GetCurrentConsoleFontEx,
43+
HANDLE, BOOL, PCONSOLE_FONT_INFOEX);
4544

4645
/* don't bother if output was ascii only */
4746
if (!non_ascii_used)
4847
return;
4948

5049
/* GetCurrentConsoleFontEx is available since Vista */
51-
pGetCurrentConsoleFontEx = (PGETCURRENTCONSOLEFONTEX) GetProcAddress(
52-
GetModuleHandle("kernel32.dll"),
53-
"GetCurrentConsoleFontEx");
54-
if (pGetCurrentConsoleFontEx) {
50+
if (INIT_PROC_ADDR(GetCurrentConsoleFontEx)) {
5551
CONSOLE_FONT_INFOEX cfi;
5652
cfi.cbSize = sizeof(cfi);
57-
if (pGetCurrentConsoleFontEx(console, 0, &cfi))
53+
if (GetCurrentConsoleFontEx(console, 0, &cfi))
5854
fontFamily = cfi.FontFamily;
5955
} else {
6056
/* pre-Vista: check default console font in registry */

0 commit comments

Comments
 (0)