aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPali Rohár <pali.rohar@gmail.com>2021-02-03 20:59:58 +0100
committerPali Rohár <pali.rohar@gmail.com>2021-02-03 20:59:58 +0100
commit06fea3fe8b3efe8c79f97fa724f703bc0e25aeef (patch)
tree76242f5a02117496107898597b904f1ea67de297
parent0e9d85a9d03bcedade35cced63ec6b969ab3451e (diff)
downloaddlfcn-win32-06fea3fe8b3efe8c79f97fa724f703bc0e25aeef.tar.gz
dlfcn-win32-06fea3fe8b3efe8c79f97fa724f703bc0e25aeef.tar.bz2
dlfcn-win32-06fea3fe8b3efe8c79f97fa724f703bc0e25aeef.zip
Add helper function MyGetModuleHandleFromAddress()
This function implements calling GetModuleHandleExA() with correct flags to retrieve hModule from passed address. To allow compilation also with older compilers and environments (like WDK) with any _WIN32_WINNT value, retrieve pointer to this function via GetProcAddress(). And as a fallback implementation use old code via VirtualQuery() which was there prior commit 8ec5ffef2eca.
-rw-r--r--src/dlfcn.c64
1 files changed, 57 insertions, 7 deletions
diff --git a/src/dlfcn.c b/src/dlfcn.c
index 4e4e10e..80bd119 100644
--- a/src/dlfcn.c
+++ b/src/dlfcn.c
@@ -24,9 +24,6 @@
24 * THE SOFTWARE. 24 * THE SOFTWARE.
25 */ 25 */
26 26
27#ifndef _WIN32_WINNT
28#define _WIN32_WINNT 0x0501
29#endif
30#ifdef _DEBUG 27#ifdef _DEBUG
31#define _CRTDBG_MAP_ALLOC 28#define _CRTDBG_MAP_ALLOC
32#include <stdlib.h> 29#include <stdlib.h>
@@ -36,6 +33,14 @@
36#include <stdio.h> 33#include <stdio.h>
37#include <stdlib.h> 34#include <stdlib.h>
38 35
36/* Older SDK versions do not have these macros */
37#ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
38#define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 0x4
39#endif
40#ifndef GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
41#define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 0x2
42#endif
43
39#ifdef _MSC_VER 44#ifdef _MSC_VER
40/* https://docs.microsoft.com/en-us/cpp/intrinsics/returnaddress */ 45/* https://docs.microsoft.com/en-us/cpp/intrinsics/returnaddress */
41#pragma intrinsic( _ReturnAddress ) 46#pragma intrinsic( _ReturnAddress )
@@ -196,6 +201,44 @@ static void save_err_ptr_str( const void *ptr, DWORD dwMessageId )
196 save_err_str( ptr_buf, dwMessageId ); 201 save_err_str( ptr_buf, dwMessageId );
197} 202}
198 203
204static HMODULE MyGetModuleHandleFromAddress( void *addr )
205{
206 static BOOL (WINAPI *GetModuleHandleExAPtr)(DWORD, LPCSTR, HMODULE *) = NULL;
207 static BOOL failed = FALSE;
208 HMODULE kernel32;
209 HMODULE hModule;
210 MEMORY_BASIC_INFORMATION info;
211 SIZE_T sLen;
212
213 if( !failed && GetModuleHandleExAPtr == NULL )
214 {
215 kernel32 = GetModuleHandleA( "Kernel32.dll" );
216 if( kernel32 != NULL )
217 GetModuleHandleExAPtr = (BOOL (WINAPI *)(DWORD, LPCSTR, HMODULE *)) GetProcAddress( kernel32, "GetModuleHandleExA" );
218 if( GetModuleHandleExAPtr == NULL )
219 failed = TRUE;
220 }
221
222 if( !failed )
223 {
224 /* If GetModuleHandleExA is available use it with GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS */
225 if( !GetModuleHandleExAPtr( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR) addr, &hModule ) )
226 return NULL;
227 }
228 else
229 {
230 /* To get HMODULE from address use undocumented hack from https://stackoverflow.com/a/2396380
231 * The HMODULE of a DLL is the same value as the module's base address.
232 */
233 sLen = VirtualQuery( addr, &info, sizeof( info ) );
234 if( sLen != sizeof( info ) )
235 return NULL;
236 hModule = (HMODULE) info.AllocationBase;
237 }
238
239 return hModule;
240}
241
199/* Load Psapi.dll at runtime, this avoids linking caveat */ 242/* Load Psapi.dll at runtime, this avoids linking caveat */
200static BOOL MyEnumProcessModules( HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded ) 243static BOOL MyEnumProcessModules( HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded )
201{ 244{
@@ -402,9 +445,12 @@ void *dlsym( void *handle, const char *name )
402 * The next object is the one found upon the application of a load 445 * The next object is the one found upon the application of a load
403 * order symbol resolution algorithm. To get caller function of dlsym() 446 * order symbol resolution algorithm. To get caller function of dlsym()
404 * use _ReturnAddress() intrinsic. To get HMODULE of caller function 447 * use _ReturnAddress() intrinsic. To get HMODULE of caller function
405 * use standard GetModuleHandleExA() function. 448 * use MyGetModuleHandleFromAddress() which calls either standard
449 * GetModuleHandleExA() function or hack via VirtualQuery().
406 */ 450 */
407 if( !GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR) _ReturnAddress( ), &hCaller ) ) 451 hCaller = MyGetModuleHandleFromAddress( _ReturnAddress( ) );
452
453 if( hCaller == NULL )
408 { 454 {
409 dwMessageId = ERROR_INVALID_PARAMETER; 455 dwMessageId = ERROR_INVALID_PARAMETER;
410 goto end; 456 goto end;
@@ -638,7 +684,9 @@ static BOOL fill_info( void *addr, Dl_info *info )
638 void *funcAddress = NULL; 684 void *funcAddress = NULL;
639 685
640 /* Get module of the specified address */ 686 /* Get module of the specified address */
641 if( !GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, addr, &hModule ) || hModule == NULL ) 687 hModule = MyGetModuleHandleFromAddress( addr );
688
689 if( hModule == NULL )
642 return FALSE; 690 return FALSE;
643 691
644 dwSize = GetModuleFileNameA( hModule, module_filename, sizeof( module_filename ) ); 692 dwSize = GetModuleFileNameA( hModule, module_filename, sizeof( module_filename ) );
@@ -676,7 +724,9 @@ int dladdr( void *addr, Dl_info *info )
676 HMODULE hModule; 724 HMODULE hModule;
677 725
678 /* Get module of the import thunk address */ 726 /* Get module of the import thunk address */
679 if( !GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, addr, &hModule ) || hModule == NULL ) 727 hModule = MyGetModuleHandleFromAddress( addr );
728
729 if( hModule == NULL )
680 return 0; 730 return 0;
681 731
682 if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IAT, &iat, &iatSize ) ) 732 if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IAT, &iat, &iatSize ) )