diff options
author | Timothy Gu <timothygu99@gmail.com> | 2015-08-06 14:33:43 +0800 |
---|---|---|
committer | Timothy Gu <timothygu99@gmail.com> | 2015-08-06 14:33:43 +0800 |
commit | 7cea745e8fd471c649b281b4e7236d83cdd4f413 (patch) | |
tree | 52e0768ff21b2ce1b2f2442e56c992cc16f17b06 | |
parent | e419539b122715a970fc825d980b6fba5b0ff935 (diff) | |
parent | aa1401bf7cf45262f10c5318f99ce5be3ea767ae (diff) | |
download | dlfcn-win32-7cea745e8fd471c649b281b4e7236d83cdd4f413.tar.gz dlfcn-win32-7cea745e8fd471c649b281b4e7236d83cdd4f413.tar.bz2 dlfcn-win32-7cea745e8fd471c649b281b4e7236d83cdd4f413.zip |
Merge pull request #20 from robertwgh/unicode
Added support for unicode character set.
-rw-r--r-- | dlfcn.c | 112 |
1 files changed, 90 insertions, 22 deletions
@@ -33,6 +33,19 @@ | |||
33 | #endif | 33 | #endif |
34 | #include "dlfcn.h" | 34 | #include "dlfcn.h" |
35 | 35 | ||
36 | #if ((defined(_WIN32) || defined(WIN32)) && (defined(_MSC_VER)) ) | ||
37 | #define snprintf sprintf_s | ||
38 | #endif | ||
39 | |||
40 | #ifdef UNICODE | ||
41 | #include <wchar.h> | ||
42 | #define CHAR wchar_t | ||
43 | #define UNICODE_L(s) L##s | ||
44 | #else | ||
45 | #define CHAR char | ||
46 | #define UNICODE_L(s) s | ||
47 | #endif | ||
48 | |||
36 | /* Note: | 49 | /* Note: |
37 | * MSDN says these functions are not thread-safe. We make no efforts to have | 50 | * MSDN says these functions are not thread-safe. We make no efforts to have |
38 | * any kind of thread safety. | 51 | * any kind of thread safety. |
@@ -86,7 +99,7 @@ static void global_add( global_object *start, HMODULE hModule ) | |||
86 | 99 | ||
87 | for( pobject = start; pobject->next; pobject = pobject->next ); | 100 | for( pobject = start; pobject->next; pobject = pobject->next ); |
88 | 101 | ||
89 | nobject = malloc( sizeof( global_object ) ); | 102 | nobject = (global_object*) malloc( sizeof( global_object ) ); |
90 | 103 | ||
91 | /* Should this be enough to fail global_add, and therefore also fail | 104 | /* Should this be enough to fail global_add, and therefore also fail |
92 | * dlopen? | 105 | * dlopen? |
@@ -125,10 +138,11 @@ static void global_rem( global_object *start, HMODULE hModule ) | |||
125 | * MSDN says the buffer cannot be larger than 64K bytes, so we set it to | 138 | * MSDN says the buffer cannot be larger than 64K bytes, so we set it to |
126 | * the limit. | 139 | * the limit. |
127 | */ | 140 | */ |
128 | static char error_buffer[65535]; | 141 | static CHAR error_buffer[65535]; |
129 | static char *current_error; | 142 | static CHAR *current_error; |
143 | static char dlerror_buffer[65536]; | ||
130 | 144 | ||
131 | static int copy_string( char *dest, int dest_size, const char *src ) | 145 | static int copy_string( CHAR *dest, int dest_size, const CHAR *src ) |
132 | { | 146 | { |
133 | int i = 0; | 147 | int i = 0; |
134 | 148 | ||
@@ -148,7 +162,7 @@ static int copy_string( char *dest, int dest_size, const char *src ) | |||
148 | return i; | 162 | return i; |
149 | } | 163 | } |
150 | 164 | ||
151 | static void save_err_str( const char *str ) | 165 | static void save_err_str( const CHAR *str ) |
152 | { | 166 | { |
153 | DWORD dwMessageId; | 167 | DWORD dwMessageId; |
154 | DWORD pos; | 168 | DWORD pos; |
@@ -160,13 +174,13 @@ static void save_err_str( const char *str ) | |||
160 | 174 | ||
161 | /* Format error message to: | 175 | /* Format error message to: |
162 | * "<argument to function that failed>": <Windows localized error message> | 176 | * "<argument to function that failed>": <Windows localized error message> |
163 | */ | 177 | */ |
164 | pos = copy_string( error_buffer, sizeof(error_buffer), "\"" ); | 178 | pos = copy_string( error_buffer, sizeof(error_buffer), UNICODE_L("\"") ); |
165 | pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, str ); | 179 | pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, str ); |
166 | pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, "\": " ); | 180 | pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, UNICODE_L("\": ") ); |
167 | pos += FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwMessageId, | 181 | pos += FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwMessageId, |
168 | MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), | 182 | MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), |
169 | error_buffer+pos, sizeof(error_buffer)-pos, NULL ); | 183 | error_buffer+pos, sizeof(error_buffer)-pos, NULL ); |
170 | 184 | ||
171 | if( pos > 1 ) | 185 | if( pos > 1 ) |
172 | { | 186 | { |
@@ -180,9 +194,19 @@ static void save_err_str( const char *str ) | |||
180 | 194 | ||
181 | static void save_err_ptr_str( const void *ptr ) | 195 | static void save_err_ptr_str( const void *ptr ) |
182 | { | 196 | { |
183 | char ptr_buf[19]; /* 0x<pointer> up to 64 bits. */ | 197 | CHAR ptr_buf[19]; /* 0x<pointer> up to 64 bits. */ |
198 | |||
199 | #ifdef UNICODE | ||
184 | 200 | ||
185 | sprintf_s( ptr_buf, 19, "0x%p", ptr ); | 201 | # if ((defined(_WIN32) || defined(WIN32)) && (defined(_MSC_VER)) ) |
202 | swprintf_s( ptr_buf, 19, UNICODE_L("0x%p"), ptr ); | ||
203 | # else | ||
204 | swprintf(ptr_buf, 19, UNICODE_L("0x%p"), ptr); | ||
205 | # endif | ||
206 | |||
207 | #else | ||
208 | snprintf( ptr_buf, 19, "0x%p", ptr ); | ||
209 | #endif | ||
186 | 210 | ||
187 | save_err_str( ptr_buf ); | 211 | save_err_str( ptr_buf ); |
188 | } | 212 | } |
@@ -220,11 +244,11 @@ void *dlopen( const char *file, int mode ) | |||
220 | 244 | ||
221 | 245 | ||
222 | /* GetModuleHandle( NULL ) only returns the current program file. So | 246 | /* GetModuleHandle( NULL ) only returns the current program file. So |
223 | * if we want to get ALL loaded module including those in linked DLLs, | 247 | * if we want to get ALL loaded module including those in linked DLLs, |
224 | * we have to use EnumProcessModules( ). | 248 | * we have to use EnumProcessModules( ). |
225 | */ | 249 | */ |
226 | if( EnumProcessModules( hCurrentProc, hAddtnlMods, | 250 | if( EnumProcessModules( hCurrentProc, hAddtnlMods, |
227 | sizeof( hAddtnlMods ), &cbNeeded ) != 0 ) | 251 | sizeof( hAddtnlMods ), &cbNeeded ) != 0 ) |
228 | { | 252 | { |
229 | DWORD i; | 253 | DWORD i; |
230 | for( i = 0; i < cbNeeded / sizeof( HMODULE ); i++ ) | 254 | for( i = 0; i < cbNeeded / sizeof( HMODULE ); i++ ) |
@@ -236,11 +260,11 @@ void *dlopen( const char *file, int mode ) | |||
236 | } | 260 | } |
237 | else | 261 | else |
238 | { | 262 | { |
239 | char lpFileName[MAX_PATH]; | 263 | CHAR lpFileName[MAX_PATH]; |
240 | int i; | 264 | int i; |
241 | 265 | ||
242 | /* MSDN says backslashes *must* be used instead of forward slashes. */ | 266 | /* MSDN says backslashes *must* be used instead of forward slashes. */ |
243 | for( i = 0 ; i < sizeof(lpFileName)-1 ; i++ ) | 267 | for( i = 0 ; i < sizeof(lpFileName) - 1 ; i ++ ) |
244 | { | 268 | { |
245 | if( !file[i] ) | 269 | if( !file[i] ) |
246 | break; | 270 | break; |
@@ -256,8 +280,8 @@ void *dlopen( const char *file, int mode ) | |||
256 | * to UNIX's search paths (start with system folders instead of current | 280 | * to UNIX's search paths (start with system folders instead of current |
257 | * folder). | 281 | * folder). |
258 | */ | 282 | */ |
259 | hModule = LoadLibraryEx( (LPSTR) lpFileName, NULL, | 283 | hModule = LoadLibraryEx(lpFileName, NULL, |
260 | LOAD_WITH_ALTERED_SEARCH_PATH ); | 284 | LOAD_WITH_ALTERED_SEARCH_PATH ); |
261 | 285 | ||
262 | /* If the object was loaded with RTLD_GLOBAL, add it to list of global | 286 | /* If the object was loaded with RTLD_GLOBAL, add it to list of global |
263 | * objects, so that its symbols may be retrieved even if the handle for | 287 | * objects, so that its symbols may be retrieved even if the handle for |
@@ -332,9 +356,14 @@ void *dlsym( void *handle, const char *name ) | |||
332 | FARPROC symbol; | 356 | FARPROC symbol; |
333 | HMODULE hModule; | 357 | HMODULE hModule; |
334 | 358 | ||
359 | #ifdef UNICODE | ||
360 | wchar_t namew[MAX_PATH]; | ||
361 | wmemset(namew, 0, MAX_PATH); | ||
362 | #endif | ||
363 | |||
335 | current_error = NULL; | 364 | current_error = NULL; |
336 | 365 | ||
337 | symbol = GetProcAddress( handle, name ); | 366 | symbol = GetProcAddress( (HMODULE) handle, name ); |
338 | 367 | ||
339 | if( symbol != NULL ) | 368 | if( symbol != NULL ) |
340 | goto end; | 369 | goto end; |
@@ -372,9 +401,27 @@ void *dlsym( void *handle, const char *name ) | |||
372 | 401 | ||
373 | end: | 402 | end: |
374 | if( symbol == NULL ) | 403 | if( symbol == NULL ) |
404 | { | ||
405 | #ifdef UNICODE | ||
406 | size_t converted_chars; | ||
407 | |||
408 | size_t str_len = strlen(name) + 1; | ||
409 | |||
410 | #if ((defined(_WIN32) || defined(WIN32)) && (defined(_MSC_VER)) ) | ||
411 | errno_t err = mbstowcs_s(&converted_chars, namew, str_len, name, str_len); | ||
412 | if (err != 0) | ||
413 | return NULL; | ||
414 | #else | ||
415 | mbstowcs(namew, name, str_len); | ||
416 | #endif | ||
417 | |||
418 | save_err_str( namew ); | ||
419 | #else | ||
375 | save_err_str( name ); | 420 | save_err_str( name ); |
421 | #endif | ||
422 | } | ||
376 | 423 | ||
377 | // warning C4054: 'type cast' : from function pointer 'FARPROC' to data pointer 'void *' | 424 | // warning C4054: 'type cast' : from function pointer 'FARPROC' to data pointer 'void *' |
378 | #ifdef _MSC_VER | 425 | #ifdef _MSC_VER |
379 | #pragma warning( suppress: 4054 ) | 426 | #pragma warning( suppress: 4054 ) |
380 | #endif | 427 | #endif |
@@ -383,7 +430,28 @@ end: | |||
383 | 430 | ||
384 | char *dlerror( void ) | 431 | char *dlerror( void ) |
385 | { | 432 | { |
386 | char *error_pointer = current_error; | 433 | char *error_pointer = dlerror_buffer; |
434 | |||
435 | #ifdef UNICODE | ||
436 | errno_t err = 0; | ||
437 | size_t converted_chars = 0; | ||
438 | size_t str_len = wcslen(current_error) + 1; | ||
439 | memset(error_pointer, 0, 65535); | ||
440 | |||
441 | # if ((defined(_WIN32) || defined(WIN32)) && (defined(_MSC_VER)) ) | ||
442 | err = wcstombs_s(&converted_chars, | ||
443 | error_pointer, str_len * sizeof(char), | ||
444 | current_error, str_len * sizeof(wchar_t)); | ||
445 | |||
446 | if (err != 0) | ||
447 | return NULL; | ||
448 | # else | ||
449 | wcstombs(error_pointer, current_error, str_len); | ||
450 | # endif | ||
451 | |||
452 | #else | ||
453 | memcpy(error_pointer, current_error, strlen(current_error) + 1); | ||
454 | #endif | ||
387 | 455 | ||
388 | /* POSIX says that invoking dlerror( ) a second time, immediately following | 456 | /* POSIX says that invoking dlerror( ) a second time, immediately following |
389 | * a prior invocation, shall result in NULL being returned. | 457 | * a prior invocation, shall result in NULL being returned. |