Skip to content

Commit

Permalink
On 1.7.x: Merge r1916254, r1916255, r1916256, r1916257, r1916258 from…
Browse files Browse the repository at this point in the history
… trunk:

  Fixes and improvements for win32 DLL late linking code.

git-svn-id: https://svn.apache.org/repos/asf/apr/apr/branches/1.7.x@1916420 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
Ivan Zhakov committed Mar 19, 2024
2 parents 99d799f + f805b12 commit 6079e86
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 24 deletions.
17 changes: 9 additions & 8 deletions include/arch/win32/apr_arch_misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,15 +198,16 @@ FARPROC apr_load_dll_func(apr_dlltoken_e fnLib, char *fnName, int ordinal);
*/
#define APR_DECLARE_LATE_DLL_FUNC(lib, rettype, calltype, fn, ord, args, names) \
typedef rettype (calltype *apr_winapi_fpt_##fn) args; \
static apr_winapi_fpt_##fn apr_winapi_pfn_##fn = NULL; \
static int apr_winapi_chk_##fn = 0; \
static volatile apr_winapi_fpt_##fn apr_winapi_pfn_##fn = (apr_winapi_fpt_##fn) (ULONG_PTR) (-1); \
static APR_INLINE int apr_winapi_ld_##fn(void) \
{ if (apr_winapi_pfn_##fn) return 1; \
if (apr_winapi_chk_##fn ++) return 0; \
if (!apr_winapi_pfn_##fn) \
apr_winapi_pfn_##fn = (apr_winapi_fpt_##fn) \
apr_load_dll_func(lib, #fn, ord); \
if (apr_winapi_pfn_##fn) return 1; else return 0; }; \
{ \
apr_winapi_fpt_##fn cached_func = apr_winapi_pfn_##fn; \
if (cached_func == (apr_winapi_fpt_##fn) (ULONG_PTR) (-1)) { \
cached_func = (apr_winapi_fpt_##fn) apr_load_dll_func(lib, #fn, ord); \
/* Pointer-sized writes are atomic on Windows. */ \
apr_winapi_pfn_##fn = cached_func; \
} \
if (cached_func) return 1; else return 0; }; \
static APR_INLINE rettype apr_winapi_##fn args \
{ if (apr_winapi_ld_##fn()) \
return (*(apr_winapi_pfn_##fn)) names; \
Expand Down
61 changes: 45 additions & 16 deletions misc/win32/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,32 +161,61 @@ apr_status_t apr_get_oslevel(apr_oslevel_e *level)
* missing from one or more releases of the Win32 API
*/

static const char* const lateDllName[DLL_defined] = {
"kernel32", "advapi32", "mswsock", "ws2_32", "shell32", "ntdll.dll",
"Iphplapi" };
static HMODULE lateDllHandle[DLL_defined] = {
NULL, NULL, NULL, NULL, NULL, NULL,
NULL };
typedef struct win32_late_dll_t {
const char *dll_name;
volatile HMODULE dll_handle;
} win32_late_dll_t;

static win32_late_dll_t late_dll[DLL_defined] = {
{"kernel32", INVALID_HANDLE_VALUE},
{"advapi32", INVALID_HANDLE_VALUE},
{"mswsock", INVALID_HANDLE_VALUE},
{"ws2_32", INVALID_HANDLE_VALUE},
{"shell32", INVALID_HANDLE_VALUE},
{"ntdll.dll", INVALID_HANDLE_VALUE},
{"Iphplapi", INVALID_HANDLE_VALUE}
};

FARPROC apr_load_dll_func(apr_dlltoken_e fnLib, char* fnName, int ordinal)
{
if (!lateDllHandle[fnLib]) {
lateDllHandle[fnLib] = LoadLibraryA(lateDllName[fnLib]);
if (!lateDllHandle[fnLib])
return NULL;
win32_late_dll_t *dll = &late_dll[fnLib];
HMODULE cached_dll_handle;

/* Pointer sized reads are atomic on Windows. */
cached_dll_handle = dll->dll_handle;
if (cached_dll_handle == INVALID_HANDLE_VALUE) {
HMODULE dll_handle = NULL;

dll_handle = LoadLibrary(dll->dll_name);

cached_dll_handle = InterlockedCompareExchangePointer(&dll->dll_handle,
dll_handle,
INVALID_HANDLE_VALUE);
if (cached_dll_handle == INVALID_HANDLE_VALUE) {
cached_dll_handle = dll_handle;
}
else if (dll_handle) {
/* Other thread won the race: release our library handle. */
FreeLibrary(dll_handle);
}
}

if (!cached_dll_handle) {
return NULL;
}

#if defined(_WIN32_WCE)
if (ordinal)
return GetProcAddressA(lateDllHandle[fnLib], (const char *)
(apr_ssize_t)ordinal);
return GetProcAddressA(cached_dll_handle,
(const char *) (apr_ssize_t)ordinal);
else
return GetProcAddressA(lateDllHandle[fnLib], fnName);
return GetProcAddressA(cached_dll_handle, fnName);
#else
if (ordinal)
return GetProcAddress(lateDllHandle[fnLib], (const char *)
(apr_ssize_t)ordinal);
return GetProcAddress(cached_dll_handle,
(const char *) (apr_ssize_t)ordinal);
else
return GetProcAddress(lateDllHandle[fnLib], fnName);
return GetProcAddress(cached_dll_handle, fnName);
#endif
}

Expand Down

0 comments on commit 6079e86

Please sign in to comment.