diff options
author | Ramiro Polla <ramiro.polla@gmail.com> | 2007-06-29 22:42:58 +0000 |
---|---|---|
committer | Ramiro Polla <ramiro.polla@gmail.com> | 2007-06-29 22:42:58 +0000 |
commit | 40f1a4cc1e80c496aaab4f76a88810273ee0b15f (patch) | |
tree | bf608d4e7f793cd4c5ca9b3d8e6b3410083a8177 | |
parent | 649282b7f966c96548011c68eef8527358049b97 (diff) | |
download | dlfcn-win32-40f1a4cc1e80c496aaab4f76a88810273ee0b15f.tar.gz dlfcn-win32-40f1a4cc1e80c496aaab4f76a88810273ee0b15f.tar.bz2 dlfcn-win32-40f1a4cc1e80c496aaab4f76a88810273ee0b15f.zip |
Take care of our own error messages
-rw-r--r-- | dlfcn.c | 110 |
1 files changed, 64 insertions, 46 deletions
@@ -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 |
70 | static 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 | */ | ||
74 | static char error_buffer[65535]; | ||
75 | static int dlerror_was_last_call; | ||
71 | 76 | ||
72 | static int copy_string( char *dest, int dest_size, const char *src ) | 77 | static 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 | ||
97 | static 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 | |||
125 | static 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 | |||
92 | void *dlopen( const char *file, int mode ) | 134 | void *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 | ||
222 | char *dlerror( void ) | 268 | char *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 | } |