]>
Commit | Line | Data |
---|---|---|
1a6944fd | 1 | /** dynamic library loader (mapping to svr4) |
7e616b10 RR |
2 | |
3 | Copyright (C) 1995 by Ke Jin <kejin@empress.com> | |
1a6944fd RR |
4 | |
5 | This program is free software; you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 2 of the License, or | |
8 | (at your option) any later version. | |
9 | ||
10 | This program is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | **/ | |
15 | ||
7e616b10 RR |
16 | #ifdef DLDAPI_OS2 |
17 | # define INCL_DOSMODULEMGR /* Module Manager values */ | |
18 | # define INCL_DOSERRORS /* Error values */ | |
19 | # include <os2.h> | |
20 | # include <stdio.h> | |
21 | #endif | |
1a6944fd | 22 | |
7e616b10 | 23 | #include "wx/setup.h" |
1a6944fd RR |
24 | #include <../iodbc/dlf.h> |
25 | #include <errno.h> | |
26 | ||
7e616b10 | 27 | #ifdef DLDAPI_DEFINED |
1a6944fd RR |
28 | # undef DLDAPI_DEFINED |
29 | #endif | |
30 | ||
7e616b10 | 31 | #ifdef DLDAPI_SVR4_DLFCN |
1a6944fd | 32 | # define DLDAPI_DEFINED |
7e616b10 | 33 | static char sccsid[] = "@(#)dynamic load interface -- SVR4 dlfcn"; |
1a6944fd RR |
34 | #endif |
35 | ||
7e616b10 | 36 | /********************************* |
1a6944fd | 37 | * |
7e616b10 | 38 | * HP/UX |
1a6944fd RR |
39 | * |
40 | *********************************/ | |
7e616b10 RR |
41 | #ifdef DLDAPI_HP_SHL |
42 | # define DLDAPI_DEFINED | |
43 | # include <dl.h> | |
1a6944fd | 44 | |
7e616b10 | 45 | static char sccsid[] = "@(#)dynamic load interface -- HP/UX dl(shl)"; |
1a6944fd | 46 | |
7e616b10 | 47 | void* dlopen(char* path, int mode) |
1a6944fd | 48 | { |
7e616b10 | 49 | return (void*)shl_load((char*)(path), BIND_DEFERRED, 0L); |
1a6944fd RR |
50 | } |
51 | ||
7e616b10 | 52 | void* dlsym(void* hdll, char* sym) |
1a6944fd | 53 | { |
7e616b10 RR |
54 | void* symaddr = 0; |
55 | int ret; | |
1a6944fd | 56 | |
7e616b10 RR |
57 | if( ! hdll ) |
58 | hdll = (void*)PROG_HANDLE; | |
1a6944fd | 59 | |
7e616b10 RR |
60 | /* Remember, a driver may export calls as function pointers |
61 | * (i.e. with type TYPE_DATA) rather than as functions | |
62 | * (i.e. with type TYPE_PROCEDURE). Thus, to be safe, we | |
63 | * uses TYPE_UNDEFINED to cover all of them. | |
64 | */ | |
65 | ret = shl_findsym((shl_t*)&hdll, sym, TYPE_UNDEFINED, &symaddr); | |
1a6944fd | 66 | |
7e616b10 RR |
67 | if( ret == -1 ) |
68 | return 0; | |
1a6944fd | 69 | |
7e616b10 | 70 | return symaddr; |
1a6944fd RR |
71 | } |
72 | ||
7e616b10 | 73 | char* dlerror() |
1a6944fd | 74 | { |
7e616b10 | 75 | extern char* strerror(); |
1a6944fd | 76 | |
7e616b10 | 77 | return strerror(errno); |
1a6944fd RR |
78 | } |
79 | ||
7e616b10 | 80 | int dlclose(void* hdll) |
1a6944fd | 81 | { |
7e616b10 | 82 | return shl_unload((shl_t)hdll); |
1a6944fd RR |
83 | } |
84 | ||
7e616b10 | 85 | #endif /* end of HP/UX Seection */ |
1a6944fd RR |
86 | |
87 | /********************************* | |
88 | * | |
7e616b10 | 89 | * IBM AIX |
1a6944fd RR |
90 | * |
91 | *********************************/ | |
7e616b10 RR |
92 | #ifdef DLDAPI_AIX_LOAD |
93 | # define DLDAPI_DEFINED | |
94 | # include <sys/ldr.h> | |
95 | # include <sys/stat.h> | |
96 | # include <nlist.h> | |
1a6944fd RR |
97 | |
98 | /* | |
7e616b10 | 99 | * Following id sting is a copyright mark. Removing(i.e. use the |
1a6944fd | 100 | * source code in this .c file without include it or make it not |
7e616b10 RR |
101 | * appear in the final object file of AIX platform) or modifing |
102 | * it without permission from original author(kejin@empress.com) | |
1a6944fd RR |
103 | * are copyright violation. |
104 | */ | |
105 | static char sccsid[] | |
7e616b10 | 106 | = "@(#)dynamic load interface, Copyright(c) 1995 by Ke Jin"; |
1a6944fd | 107 | |
7e616b10 RR |
108 | # ifndef HTAB_SIZE |
109 | # define HTAB_SIZE 256 | |
1a6944fd RR |
110 | # endif |
111 | ||
7e616b10 | 112 | # define FACTOR 0.618039887 /* i.e. (sqrt(5) - 1)/2 */ |
1a6944fd | 113 | |
7e616b10 RR |
114 | # ifndef ENTRY_SYM |
115 | # define ENTRY_SYM ".__start" /* default entry point for aix */ | |
1a6944fd RR |
116 | # endif |
117 | ||
118 | typedef struct slot_s | |
119 | { | |
7e616b10 RR |
120 | char* sym; |
121 | long fdesc[3]; /* 12 bytes function descriptor */ | |
122 | struct slot_s* next; | |
1a6944fd RR |
123 | } slot_t; |
124 | ||
125 | /* Note: on AIX, a function pointer actually points to a | |
126 | * function descriptor, a 12 bytes data. The first 4 bytes | |
7e616b10 | 127 | * is the virtual address of the function. The next 4 bytes |
1a6944fd | 128 | * is the virtual address of TOC (Table of Contents) of the |
7e616b10 RR |
129 | * object module the function belong to. The last 4 bytes |
130 | * are always 0 for C and Fortran functions. Every object | |
1a6944fd RR |
131 | * module has an entry point (which can be specified at link |
132 | * time by -e ld option). iODBC driver manager requires ODBC | |
133 | * driver shared library always use the default entry point | |
134 | * (so you shouldn't use -e ld option when creating a driver | |
7e616b10 | 135 | * share library). load() returns the function descriptor of |
1a6944fd RR |
136 | * a module's entry point. From which we can calculate function |
137 | * descriptors of other functions in the same module by using | |
7e616b10 RR |
138 | * the fact that the load() doesn't change the relative |
139 | * offset of functions to their module entry point(i.e the | |
140 | * offset in memory loaded by load() will be as same as in | |
141 | * the module library file). | |
1a6944fd RR |
142 | */ |
143 | ||
7e616b10 RR |
144 | typedef slot_t* hent_t; |
145 | typedef struct nlist nlist_t; | |
146 | typedef struct stat stat_t; | |
1a6944fd | 147 | |
7e616b10 | 148 | typedef struct obj |
1a6944fd | 149 | { |
7e616b10 RR |
150 | int dev; /* device id */ |
151 | int ino; /* inode number */ | |
152 | char* path; /* file name */ | |
153 | int (*pentry)(); /* entry point of this share library */ | |
154 | int refn; /* number of reference */ | |
155 | hent_t htab[HTAB_SIZE]; | |
156 | struct obj* | |
157 | next; | |
1a6944fd RR |
158 | } obj_t; |
159 | ||
7e616b10 | 160 | static char* errmsg = 0; |
1a6944fd RR |
161 | |
162 | static void init_htab(hent_t* ht) | |
163 | /* initate a hashing table */ | |
164 | { | |
7e616b10 | 165 | int i; |
1a6944fd | 166 | |
7e616b10 RR |
167 | for(i=0; i<HTAB_SIZE; i++) |
168 | ht[i] = (slot_t*)0; | |
1a6944fd | 169 | |
7e616b10 | 170 | return; |
1a6944fd RR |
171 | } |
172 | ||
173 | static void clean_htab(hent_t* ht) | |
174 | /* free all slots */ | |
175 | { | |
7e616b10 RR |
176 | int i; |
177 | slot_t* ent; | |
178 | slot_t* tent; | |
179 | ||
180 | for(i = 0; i< HTAB_SIZE; i++) | |
181 | { | |
182 | for( ent = ht[i]; ent; ) | |
183 | { | |
184 | tent = ent->next; | |
185 | ||
186 | free(ent->sym); | |
187 | free(ent); | |
188 | ||
189 | ent = tent; | |
190 | } | |
191 | ||
192 | ht[i] = 0; | |
193 | } | |
194 | ||
195 | return; | |
1a6944fd RR |
196 | } |
197 | ||
7e616b10 | 198 | static int hash(char* sym ) |
1a6944fd | 199 | { |
7e616b10 RR |
200 | int a, key; |
201 | double f; | |
1a6944fd | 202 | |
7e616b10 RR |
203 | if( !sym || !*sym ) |
204 | return 0; | |
1a6944fd | 205 | |
7e616b10 | 206 | for(key=*sym;*sym;sym++) |
1a6944fd | 207 | { |
7e616b10 | 208 | key += *sym; |
1a6944fd RR |
209 | a = key; |
210 | ||
7e616b10 RR |
211 | key = (int)( (a<<8) + (key>>8) ); |
212 | key = (key>0)? key:-key; | |
1a6944fd RR |
213 | } |
214 | ||
7e616b10 RR |
215 | f = key*FACTOR; |
216 | a = (int)f; | |
1a6944fd | 217 | |
7e616b10 | 218 | return (int)((HTAB_SIZE - 1)*( f - a )); |
1a6944fd RR |
219 | } |
220 | ||
7e616b10 | 221 | static hent_t search(hent_t* htab, char* sym) |
1a6944fd RR |
222 | /* search hashing table to find a matched slot */ |
223 | { | |
7e616b10 RR |
224 | int key; |
225 | slot_t* ent; | |
1a6944fd | 226 | |
7e616b10 | 227 | key = hash(sym); |
1a6944fd | 228 | |
7e616b10 RR |
229 | for(ent = htab[key]; ent; ent = ent->next ) |
230 | { | |
231 | if(!strcmp(ent->sym, sym)) | |
232 | return ent; | |
233 | } | |
1a6944fd | 234 | |
7e616b10 | 235 | return 0; /* no match */ |
1a6944fd RR |
236 | } |
237 | ||
7e616b10 | 238 | static void insert(hent_t* htab, slot_t* ent) |
1a6944fd RR |
239 | /* insert a new slot to hashing table */ |
240 | { | |
7e616b10 | 241 | int key; |
1a6944fd | 242 | |
7e616b10 | 243 | key = hash(ent->sym); |
1a6944fd | 244 | |
7e616b10 RR |
245 | ent->next = htab[key]; |
246 | htab[key] = ent; | |
1a6944fd | 247 | |
7e616b10 | 248 | return; |
1a6944fd RR |
249 | } |
250 | ||
7e616b10 | 251 | static slot_t* slot_alloc(char* sym) |
1a6944fd RR |
252 | /* allocate a new slot with symbol */ |
253 | { | |
7e616b10 | 254 | slot_t* ent; |
1a6944fd | 255 | |
7e616b10 | 256 | ent = (slot_t*)malloc(sizeof(slot_t)); |
1a6944fd | 257 | |
7e616b10 | 258 | ent->sym = (char*)malloc(strlen(sym)+1); |
1a6944fd | 259 | |
7e616b10 RR |
260 | if( ! ent->sym ) |
261 | { | |
262 | free(ent); | |
263 | return 0; | |
264 | } | |
1a6944fd | 265 | |
7e616b10 | 266 | strcpy( ent->sym, sym ); |
1a6944fd | 267 | |
7e616b10 | 268 | return ent; |
1a6944fd RR |
269 | } |
270 | ||
271 | static obj_t* obj_list = 0; | |
272 | ||
7e616b10 | 273 | void* dlopen(char* file, int mode ) |
1a6944fd | 274 | { |
7e616b10 RR |
275 | stat_t st; |
276 | obj_t* pobj; | |
277 | char buf[1024]; | |
278 | ||
279 | if( ! file || ! *file ) | |
280 | { | |
281 | errno = EINVAL; | |
282 | return 0; | |
283 | } | |
284 | ||
285 | errno = 0; | |
286 | errmsg = 0; | |
1a6944fd RR |
287 | |
288 | #if 0 | |
7e616b10 RR |
289 | if( file[0] != '/' && file[0] != '.' ) |
290 | { | |
291 | for(;;) | |
292 | { | |
293 | sprintf(buf, "/lib/%s", file); | |
294 | ||
295 | if( stat( buf, &st ) ) | |
296 | { | |
297 | file = buf; | |
298 | break; | |
299 | } | |
300 | ||
301 | sprintf(buf, "/usr/lib/%s", file); | |
302 | ||
303 | if( stat( buf, &st ) ) | |
304 | { | |
305 | file = buf; | |
306 | break; | |
307 | } | |
308 | ||
309 | if( stat( file, &st ) ) | |
310 | break; | |
311 | ||
312 | return 0; | |
313 | } | |
314 | } | |
315 | else | |
1a6944fd | 316 | #endif |
7e616b10 RR |
317 | if( stat( file, &st ) ) |
318 | return 0; | |
1a6944fd | 319 | |
7e616b10 RR |
320 | for( pobj = obj_list; pobj; pobj = pobj->next ) |
321 | /* find a match object */ | |
322 | { | |
323 | if( pobj->ino == st.st_ino | |
324 | && pobj->dev == st.st_dev ) | |
325 | { | |
326 | /* found a match. increase its | |
327 | * reference count and return | |
328 | * its address */ | |
329 | pobj->refn ++; | |
330 | return pobj; | |
331 | } | |
332 | } | |
1a6944fd | 333 | |
7e616b10 | 334 | pobj = (obj_t*)malloc( sizeof(obj_t) ); |
1a6944fd | 335 | |
7e616b10 RR |
336 | if( ! pobj ) |
337 | return 0; | |
1a6944fd | 338 | |
7e616b10 | 339 | pobj->path = (char*)malloc( strlen(file) + 1); |
1a6944fd | 340 | |
7e616b10 RR |
341 | if( ! pobj->path ) |
342 | { | |
343 | free( pobj ); | |
344 | return 0; | |
345 | } | |
1a6944fd | 346 | |
7e616b10 | 347 | strcpy( pobj->path, file ); |
1a6944fd | 348 | |
7e616b10 RR |
349 | pobj->dev = st.st_dev; |
350 | pobj->ino = st.st_ino; | |
351 | pobj->refn = 1; | |
1a6944fd | 352 | |
7e616b10 | 353 | pobj->pentry = (int(*)())load(file, 0, 0); |
1a6944fd | 354 | |
7e616b10 RR |
355 | if( ! pobj->pentry ) |
356 | { | |
357 | free( pobj->path ); | |
358 | free( pobj ); | |
359 | return 0; | |
360 | } | |
1a6944fd | 361 | |
7e616b10 | 362 | init_htab(pobj->htab); |
1a6944fd | 363 | |
7e616b10 RR |
364 | pobj->next = obj_list; |
365 | obj_list = pobj; | |
1a6944fd | 366 | |
7e616b10 | 367 | return pobj; |
1a6944fd RR |
368 | } |
369 | ||
7e616b10 | 370 | int dlclose(void* hobj) |
1a6944fd | 371 | { |
7e616b10 RR |
372 | obj_t* pobj = (obj_t*)hobj; |
373 | obj_t* tpobj; | |
374 | int match = 0; | |
375 | ||
376 | if( ! hobj ) | |
377 | { | |
378 | errno = EINVAL; | |
379 | return -1; | |
380 | } | |
381 | ||
382 | errno = 0; | |
383 | errmsg = 0; | |
384 | ||
385 | if( pobj == obj_list ) | |
386 | { | |
387 | pobj->refn --; | |
388 | ||
389 | if( pobj->refn ) | |
390 | return 0; | |
391 | ||
392 | match = 1; | |
393 | obj_list = pobj->next; | |
394 | } | |
395 | ||
396 | for( tpobj = obj_list; !match && tpobj; tpobj = tpobj->next ) | |
397 | { | |
398 | if( tpobj->next == pobj ) | |
399 | { | |
400 | pobj->refn --; | |
401 | ||
402 | if( pobj->refn ) | |
403 | return 0; | |
404 | ||
405 | match = 1; | |
406 | tpobj->next = pobj->next; | |
407 | } | |
408 | } | |
409 | ||
410 | if(match) | |
411 | { | |
412 | unload((void*)(pobj->pentry)); | |
413 | clean_htab(pobj->htab); | |
414 | free(pobj->path); | |
415 | free(pobj); | |
416 | } | |
417 | ||
418 | return 0; | |
1a6944fd RR |
419 | } |
420 | ||
7e616b10 | 421 | char* dlerror() |
1a6944fd | 422 | { |
7e616b10 | 423 | extern char* sys_errlist[]; |
1a6944fd | 424 | |
7e616b10 RR |
425 | if( ! errmsg || ! errmsg[0] ) |
426 | { | |
427 | if( errno >= 0 ) | |
428 | return sys_errlist[errno]; | |
429 | ||
430 | return ""; | |
431 | } | |
1a6944fd | 432 | |
7e616b10 | 433 | return errmsg; |
1a6944fd RR |
434 | } |
435 | ||
7e616b10 | 436 | void* dlsym(void* hdl, char* sym) |
1a6944fd | 437 | { |
7e616b10 RR |
438 | nlist_t nl[3]; |
439 | obj_t* pobj = (obj_t*)hdl; | |
440 | slot_t* ent; | |
441 | int (*fp)(); | |
442 | long lbuf[3]; | |
443 | ||
444 | if( !hdl || !(pobj->htab) || !sym || ! *sym ) | |
445 | { | |
446 | errno = EINVAL; | |
447 | return 0; | |
448 | } | |
449 | ||
450 | errno = 0; | |
451 | errmsg = 0; | |
452 | ||
453 | ent = search( pobj->htab, sym ); | |
454 | ||
455 | if( ent ) | |
456 | return ent->fdesc; | |
457 | ||
458 | #define n_name _n._n_name | |
459 | ||
460 | nl[0].n_name = ENTRY_SYM; | |
461 | nl[1].n_name = sym; | |
462 | nl[2].n_name = 0; | |
463 | ||
464 | /* There is a potential problem here. If application | |
465 | * did not pass a full path name, and changed the | |
466 | * working directory after the load(), then nlist() | |
467 | * will be unable to open the original shared library | |
468 | * file to resolve the symbols. there are 3 ways to working | |
469 | * round this: 1. convert to full pathname in driver | |
470 | * manager. 2. applications always pass driver's full | |
471 | * path name. 3. if driver itself don't support | |
472 | * SQLGetFunctions(), call it with SQL_ALL_FUNCTIONS | |
473 | * as flag immidately after SQLConnect(), SQLDriverConnect() | |
474 | * and SQLBrowseConnect() to force the driver manager | |
475 | * resolving all will be used symbols. | |
476 | */ | |
477 | if( nlist( pobj->path, nl) == -1 ) | |
478 | return 0; | |
479 | ||
480 | if( ! nl[0].n_type && ! nl[0].n_value ) | |
481 | { | |
482 | errmsg = "can't locate module entry symbol"; | |
483 | return 0; | |
484 | } | |
485 | ||
486 | /* Note: On AIX 3.x if the object library is not | |
487 | * built with -g compiling option, .n_type field | |
488 | * is always 0. While on 4.x it will be 32. | |
489 | * On AIX 4.x, if the symbol is a entry point, | |
490 | * n_value will be 0. However, one thing is for sure | |
491 | * that if a symbol is not existance in the file, | |
492 | * both .n_type and .n_value would be 0. | |
493 | */ | |
494 | ||
495 | if( ! nl[1].n_type && ! nl[1].n_value ) | |
496 | { | |
497 | errmsg = "symbol not existance in this module"; | |
498 | return 0; | |
499 | } | |
500 | ||
501 | ent = slot_alloc(sym); | |
502 | ||
503 | if( ! ent ) | |
504 | return 0; | |
505 | ||
506 | /* catch it with a slot in the hashing table */ | |
507 | insert(pobj->htab, ent); | |
508 | ||
509 | memcpy(ent->fdesc, pobj->pentry, sizeof(ent->fdesc)); | |
510 | ||
511 | /* now ent->fdesc[0] is the virtual address of entry point | |
512 | * and ent->fdesc[1] is the TOC of the module | |
513 | */ | |
514 | ||
515 | /* let's calculate the virtual address of the symbol | |
516 | * by adding a relative offset getting from the module | |
517 | * file symbol table, i.e | |
518 | * | |
519 | * functin virtual address = entry point virtual address + | |
520 | * + ( function offset in file - entry point offset in file ) | |
521 | */ | |
522 | ||
523 | (ent->fdesc)[0] = (ent->fdesc)[0] + | |
524 | ( nl[1].n_value - nl[0].n_value ); | |
525 | ||
526 | /* return the function descriptor */ | |
527 | return ent->fdesc; | |
1a6944fd RR |
528 | } |
529 | ||
7e616b10 | 530 | #endif /* end of IBM AIX Section */ |
1a6944fd RR |
531 | |
532 | ||
7e616b10 | 533 | /********************************* |
1a6944fd | 534 | * |
7e616b10 | 535 | * Windows 3.x, 95, NT |
1a6944fd RR |
536 | * |
537 | *********************************/ | |
7e616b10 RR |
538 | #ifdef DLDAPI_WINDOWS |
539 | # define DLDAPI_DEFINED | |
540 | # include <windows.h> | |
1a6944fd | 541 | |
7e616b10 | 542 | void FAR* dlopen(char FAR* dll, int mode) |
1a6944fd | 543 | { |
7e616b10 | 544 | HINSTANCE hint; |
1a6944fd | 545 | |
7e616b10 RR |
546 | if( dll == NULL ) |
547 | { | |
548 | return GetWindowWord( NULL, GWW_HINSTANCE ); | |
549 | } | |
1a6944fd | 550 | |
7e616b10 | 551 | hint = LoadLibrary(dll); |
1a6944fd | 552 | |
7e616b10 RR |
553 | if( hint < HINSTANCE_ERROR ) |
554 | { | |
555 | return NULL; | |
556 | } | |
1a6944fd | 557 | |
7e616b10 | 558 | return (void FAR*)hint; |
1a6944fd RR |
559 | } |
560 | ||
7e616b10 | 561 | void FAR* dlsym( void FAR* hdll, char FAR* sym ) |
1a6944fd | 562 | { |
7e616b10 | 563 | return (void FAR*)GetProcAddress(hdll, sym); |
1a6944fd RR |
564 | } |
565 | ||
7e616b10 | 566 | char FAR* dlerror() |
1a6944fd | 567 | { |
7e616b10 | 568 | return 0L; /* unimplemented yet */ |
1a6944fd RR |
569 | } |
570 | ||
7e616b10 | 571 | int dlclose(void FAR* hdll) |
1a6944fd | 572 | { |
7e616b10 | 573 | FreeLibrary((HINSTANCE)hdll); |
1a6944fd RR |
574 | } |
575 | ||
7e616b10 | 576 | #endif /* end of Windows family */ |
1a6944fd | 577 | |
7e616b10 | 578 | /********************************* |
1a6944fd | 579 | * |
7e616b10 | 580 | * OS/2 2.x, 3.x |
1a6944fd | 581 | * |
7e616b10 | 582 | *********************************/ |
1a6944fd | 583 | #ifdef DLDAPI_OS2 |
7e616b10 | 584 | # define DLDAPI_DEFINED |
1a6944fd | 585 | /* |
7e616b10 | 586 | * DosLoadModule(), DosQueryProcAddress(), DosFreeModule(), ... |
1a6944fd | 587 | */ |
7e616b10 RR |
588 | |
589 | void FAR* dlopen(char FAR* dll, int mode) | |
590 | { | |
591 | APIRET rc = NO_ERROR; /* API return code */ | |
592 | UCHAR LoadError[256] = ""; /* Area for Load fail. info */ | |
593 | HMODULE ModuleHandle = NULLHANDLE; /* Module handle */ | |
594 | ||
595 | if( dll == NULL || '\0' == *dll ) | |
596 | { | |
597 | return NULL; | |
598 | } | |
599 | ||
600 | rc = NO_ERROR; | |
601 | rc = DosLoadModule( LoadError, /* Failure info buffer */ | |
602 | sizeof(LoadError), /* Size of buffer */ | |
603 | dll, /* Module to load */ | |
604 | &ModuleHandle ); /* Module handle returned */ | |
605 | if (rc != NO_ERROR) | |
606 | { | |
607 | #ifdef DEBUG | |
608 | fprintf( stderr, | |
609 | "[dlf.c] dlopen: DosLoadModule(0x%08lX, %d, \"%s\", 0x%08lX) = %d\n", | |
610 | &LoadError, sizeof(LoadError), dll, &ModuleHandle, rc | |
611 | ); | |
612 | fprintf( stderr, | |
613 | " ---> missing module '%s'\n", | |
614 | LoadError ); | |
1a6944fd | 615 | #endif |
7e616b10 RR |
616 | return NULL; |
617 | } | |
1a6944fd | 618 | |
7e616b10 RR |
619 | return (void FAR*) ModuleHandle; |
620 | ||
621 | } | |
622 | ||
623 | void FAR* dlsym( void FAR* hdll, char FAR* sym ) | |
624 | { | |
625 | APIRET rc = NO_ERROR; /* API return code */ | |
626 | PFN ModuleAddress = NULL; /* Module address */ | |
627 | ||
628 | rc = DosQueryProcAddr( (HMODULE) hdll, 0, sym, &ModuleAddress ); | |
629 | ||
630 | return (void FAR*) (NO_ERROR == rc) ? ModuleAddress | |
631 | : NULL; | |
632 | } | |
633 | ||
634 | char FAR* dlerror() | |
635 | { | |
636 | return 0L; /* unimplemented yet */ | |
637 | } | |
638 | ||
639 | int dlclose(void FAR* hdll) | |
640 | { | |
641 | return DosFreeModule( (HMODULE) hdll ); | |
642 | } | |
643 | ||
644 | #endif | |
645 | ||
646 | /*********************************** | |
647 | * | |
648 | * other platforms | |
649 | * | |
650 | ***********************************/ | |
651 | #ifdef DLDAPI_MAC | |
652 | # define DLDAPI_DEFINED | |
1a6944fd RR |
653 | #endif |
654 | ||
655 | #ifdef DLDAPI_NEXT | |
7e616b10 | 656 | # define DLDAPI_DEFINED |
1a6944fd RR |
657 | #endif |
658 | ||
659 | #ifndef DLDAPI_DEFINED | |
7e616b10 | 660 | # error "dynamic load editor undefined" |
1a6944fd | 661 | #endif |