From 40f1a4cc1e80c496aaab4f76a88810273ee0b15f Mon Sep 17 00:00:00 2001 From: Ramiro Polla Date: Fri, 29 Jun 2007 22:42:58 +0000 Subject: Take care of our own error messages --- dlfcn.c | 110 +++++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 64 insertions(+), 46 deletions(-) diff --git a/dlfcn.c b/dlfcn.c index c279897..4c82304 100644 --- a/dlfcn.c +++ b/dlfcn.c @@ -66,8 +66,13 @@ static void global_object_rem( HMODULE hModule ) } } -/* Argument to last function. Used in dlerror( ) */ -static char last_name[MAX_PATH]; +/* POSIX says dlerror( ) doesn't have to be thread-safe, so we use one + * static buffer. + * MSDN says the buffer cannot be larger than 64K bytes, so we set it to + * the limit. + */ +static char error_buffer[65535]; +static int dlerror_was_last_call; static int copy_string( char *dest, int dest_size, const char *src ) { @@ -89,19 +94,55 @@ static int copy_string( char *dest, int dest_size, const char *src ) return i; } +static void save_err_str( const char *str ) +{ + DWORD dwMessageId; + DWORD pos; + + dwMessageId = GetLastError( ); + + if( dwMessageId == 0 ) + return; + + /* Format error message to: + * "": + */ + pos = copy_string( error_buffer, sizeof(error_buffer), "\"" ); + pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, str ); + pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, "\": " ); + pos += FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwMessageId, + MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), + error_buffer+pos, sizeof(error_buffer)-pos, NULL ); + + if( pos > 1 ) + { + /* POSIX says the string must not have trailing */ + if( error_buffer[pos-2] == '\r' && error_buffer[pos-1] == '\n' ) + error_buffer[pos-2] = '\0'; + } +} + +static void save_err_ptr( const void *ptr ) +{ + char ptr_buf[19]; /* 0x up to 64 bits. */ + + sprintf( ptr_buf, "0x%p", ptr ); + + save_err_str( ptr_buf ); +} + void *dlopen( const char *file, int mode ) { HMODULE hModule; UINT uMode; + dlerror_was_last_call = 0; + /* Do not let Windows display the critical-error-handler message box */ uMode = SetErrorMode( SEM_FAILCRITICALERRORS ); if( file == 0 ) { - /* Save NULL pointer for error message */ - sprintf( last_name, "0x%p", file ); - /* POSIX says that if the value of file is 0, a handle on a global * symbol object must be provided. That object must be able to access * all symbols from the original program file, and any objects loaded @@ -111,6 +152,9 @@ void *dlopen( const char *file, int mode ) * the RTLD_GLOBAL flag, we create our own list later on. */ hModule = GetModuleHandle( NULL ); + + if( !hModule ) + save_err_ptr( file ); } else { @@ -129,9 +173,6 @@ void *dlopen( const char *file, int mode ) } lpFileName[i] = '\0'; - /* Save file name for error message */ - copy_string( last_name, sizeof(last_name), lpFileName ); - /* POSIX says the search path is implementation-defined. * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely * to UNIX's search paths (start with system folders instead of current @@ -147,7 +188,9 @@ void *dlopen( const char *file, int mode ) * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the * symbols will remain global. */ - if( hModule && (mode & RTLD_GLOBAL) ) + if( !hModule ) + save_err_str( lpFileName ); + else if( (mode & RTLD_GLOBAL) ) global_object_add( hModule ); } @@ -162,8 +205,7 @@ int dlclose( void *handle ) HMODULE hModule = (HMODULE) handle; BOOL ret; - /* Save handle for error message */ - sprintf( last_name, "0x%p", handle ); + dlerror_was_last_call = 0; ret = FreeLibrary( hModule ); @@ -172,6 +214,8 @@ int dlclose( void *handle ) */ if( ret ) global_object_rem( hModule ); + else + save_err_ptr( handle ); /* dlclose's return value in inverted in relation to FreeLibrary's. */ ret = !ret; @@ -183,8 +227,7 @@ void *dlsym( void *handle, const char *name ) { FARPROC symbol; - /* Save symbol name for error message */ - copy_string( last_name, sizeof(last_name), name ); + dlerror_was_last_call = 0; symbol = GetProcAddress( handle, name ); @@ -216,46 +259,21 @@ void *dlsym( void *handle, const char *name ) CloseHandle( hModule ); } + if( symbol == NULL ) + save_err_str( name ); + return (void*) symbol; } char *dlerror( void ) { - DWORD dwMessageId; - /* POSIX says this function doesn't have to be thread-safe, so we use one - * static buffer. - * MSDN says the buffer cannot be larger than 64K bytes, so we set it to - * the limit. - */ - static char lpBuffer[65535]; - DWORD ret; - - dwMessageId = GetLastError( ); - - if( dwMessageId == 0 ) - return NULL; - - /* Format error message to: - * "": - */ - ret = copy_string( lpBuffer, sizeof(lpBuffer), "\"" ); - ret += copy_string( lpBuffer+ret, sizeof(lpBuffer)-ret, last_name ); - ret += copy_string( lpBuffer+ret, sizeof(lpBuffer)-ret, "\": " ); - ret += FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwMessageId, - MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), - lpBuffer+ret, sizeof(lpBuffer)-ret, NULL ); - - if( ret > 1 ) - { - /* POSIX says the string must not have trailing */ - if( lpBuffer[ret-2] == '\r' && lpBuffer[ret-1] == '\n' ) - lpBuffer[ret-2] = '\0'; - } - /* POSIX says that invoking dlerror( ) a second time, immediately following * a prior invocation, shall result in NULL being returned. */ - SetLastError(0); + if( dlerror_was_last_call ) + return NULL; + + dlerror_was_last_call = 1; - return lpBuffer; + return error_buffer; } -- cgit v1.2.3-55-g6feb