aboutsummaryrefslogtreecommitdiff
path: root/dlfcn.c
diff options
context:
space:
mode:
Diffstat (limited to 'dlfcn.c')
-rw-r--r--dlfcn.c127
1 files changed, 80 insertions, 47 deletions
diff --git a/dlfcn.c b/dlfcn.c
index 993808d..ec60423 100644
--- a/dlfcn.c
+++ b/dlfcn.c
@@ -72,34 +72,36 @@ static local_object *local_search( HMODULE hModule )
72 return NULL; 72 return NULL;
73} 73}
74 74
75static void local_add( HMODULE hModule ) 75static BOOL local_add( HMODULE hModule )
76{ 76{
77 local_object *pobject; 77 local_object *pobject;
78 local_object *nobject; 78 local_object *nobject;
79 79
80 if( hModule == NULL ) 80 if( hModule == NULL )
81 return; 81 return TRUE;
82 82
83 pobject = local_search( hModule ); 83 pobject = local_search( hModule );
84 84
85 /* Do not add object again if it's already on the list */ 85 /* Do not add object again if it's already on the list */
86 if( pobject ) 86 if( pobject )
87 return; 87 return TRUE;
88 88
89 for( pobject = &first_object; pobject->next; pobject = pobject->next ); 89 for( pobject = &first_object; pobject->next; pobject = pobject->next );
90 90
91 nobject = (local_object*) malloc( sizeof( local_object ) ); 91 nobject = (local_object*) malloc( sizeof( local_object ) );
92 92
93 /* Should this be enough to fail local_add, and therefore also fail
94 * dlopen?
95 */
96 if( !nobject ) 93 if( !nobject )
97 return; 94 {
95 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
96 return FALSE;
97 }
98 98
99 pobject->next = nobject; 99 pobject->next = nobject;
100 nobject->next = NULL; 100 nobject->next = NULL;
101 nobject->previous = pobject; 101 nobject->previous = pobject;
102 nobject->hModule = hModule; 102 nobject->hModule = hModule;
103
104 return TRUE;
103} 105}
104 106
105static void local_rem( HMODULE hModule ) 107static void local_rem( HMODULE hModule )
@@ -240,51 +242,73 @@ void *dlopen( const char *file, int mode )
240 HANDLE hCurrentProc; 242 HANDLE hCurrentProc;
241 DWORD dwProcModsBefore, dwProcModsAfter; 243 DWORD dwProcModsBefore, dwProcModsAfter;
242 char lpFileName[MAX_PATH]; 244 char lpFileName[MAX_PATH];
243 size_t i; 245 size_t i, len;
244 246
245 /* MSDN says backslashes *must* be used instead of forward slashes. */ 247 len = strlen( file );
246 for( i = 0 ; i < sizeof(lpFileName) - 1 ; i ++ ) 248
249 if( len >= sizeof( lpFileName ) )
247 { 250 {
248 if( !file[i] ) 251 SetLastError( ERROR_FILENAME_EXCED_RANGE );
249 break; 252 save_err_str( file );
250 else if( file[i] == '/' ) 253 hModule = NULL;
251 lpFileName[i] = '\\';
252 else
253 lpFileName[i] = file[i];
254 } 254 }
255 lpFileName[i] = '\0'; 255 else
256 {
257 /* MSDN says backslashes *must* be used instead of forward slashes. */
258 for( i = 0; i < len; i++ )
259 {
260 if( file[i] == '/' )
261 lpFileName[i] = '\\';
262 else
263 lpFileName[i] = file[i];
264 }
265 lpFileName[len] = '\0';
256 266
257 hCurrentProc = GetCurrentProcess( ); 267 hCurrentProc = GetCurrentProcess( );
258 268
259 if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsBefore ) == 0 ) 269 if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsBefore ) == 0 )
260 dwProcModsBefore = 0; 270 dwProcModsBefore = 0;
261 271
262 /* POSIX says the search path is implementation-defined. 272 /* POSIX says the search path is implementation-defined.
263 * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely 273 * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely
264 * to UNIX's search paths (start with system folders instead of current 274 * to UNIX's search paths (start with system folders instead of current
265 * folder). 275 * folder).
266 */ 276 */
267 hModule = LoadLibraryExA(lpFileName, NULL, 277 hModule = LoadLibraryExA( lpFileName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
268 LOAD_WITH_ALTERED_SEARCH_PATH ); 278
269 279 if( !hModule )
270 if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsAfter ) == 0 ) 280 {
271 dwProcModsAfter = 0; 281 save_err_str( lpFileName );
272 282 }
273 /* If the object was loaded with RTLD_LOCAL, add it to list of local 283 else
274 * objects, so that its symbols cannot be retrieved even if the handle for 284 {
275 * the original program file is passed. POSIX says that if the same 285 if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsAfter ) == 0 )
276 * file is specified in multiple invocations, and any of them are 286 dwProcModsAfter = 0;
277 * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the 287
278 * symbols will remain global. If number of loaded modules was not 288 /* If the object was loaded with RTLD_LOCAL, add it to list of local
279 * changed after calling LoadLibraryEx(), it means that library was 289 * objects, so that its symbols cannot be retrieved even if the handle for
280 * already loaded. 290 * the original program file is passed. POSIX says that if the same
281 */ 291 * file is specified in multiple invocations, and any of them are
282 if( !hModule ) 292 * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the
283 save_err_str( lpFileName ); 293 * symbols will remain global. If number of loaded modules was not
284 else if( (mode & RTLD_LOCAL) && dwProcModsBefore != dwProcModsAfter ) 294 * changed after calling LoadLibraryEx(), it means that library was
285 local_add( hModule ); 295 * already loaded.
286 else if( !(mode & RTLD_LOCAL) && dwProcModsBefore == dwProcModsAfter ) 296 */
287 local_rem( hModule ); 297 if( (mode & RTLD_LOCAL) && dwProcModsBefore != dwProcModsAfter )
298 {
299 if( !local_add( hModule ) )
300 {
301 save_err_str( lpFileName );
302 FreeLibrary( hModule );
303 hModule = NULL;
304 }
305 }
306 else if( !(mode & RTLD_LOCAL) && dwProcModsBefore == dwProcModsAfter )
307 {
308 local_rem( hModule );
309 }
310 }
311 }
288 } 312 }
289 313
290 /* Return to previous state of the error-mode bit flags. */ 314 /* Return to previous state of the error-mode bit flags. */
@@ -353,10 +377,17 @@ void *dlsym( void *handle, const char *name )
353 size_t sLen; 377 size_t sLen;
354 sLen = VirtualQueryEx( hCurrentProc, _ReturnAddress(), &info, sizeof( info ) ); 378 sLen = VirtualQueryEx( hCurrentProc, _ReturnAddress(), &info, sizeof( info ) );
355 if( sLen != sizeof( info ) ) 379 if( sLen != sizeof( info ) )
380 {
381 if( sLen != 0 )
382 SetLastError( ERROR_INVALID_PARAMETER );
356 goto end; 383 goto end;
384 }
357 hCaller = (HMODULE) info.AllocationBase; 385 hCaller = (HMODULE) info.AllocationBase;
358 if(!hCaller) 386 if( !hCaller )
387 {
388 SetLastError( ERROR_INVALID_PARAMETER );
359 goto end; 389 goto end;
390 }
360 } 391 }
361 392
362 if( handle != RTLD_NEXT ) 393 if( handle != RTLD_NEXT )
@@ -414,6 +445,8 @@ void *dlsym( void *handle, const char *name )
414end: 445end:
415 if( symbol == NULL ) 446 if( symbol == NULL )
416 { 447 {
448 if( GetLastError() == 0 )
449 SetLastError( ERROR_PROC_NOT_FOUND );
417 save_err_str( name ); 450 save_err_str( name );
418 } 451 }
419 452