diff options
| author | Guohui Wang <robertwgh@gmail.com> | 2015-04-09 03:30:39 -0700 |
|---|---|---|
| committer | Guohui Wang <robertwgh@gmail.com> | 2015-04-09 03:30:39 -0700 |
| commit | aa1401bf7cf45262f10c5318f99ce5be3ea767ae (patch) | |
| tree | 52e0768ff21b2ce1b2f2442e56c992cc16f17b06 | |
| parent | e419539b122715a970fc825d980b6fba5b0ff935 (diff) | |
| download | dlfcn-win32-aa1401bf7cf45262f10c5318f99ce5be3ea767ae.tar.gz dlfcn-win32-aa1401bf7cf45262f10c5318f99ce5be3ea767ae.tar.bz2 dlfcn-win32-aa1401bf7cf45262f10c5318f99ce5be3ea767ae.zip | |
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. |
