00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "dlfcn.h"
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023
00024
00025
00026
00027
00028
00029 typedef struct global_object {
00030 HMODULE hModule;
00031 struct global_object *previous;
00032 struct global_object *next;
00033 } global_object;
00034
00035 static global_object first_object;
00036
00037
00038 static global_object *global_search( HMODULE hModule )
00039 {
00040 global_object *pobject;
00041
00042 if( hModule == NULL )
00043 return NULL;
00044
00045 for( pobject = &first_object; pobject ; pobject = pobject->next )
00046 if( pobject->hModule == hModule )
00047 return pobject;
00048
00049 return NULL;
00050 }
00051
00052 static void global_add( HMODULE hModule )
00053 {
00054 global_object *pobject;
00055 global_object *nobject;
00056
00057 if( hModule == NULL )
00058 return;
00059
00060 pobject = global_search( hModule );
00061
00062
00063 if( pobject )
00064 return;
00065
00066 for( pobject = &first_object; pobject->next ; pobject = pobject->next );
00067
00068 nobject = malloc( sizeof(global_object) );
00069
00070
00071
00072
00073 if( !nobject )
00074 return;
00075
00076 pobject->next = nobject;
00077 nobject->next = NULL;
00078 nobject->previous = pobject;
00079 nobject->hModule = hModule;
00080 }
00081
00082 static void global_rem( HMODULE hModule )
00083 {
00084 global_object *pobject;
00085
00086 if( hModule == NULL )
00087 return;
00088
00089 pobject = global_search( hModule );
00090
00091 if( !pobject )
00092 return;
00093
00094 if( pobject->next )
00095 pobject->next->previous = pobject->previous;
00096 if( pobject->previous )
00097 pobject->previous->next = pobject->next;
00098
00099 free( pobject );
00100 }
00101
00102
00103
00104
00105
00106
00107 static char error_buffer[65535];
00108 static char *current_error;
00109
00110 static int copy_string( char *dest, int dest_size, const char *src )
00111 {
00112 int i = 0;
00113
00114
00115 if( !src && !dest )
00116 return 0;
00117
00118 for( i = 0 ; i < dest_size-1 ; i++ )
00119 {
00120 if( !src[i] )
00121 break;
00122 else
00123 dest[i] = src[i];
00124 }
00125 dest[i] = '\0';
00126
00127 return i;
00128 }
00129
00130 static void save_err_str( const char *str )
00131 {
00132 DWORD dwMessageId;
00133 DWORD pos;
00134
00135 dwMessageId = GetLastError( );
00136
00137 if( dwMessageId == 0 )
00138 return;
00139
00140
00141
00142
00143 pos = copy_string( error_buffer, sizeof(error_buffer), "\"" );
00144 pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, str );
00145 pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, "\": " );
00146 pos += FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwMessageId,
00147 MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
00148 error_buffer+pos, sizeof(error_buffer)-pos, NULL );
00149
00150 if( pos > 1 )
00151 {
00152
00153 if( error_buffer[pos-2] == '\r' && error_buffer[pos-1] == '\n' )
00154 error_buffer[pos-2] = '\0';
00155 }
00156
00157 current_error = error_buffer;
00158 }
00159
00160 static void save_err_ptr_str( const void *ptr )
00161 {
00162 char ptr_buf[19];
00163
00164 sprintf( ptr_buf, "0x%p", ptr );
00165
00166 save_err_str( ptr_buf );
00167 }
00168
00169 void *dlopen( const char *file, int mode )
00170 {
00171 HMODULE hModule;
00172 UINT uMode;
00173
00174 current_error = NULL;
00175
00176
00177 uMode = SetErrorMode( SEM_FAILCRITICALERRORS );
00178
00179 if( file == 0 )
00180 {
00181
00182
00183
00184
00185
00186
00187
00188
00189 hModule = GetModuleHandle( NULL );
00190
00191 if( !hModule )
00192 save_err_ptr_str( file );
00193 }
00194 else
00195 {
00196 char lpFileName[MAX_PATH];
00197 int i;
00198
00199
00200 for( i = 0 ; i < sizeof(lpFileName)-1 ; i++ )
00201 {
00202 if( !file[i] )
00203 break;
00204 else if( file[i] == '/' )
00205 lpFileName[i] = '\\';
00206 else
00207 lpFileName[i] = file[i];
00208 }
00209 lpFileName[i] = '\0';
00210
00211
00212
00213
00214
00215
00216 hModule = LoadLibraryEx( (LPSTR) lpFileName, NULL,
00217 LOAD_WITH_ALTERED_SEARCH_PATH );
00218
00219
00220
00221
00222
00223
00224
00225
00226 if( !hModule )
00227 save_err_str( lpFileName );
00228 else if( (mode & RTLD_GLOBAL) )
00229 global_add( hModule );
00230 }
00231
00232
00233 SetErrorMode( uMode );
00234
00235 return (void *) hModule;
00236 }
00237
00238 int dlclose( void *handle )
00239 {
00240 HMODULE hModule = (HMODULE) handle;
00241 BOOL ret;
00242
00243 current_error = NULL;
00244
00245 ret = FreeLibrary( hModule );
00246
00247
00248
00249
00250 if( ret )
00251 global_rem( hModule );
00252 else
00253 save_err_ptr_str( handle );
00254
00255
00256 ret = !ret;
00257
00258 return (int) ret;
00259 }
00260
00261 void *dlsym( void *handle, const char *name )
00262 {
00263 FARPROC symbol;
00264
00265 current_error = NULL;
00266
00267 symbol = GetProcAddress( handle, name );
00268
00269 if( symbol == NULL )
00270 {
00271 HMODULE hModule;
00272
00273
00274
00275
00276
00277 hModule = GetModuleHandle( NULL );
00278
00279 if( hModule == handle )
00280 {
00281 global_object *pobject;
00282
00283 for( pobject = &first_object; pobject ; pobject = pobject->next )
00284 {
00285 if( pobject->hModule )
00286 {
00287 symbol = GetProcAddress( pobject->hModule, name );
00288 if( symbol != NULL )
00289 break;
00290 }
00291 }
00292 }
00293
00294
00295
00296 }
00297
00298 if( symbol == NULL )
00299 save_err_str( name );
00300
00301 return (void*) symbol;
00302 }
00303
00304 char *dlerror( void )
00305 {
00306 char *error_pointer = current_error;
00307
00308
00309
00310
00311 current_error = NULL;
00312
00313 return error_pointer;
00314 }