aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRamiro Polla <ramiro.polla@gmail.com>2007-06-29 22:42:58 +0000
committerRamiro Polla <ramiro.polla@gmail.com>2007-06-29 22:42:58 +0000
commit40f1a4cc1e80c496aaab4f76a88810273ee0b15f (patch)
treebf608d4e7f793cd4c5ca9b3d8e6b3410083a8177
parent649282b7f966c96548011c68eef8527358049b97 (diff)
downloaddlfcn-win32-40f1a4cc1e80c496aaab4f76a88810273ee0b15f.tar.gz
dlfcn-win32-40f1a4cc1e80c496aaab4f76a88810273ee0b15f.tar.bz2
dlfcn-win32-40f1a4cc1e80c496aaab4f76a88810273ee0b15f.zip
Take care of our own error messages
-rw-r--r--dlfcn.c110
1 files 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 )
66 } 66 }
67} 67}
68 68
69/* Argument to last function. Used in dlerror( ) */ 69/* POSIX says dlerror( ) doesn't have to be thread-safe, so we use one
70static char last_name[MAX_PATH]; 70 * static buffer.
71 * MSDN says the buffer cannot be larger than 64K bytes, so we set it to
72 * the limit.
73 */
74static char error_buffer[65535];
75static int dlerror_was_last_call;
71 76
72static int copy_string( char *dest, int dest_size, const char *src ) 77static int copy_string( char *dest, int dest_size, const char *src )
73{ 78{
@@ -89,19 +94,55 @@ static int copy_string( char *dest, int dest_size, const char *src )
89 return i; 94 return i;
90} 95}
91 96
97static void save_err_str( const char *str )
98{
99 DWORD dwMessageId;
100 DWORD pos;
101
102 dwMessageId = GetLastError( );
103
104 if( dwMessageId == 0 )
105 return;
106
107 /* Format error message to:
108 * "<argument to function that failed>": <Windows localized error message>
109 */
110 pos = copy_string( error_buffer, sizeof(error_buffer), "\"" );
111 pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, str );
112 pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, "\": " );
113 pos += FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwMessageId,
114 MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
115 error_buffer+pos, sizeof(error_buffer)-pos, NULL );
116
117 if( pos > 1 )
118 {
119 /* POSIX says the string must not have trailing <newline> */
120 if( error_buffer[pos-2] == '\r' && error_buffer[pos-1] == '\n' )
121 error_buffer[pos-2] = '\0';
122 }
123}
124
125static void save_err_ptr( const void *ptr )
126{
127 char ptr_buf[19]; /* 0x<pointer> up to 64 bits. */
128
129 sprintf( ptr_buf, "0x%p", ptr );
130
131 save_err_str( ptr_buf );
132}
133
92void *dlopen( const char *file, int mode ) 134void *dlopen( const char *file, int mode )
93{ 135{
94 HMODULE hModule; 136 HMODULE hModule;
95 UINT uMode; 137 UINT uMode;
96 138
139 dlerror_was_last_call = 0;
140
97 /* Do not let Windows display the critical-error-handler message box */ 141 /* Do not let Windows display the critical-error-handler message box */
98 uMode = SetErrorMode( SEM_FAILCRITICALERRORS ); 142 uMode = SetErrorMode( SEM_FAILCRITICALERRORS );
99 143
100 if( file == 0 ) 144 if( file == 0 )
101 { 145 {
102 /* Save NULL pointer for error message */
103 sprintf( last_name, "0x%p", file );
104
105 /* POSIX says that if the value of file is 0, a handle on a global 146 /* POSIX says that if the value of file is 0, a handle on a global
106 * symbol object must be provided. That object must be able to access 147 * symbol object must be provided. That object must be able to access
107 * all symbols from the original program file, and any objects loaded 148 * all symbols from the original program file, and any objects loaded
@@ -111,6 +152,9 @@ void *dlopen( const char *file, int mode )
111 * the RTLD_GLOBAL flag, we create our own list later on. 152 * the RTLD_GLOBAL flag, we create our own list later on.
112 */ 153 */
113 hModule = GetModuleHandle( NULL ); 154 hModule = GetModuleHandle( NULL );
155
156 if( !hModule )
157 save_err_ptr( file );
114 } 158 }
115 else 159 else
116 { 160 {
@@ -129,9 +173,6 @@ void *dlopen( const char *file, int mode )
129 } 173 }
130 lpFileName[i] = '\0'; 174 lpFileName[i] = '\0';
131 175
132 /* Save file name for error message */
133 copy_string( last_name, sizeof(last_name), lpFileName );
134
135 /* POSIX says the search path is implementation-defined. 176 /* POSIX says the search path is implementation-defined.
136 * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely 177 * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely
137 * to UNIX's search paths (start with system folders instead of current 178 * to UNIX's search paths (start with system folders instead of current
@@ -147,7 +188,9 @@ void *dlopen( const char *file, int mode )
147 * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the 188 * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the
148 * symbols will remain global. 189 * symbols will remain global.
149 */ 190 */
150 if( hModule && (mode & RTLD_GLOBAL) ) 191 if( !hModule )
192 save_err_str( lpFileName );
193 else if( (mode & RTLD_GLOBAL) )
151 global_object_add( hModule ); 194 global_object_add( hModule );
152 } 195 }
153 196
@@ -162,8 +205,7 @@ int dlclose( void *handle )
162 HMODULE hModule = (HMODULE) handle; 205 HMODULE hModule = (HMODULE) handle;
163 BOOL ret; 206 BOOL ret;
164 207
165 /* Save handle for error message */ 208 dlerror_was_last_call = 0;
166 sprintf( last_name, "0x%p", handle );
167 209
168 ret = FreeLibrary( hModule ); 210 ret = FreeLibrary( hModule );
169 211
@@ -172,6 +214,8 @@ int dlclose( void *handle )
172 */ 214 */
173 if( ret ) 215 if( ret )
174 global_object_rem( hModule ); 216 global_object_rem( hModule );
217 else
218 save_err_ptr( handle );
175 219
176 /* dlclose's return value in inverted in relation to FreeLibrary's. */ 220 /* dlclose's return value in inverted in relation to FreeLibrary's. */
177 ret = !ret; 221 ret = !ret;
@@ -183,8 +227,7 @@ void *dlsym( void *handle, const char *name )
183{ 227{
184 FARPROC symbol; 228 FARPROC symbol;
185 229
186 /* Save symbol name for error message */ 230 dlerror_was_last_call = 0;
187 copy_string( last_name, sizeof(last_name), name );
188 231
189 symbol = GetProcAddress( handle, name ); 232 symbol = GetProcAddress( handle, name );
190 233
@@ -216,46 +259,21 @@ void *dlsym( void *handle, const char *name )
216 CloseHandle( hModule ); 259 CloseHandle( hModule );
217 } 260 }
218 261
262 if( symbol == NULL )
263 save_err_str( name );
264
219 return (void*) symbol; 265 return (void*) symbol;
220} 266}
221 267
222char *dlerror( void ) 268char *dlerror( void )
223{ 269{
224 DWORD dwMessageId;
225 /* POSIX says this function doesn't have to be thread-safe, so we use one
226 * static buffer.
227 * MSDN says the buffer cannot be larger than 64K bytes, so we set it to
228 * the limit.
229 */
230 static char lpBuffer[65535];
231 DWORD ret;
232
233 dwMessageId = GetLastError( );
234
235 if( dwMessageId == 0 )
236 return NULL;
237
238 /* Format error message to:
239 * "<argument to function that failed>": <Windows localized error message>
240 */
241 ret = copy_string( lpBuffer, sizeof(lpBuffer), "\"" );
242 ret += copy_string( lpBuffer+ret, sizeof(lpBuffer)-ret, last_name );
243 ret += copy_string( lpBuffer+ret, sizeof(lpBuffer)-ret, "\": " );
244 ret += FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwMessageId,
245 MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
246 lpBuffer+ret, sizeof(lpBuffer)-ret, NULL );
247
248 if( ret > 1 )
249 {
250 /* POSIX says the string must not have trailing <newline> */
251 if( lpBuffer[ret-2] == '\r' && lpBuffer[ret-1] == '\n' )
252 lpBuffer[ret-2] = '\0';
253 }
254
255 /* POSIX says that invoking dlerror( ) a second time, immediately following 270 /* POSIX says that invoking dlerror( ) a second time, immediately following
256 * a prior invocation, shall result in NULL being returned. 271 * a prior invocation, shall result in NULL being returned.
257 */ 272 */
258 SetLastError(0); 273 if( dlerror_was_last_call )
274 return NULL;
275
276 dlerror_was_last_call = 1;
259 277
260 return lpBuffer; 278 return error_buffer;
261} 279}