1/* dso_win32.c */ 2/* 3 * Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project 4 * 2000. 5 */ 6/* ==================================================================== 7 * Copyright (c) 2000 The OpenSSL Project. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. All advertising materials mentioning features or use of this 22 * software must display the following acknowledgment: 23 * "This product includes software developed by the OpenSSL Project 24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25 * 26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27 * endorse or promote products derived from this software without 28 * prior written permission. For written permission, please contact 29 * licensing@OpenSSL.org. 30 * 31 * 5. Products derived from this software may not be called "OpenSSL" 32 * nor may "OpenSSL" appear in their names without prior written 33 * permission of the OpenSSL Project. 34 * 35 * 6. Redistributions of any form whatsoever must retain the following 36 * acknowledgment: 37 * "This product includes software developed by the OpenSSL Project 38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51 * OF THE POSSIBILITY OF SUCH DAMAGE. 52 * ==================================================================== 53 * 54 * This product includes cryptographic software written by Eric Young 55 * (eay@cryptsoft.com). This product includes software written by Tim 56 * Hudson (tjh@cryptsoft.com). 57 * 58 */ 59 60#include <stdio.h> 61#include <string.h> 62#include "cryptlib.h" 63#include <openssl/dso.h> 64 65#if !defined(DSO_WIN32) 66DSO_METHOD *DSO_METHOD_win32(void) 67{ 68 return NULL; 69} 70#else 71 72# ifdef _WIN32_WCE 73# if _WIN32_WCE < 300 74static FARPROC GetProcAddressA(HMODULE hModule, LPCSTR lpProcName) 75{ 76 WCHAR lpProcNameW[64]; 77 int i; 78 79 for (i = 0; lpProcName[i] && i < 64; i++) 80 lpProcNameW[i] = (WCHAR)lpProcName[i]; 81 if (i == 64) 82 return NULL; 83 lpProcNameW[i] = 0; 84 85 return GetProcAddressW(hModule, lpProcNameW); 86} 87# endif 88# undef GetProcAddress 89# define GetProcAddress GetProcAddressA 90 91static HINSTANCE LoadLibraryA(LPCSTR lpLibFileName) 92{ 93 WCHAR *fnamw; 94 size_t len_0 = strlen(lpLibFileName) + 1, i; 95 96# ifdef _MSC_VER 97 fnamw = (WCHAR *)_alloca(len_0 * sizeof(WCHAR)); 98# else 99 fnamw = (WCHAR *)alloca(len_0 * sizeof(WCHAR)); 100# endif 101 if (fnamw == NULL) { 102 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 103 return NULL; 104 } 105# if defined(_WIN32_WCE) && _WIN32_WCE>=101 106 if (!MultiByteToWideChar(CP_ACP, 0, lpLibFileName, len_0, fnamw, len_0)) 107# endif 108 for (i = 0; i < len_0; i++) 109 fnamw[i] = (WCHAR)lpLibFileName[i]; 110 111 return LoadLibraryW(fnamw); 112} 113# endif 114 115/* Part of the hack in "win32_load" ... */ 116# define DSO_MAX_TRANSLATED_SIZE 256 117 118static int win32_load(DSO *dso); 119static int win32_unload(DSO *dso); 120static void *win32_bind_var(DSO *dso, const char *symname); 121static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname); 122# if 0 123static int win32_unbind_var(DSO *dso, char *symname, void *symptr); 124static int win32_unbind_func(DSO *dso, char *symname, DSO_FUNC_TYPE symptr); 125static int win32_init(DSO *dso); 126static int win32_finish(DSO *dso); 127static long win32_ctrl(DSO *dso, int cmd, long larg, void *parg); 128# endif 129static char *win32_name_converter(DSO *dso, const char *filename); 130static char *win32_merger(DSO *dso, const char *filespec1, 131 const char *filespec2); 132static int win32_pathbyaddr(void *addr, char *path, int sz); 133static void *win32_globallookup(const char *name); 134 135static const char *openssl_strnchr(const char *string, int c, size_t len); 136 137static DSO_METHOD dso_meth_win32 = { 138 "OpenSSL 'win32' shared library method", 139 win32_load, 140 win32_unload, 141 win32_bind_var, 142 win32_bind_func, 143/* For now, "unbind" doesn't exist */ 144# if 0 145 NULL, /* unbind_var */ 146 NULL, /* unbind_func */ 147# endif 148 NULL, /* ctrl */ 149 win32_name_converter, 150 win32_merger, 151 NULL, /* init */ 152 NULL, /* finish */ 153 win32_pathbyaddr, 154 win32_globallookup 155}; 156 157DSO_METHOD *DSO_METHOD_win32(void) 158{ 159 return (&dso_meth_win32); 160} 161 162/* 163 * For this DSO_METHOD, our meth_data STACK will contain; (i) a pointer to 164 * the handle (HINSTANCE) returned from LoadLibrary(), and copied. 165 */ 166 167static int win32_load(DSO *dso) 168{ 169 HINSTANCE h = NULL, *p = NULL; 170 /* See applicable comments from dso_dl.c */ 171 char *filename = DSO_convert_filename(dso, NULL); 172 173 if (filename == NULL) { 174 DSOerr(DSO_F_WIN32_LOAD, DSO_R_NO_FILENAME); 175 goto err; 176 } 177 h = LoadLibraryA(filename); 178 if (h == NULL) { 179 DSOerr(DSO_F_WIN32_LOAD, DSO_R_LOAD_FAILED); 180 ERR_add_error_data(3, "filename(", filename, ")"); 181 goto err; 182 } 183 p = (HINSTANCE *) OPENSSL_malloc(sizeof(HINSTANCE)); 184 if (p == NULL) { 185 DSOerr(DSO_F_WIN32_LOAD, ERR_R_MALLOC_FAILURE); 186 goto err; 187 } 188 *p = h; 189 if (!sk_void_push(dso->meth_data, p)) { 190 DSOerr(DSO_F_WIN32_LOAD, DSO_R_STACK_ERROR); 191 goto err; 192 } 193 /* Success */ 194 dso->loaded_filename = filename; 195 return (1); 196 err: 197 /* Cleanup ! */ 198 if (filename != NULL) 199 OPENSSL_free(filename); 200 if (p != NULL) 201 OPENSSL_free(p); 202 if (h != NULL) 203 FreeLibrary(h); 204 return (0); 205} 206 207static int win32_unload(DSO *dso) 208{ 209 HINSTANCE *p; 210 if (dso == NULL) { 211 DSOerr(DSO_F_WIN32_UNLOAD, ERR_R_PASSED_NULL_PARAMETER); 212 return (0); 213 } 214 if (sk_void_num(dso->meth_data) < 1) 215 return (1); 216 p = sk_void_pop(dso->meth_data); 217 if (p == NULL) { 218 DSOerr(DSO_F_WIN32_UNLOAD, DSO_R_NULL_HANDLE); 219 return (0); 220 } 221 if (!FreeLibrary(*p)) { 222 DSOerr(DSO_F_WIN32_UNLOAD, DSO_R_UNLOAD_FAILED); 223 /* 224 * We should push the value back onto the stack in case of a retry. 225 */ 226 sk_void_push(dso->meth_data, p); 227 return (0); 228 } 229 /* Cleanup */ 230 OPENSSL_free(p); 231 return (1); 232} 233 234/* 235 * Using GetProcAddress for variables? TODO: Check this out in the Win32 API 236 * docs, there's probably a variant for variables. 237 */ 238static void *win32_bind_var(DSO *dso, const char *symname) 239{ 240 HINSTANCE *ptr; 241 void *sym; 242 243 if ((dso == NULL) || (symname == NULL)) { 244 DSOerr(DSO_F_WIN32_BIND_VAR, ERR_R_PASSED_NULL_PARAMETER); 245 return (NULL); 246 } 247 if (sk_void_num(dso->meth_data) < 1) { 248 DSOerr(DSO_F_WIN32_BIND_VAR, DSO_R_STACK_ERROR); 249 return (NULL); 250 } 251 ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1); 252 if (ptr == NULL) { 253 DSOerr(DSO_F_WIN32_BIND_VAR, DSO_R_NULL_HANDLE); 254 return (NULL); 255 } 256 sym = GetProcAddress(*ptr, symname); 257 if (sym == NULL) { 258 DSOerr(DSO_F_WIN32_BIND_VAR, DSO_R_SYM_FAILURE); 259 ERR_add_error_data(3, "symname(", symname, ")"); 260 return (NULL); 261 } 262 return (sym); 263} 264 265static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname) 266{ 267 HINSTANCE *ptr; 268 void *sym; 269 270 if ((dso == NULL) || (symname == NULL)) { 271 DSOerr(DSO_F_WIN32_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER); 272 return (NULL); 273 } 274 if (sk_void_num(dso->meth_data) < 1) { 275 DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_STACK_ERROR); 276 return (NULL); 277 } 278 ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1); 279 if (ptr == NULL) { 280 DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_NULL_HANDLE); 281 return (NULL); 282 } 283 sym = GetProcAddress(*ptr, symname); 284 if (sym == NULL) { 285 DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_SYM_FAILURE); 286 ERR_add_error_data(3, "symname(", symname, ")"); 287 return (NULL); 288 } 289 return ((DSO_FUNC_TYPE)sym); 290} 291 292struct file_st { 293 const char *node; 294 int nodelen; 295 const char *device; 296 int devicelen; 297 const char *predir; 298 int predirlen; 299 const char *dir; 300 int dirlen; 301 const char *file; 302 int filelen; 303}; 304 305static struct file_st *win32_splitter(DSO *dso, const char *filename, 306 int assume_last_is_dir) 307{ 308 struct file_st *result = NULL; 309 enum { IN_NODE, IN_DEVICE, IN_FILE } position; 310 const char *start = filename; 311 char last; 312 313 if (!filename) { 314 DSOerr(DSO_F_WIN32_SPLITTER, DSO_R_NO_FILENAME); 315 /* 316 * goto err; 317 */ 318 return (NULL); 319 } 320 321 result = OPENSSL_malloc(sizeof(struct file_st)); 322 if (result == NULL) { 323 DSOerr(DSO_F_WIN32_SPLITTER, ERR_R_MALLOC_FAILURE); 324 return (NULL); 325 } 326 327 memset(result, 0, sizeof(struct file_st)); 328 position = IN_DEVICE; 329 330 if ((filename[0] == '\\' && filename[1] == '\\') 331 || (filename[0] == '/' && filename[1] == '/')) { 332 position = IN_NODE; 333 filename += 2; 334 start = filename; 335 result->node = start; 336 } 337 338 do { 339 last = filename[0]; 340 switch (last) { 341 case ':': 342 if (position != IN_DEVICE) { 343 DSOerr(DSO_F_WIN32_SPLITTER, DSO_R_INCORRECT_FILE_SYNTAX); 344 /* 345 * goto err; 346 */ 347 OPENSSL_free(result); 348 return (NULL); 349 } 350 result->device = start; 351 result->devicelen = (int)(filename - start); 352 position = IN_FILE; 353 start = ++filename; 354 result->dir = start; 355 break; 356 case '\\': 357 case '/': 358 if (position == IN_NODE) { 359 result->nodelen = (int)(filename - start); 360 position = IN_FILE; 361 start = ++filename; 362 result->dir = start; 363 } else if (position == IN_DEVICE) { 364 position = IN_FILE; 365 filename++; 366 result->dir = start; 367 result->dirlen = (int)(filename - start); 368 start = filename; 369 } else { 370 filename++; 371 result->dirlen += (int)(filename - start); 372 start = filename; 373 } 374 break; 375 case '\0': 376 if (position == IN_NODE) { 377 result->nodelen = (int)(filename - start); 378 } else { 379 if (filename - start > 0) { 380 if (assume_last_is_dir) { 381 if (position == IN_DEVICE) { 382 result->dir = start; 383 result->dirlen = 0; 384 } 385 result->dirlen += (int)(filename - start); 386 } else { 387 result->file = start; 388 result->filelen = (int)(filename - start); 389 } 390 } 391 } 392 break; 393 default: 394 filename++; 395 break; 396 } 397 } 398 while (last); 399 400 if (!result->nodelen) 401 result->node = NULL; 402 if (!result->devicelen) 403 result->device = NULL; 404 if (!result->dirlen) 405 result->dir = NULL; 406 if (!result->filelen) 407 result->file = NULL; 408 409 return (result); 410} 411 412static char *win32_joiner(DSO *dso, const struct file_st *file_split) 413{ 414 int len = 0, offset = 0; 415 char *result = NULL; 416 const char *start; 417 418 if (!file_split) { 419 DSOerr(DSO_F_WIN32_JOINER, ERR_R_PASSED_NULL_PARAMETER); 420 return (NULL); 421 } 422 if (file_split->node) { 423 len += 2 + file_split->nodelen; /* 2 for starting \\ */ 424 if (file_split->predir || file_split->dir || file_split->file) 425 len++; /* 1 for ending \ */ 426 } else if (file_split->device) { 427 len += file_split->devicelen + 1; /* 1 for ending : */ 428 } 429 len += file_split->predirlen; 430 if (file_split->predir && (file_split->dir || file_split->file)) { 431 len++; /* 1 for ending \ */ 432 } 433 len += file_split->dirlen; 434 if (file_split->dir && file_split->file) { 435 len++; /* 1 for ending \ */ 436 } 437 len += file_split->filelen; 438 439 if (!len) { 440 DSOerr(DSO_F_WIN32_JOINER, DSO_R_EMPTY_FILE_STRUCTURE); 441 return (NULL); 442 } 443 444 result = OPENSSL_malloc(len + 1); 445 if (!result) { 446 DSOerr(DSO_F_WIN32_JOINER, ERR_R_MALLOC_FAILURE); 447 return (NULL); 448 } 449 450 if (file_split->node) { 451 strcpy(&result[offset], "\\\\"); 452 offset += 2; 453 strncpy(&result[offset], file_split->node, file_split->nodelen); 454 offset += file_split->nodelen; 455 if (file_split->predir || file_split->dir || file_split->file) { 456 result[offset] = '\\'; 457 offset++; 458 } 459 } else if (file_split->device) { 460 strncpy(&result[offset], file_split->device, file_split->devicelen); 461 offset += file_split->devicelen; 462 result[offset] = ':'; 463 offset++; 464 } 465 start = file_split->predir; 466 while (file_split->predirlen > (start - file_split->predir)) { 467 const char *end = openssl_strnchr(start, '/', 468 file_split->predirlen - (start - 469 file_split->predir)); 470 if (!end) 471 end = start 472 + file_split->predirlen - (start - file_split->predir); 473 strncpy(&result[offset], start, end - start); 474 offset += (int)(end - start); 475 result[offset] = '\\'; 476 offset++; 477 start = end + 1; 478 } 479# if 0 /* Not needed, since the directory converter 480 * above already appeneded a backslash */ 481 if (file_split->predir && (file_split->dir || file_split->file)) { 482 result[offset] = '\\'; 483 offset++; 484 } 485# endif 486 start = file_split->dir; 487 while (file_split->dirlen > (start - file_split->dir)) { 488 const char *end = openssl_strnchr(start, '/', 489 file_split->dirlen - (start - 490 file_split->dir)); 491 if (!end) 492 end = start + file_split->dirlen - (start - file_split->dir); 493 strncpy(&result[offset], start, end - start); 494 offset += (int)(end - start); 495 result[offset] = '\\'; 496 offset++; 497 start = end + 1; 498 } 499# if 0 /* Not needed, since the directory converter 500 * above already appeneded a backslash */ 501 if (file_split->dir && file_split->file) { 502 result[offset] = '\\'; 503 offset++; 504 } 505# endif 506 strncpy(&result[offset], file_split->file, file_split->filelen); 507 offset += file_split->filelen; 508 result[offset] = '\0'; 509 return (result); 510} 511 512static char *win32_merger(DSO *dso, const char *filespec1, 513 const char *filespec2) 514{ 515 char *merged = NULL; 516 struct file_st *filespec1_split = NULL; 517 struct file_st *filespec2_split = NULL; 518 519 if (!filespec1 && !filespec2) { 520 DSOerr(DSO_F_WIN32_MERGER, ERR_R_PASSED_NULL_PARAMETER); 521 return (NULL); 522 } 523 if (!filespec2) { 524 merged = OPENSSL_malloc(strlen(filespec1) + 1); 525 if (!merged) { 526 DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE); 527 return (NULL); 528 } 529 strcpy(merged, filespec1); 530 } else if (!filespec1) { 531 merged = OPENSSL_malloc(strlen(filespec2) + 1); 532 if (!merged) { 533 DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE); 534 return (NULL); 535 } 536 strcpy(merged, filespec2); 537 } else { 538 filespec1_split = win32_splitter(dso, filespec1, 0); 539 if (!filespec1_split) { 540 DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE); 541 return (NULL); 542 } 543 filespec2_split = win32_splitter(dso, filespec2, 1); 544 if (!filespec2_split) { 545 DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE); 546 OPENSSL_free(filespec1_split); 547 return (NULL); 548 } 549 550 /* Fill in into filespec1_split */ 551 if (!filespec1_split->node && !filespec1_split->device) { 552 filespec1_split->node = filespec2_split->node; 553 filespec1_split->nodelen = filespec2_split->nodelen; 554 filespec1_split->device = filespec2_split->device; 555 filespec1_split->devicelen = filespec2_split->devicelen; 556 } 557 if (!filespec1_split->dir) { 558 filespec1_split->dir = filespec2_split->dir; 559 filespec1_split->dirlen = filespec2_split->dirlen; 560 } else if (filespec1_split->dir[0] != '\\' 561 && filespec1_split->dir[0] != '/') { 562 filespec1_split->predir = filespec2_split->dir; 563 filespec1_split->predirlen = filespec2_split->dirlen; 564 } 565 if (!filespec1_split->file) { 566 filespec1_split->file = filespec2_split->file; 567 filespec1_split->filelen = filespec2_split->filelen; 568 } 569 570 merged = win32_joiner(dso, filespec1_split); 571 } 572 OPENSSL_free(filespec1_split); 573 OPENSSL_free(filespec2_split); 574 return (merged); 575} 576 577static char *win32_name_converter(DSO *dso, const char *filename) 578{ 579 char *translated; 580 int len, transform; 581 582 len = strlen(filename); 583 transform = ((strstr(filename, "/") == NULL) && 584 (strstr(filename, "\\") == NULL) && 585 (strstr(filename, ":") == NULL)); 586 if (transform) 587 /* We will convert this to "%s.dll" */ 588 translated = OPENSSL_malloc(len + 5); 589 else 590 /* We will simply duplicate filename */ 591 translated = OPENSSL_malloc(len + 1); 592 if (translated == NULL) { 593 DSOerr(DSO_F_WIN32_NAME_CONVERTER, DSO_R_NAME_TRANSLATION_FAILED); 594 return (NULL); 595 } 596 if (transform) 597 sprintf(translated, "%s.dll", filename); 598 else 599 sprintf(translated, "%s", filename); 600 return (translated); 601} 602 603static const char *openssl_strnchr(const char *string, int c, size_t len) 604{ 605 size_t i; 606 const char *p; 607 for (i = 0, p = string; i < len && *p; i++, p++) { 608 if (*p == c) 609 return p; 610 } 611 return NULL; 612} 613 614# include <tlhelp32.h> 615# ifdef _WIN32_WCE 616# define DLLNAME "TOOLHELP.DLL" 617# else 618# ifdef MODULEENTRY32 619# undef MODULEENTRY32 /* unmask the ASCII version! */ 620# endif 621# define DLLNAME "KERNEL32.DLL" 622# endif 623 624typedef HANDLE(WINAPI *CREATETOOLHELP32SNAPSHOT) (DWORD, DWORD); 625typedef BOOL(WINAPI *CLOSETOOLHELP32SNAPSHOT) (HANDLE); 626typedef BOOL(WINAPI *MODULE32) (HANDLE, MODULEENTRY32 *); 627 628static int win32_pathbyaddr(void *addr, char *path, int sz) 629{ 630 HMODULE dll; 631 HANDLE hModuleSnap = INVALID_HANDLE_VALUE; 632 MODULEENTRY32 me32; 633 CREATETOOLHELP32SNAPSHOT create_snap; 634 CLOSETOOLHELP32SNAPSHOT close_snap; 635 MODULE32 module_first, module_next; 636 637 if (addr == NULL) { 638 union { 639 int (*f) (void *, char *, int); 640 void *p; 641 } t = { 642 win32_pathbyaddr 643 }; 644 addr = t.p; 645 } 646 647 dll = LoadLibrary(TEXT(DLLNAME)); 648 if (dll == NULL) { 649 DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_UNSUPPORTED); 650 return -1; 651 } 652 653 create_snap = (CREATETOOLHELP32SNAPSHOT) 654 GetProcAddress(dll, "CreateToolhelp32Snapshot"); 655 if (create_snap == NULL) { 656 FreeLibrary(dll); 657 DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_UNSUPPORTED); 658 return -1; 659 } 660 /* We take the rest for granted... */ 661# ifdef _WIN32_WCE 662 close_snap = (CLOSETOOLHELP32SNAPSHOT) 663 GetProcAddress(dll, "CloseToolhelp32Snapshot"); 664# else 665 close_snap = (CLOSETOOLHELP32SNAPSHOT) CloseHandle; 666# endif 667 module_first = (MODULE32) GetProcAddress(dll, "Module32First"); 668 module_next = (MODULE32) GetProcAddress(dll, "Module32Next"); 669 670 hModuleSnap = (*create_snap) (TH32CS_SNAPMODULE, 0); 671 if (hModuleSnap == INVALID_HANDLE_VALUE) { 672 FreeLibrary(dll); 673 DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_UNSUPPORTED); 674 return -1; 675 } 676 677 me32.dwSize = sizeof(me32); 678 679 if (!(*module_first) (hModuleSnap, &me32)) { 680 (*close_snap) (hModuleSnap); 681 FreeLibrary(dll); 682 DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_FAILURE); 683 return -1; 684 } 685 686 do { 687 if ((BYTE *) addr >= me32.modBaseAddr && 688 (BYTE *) addr < me32.modBaseAddr + me32.modBaseSize) { 689 (*close_snap) (hModuleSnap); 690 FreeLibrary(dll); 691# ifdef _WIN32_WCE 692# if _WIN32_WCE >= 101 693 return WideCharToMultiByte(CP_ACP, 0, me32.szExePath, -1, 694 path, sz, NULL, NULL); 695# else 696 { 697 int i, len = (int)wcslen(me32.szExePath); 698 if (sz <= 0) 699 return len + 1; 700 if (len >= sz) 701 len = sz - 1; 702 for (i = 0; i < len; i++) 703 path[i] = (char)me32.szExePath[i]; 704 path[len++] = 0; 705 return len; 706 } 707# endif 708# else 709 { 710 int len = (int)strlen(me32.szExePath); 711 if (sz <= 0) 712 return len + 1; 713 if (len >= sz) 714 len = sz - 1; 715 memcpy(path, me32.szExePath, len); 716 path[len++] = 0; 717 return len; 718 } 719# endif 720 } 721 } while ((*module_next) (hModuleSnap, &me32)); 722 723 (*close_snap) (hModuleSnap); 724 FreeLibrary(dll); 725 return 0; 726} 727 728static void *win32_globallookup(const char *name) 729{ 730 HMODULE dll; 731 HANDLE hModuleSnap = INVALID_HANDLE_VALUE; 732 MODULEENTRY32 me32; 733 CREATETOOLHELP32SNAPSHOT create_snap; 734 CLOSETOOLHELP32SNAPSHOT close_snap; 735 MODULE32 module_first, module_next; 736 FARPROC ret = NULL; 737 738 dll = LoadLibrary(TEXT(DLLNAME)); 739 if (dll == NULL) { 740 DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED); 741 return NULL; 742 } 743 744 create_snap = (CREATETOOLHELP32SNAPSHOT) 745 GetProcAddress(dll, "CreateToolhelp32Snapshot"); 746 if (create_snap == NULL) { 747 FreeLibrary(dll); 748 DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED); 749 return NULL; 750 } 751 /* We take the rest for granted... */ 752# ifdef _WIN32_WCE 753 close_snap = (CLOSETOOLHELP32SNAPSHOT) 754 GetProcAddress(dll, "CloseToolhelp32Snapshot"); 755# else 756 close_snap = (CLOSETOOLHELP32SNAPSHOT) CloseHandle; 757# endif 758 module_first = (MODULE32) GetProcAddress(dll, "Module32First"); 759 module_next = (MODULE32) GetProcAddress(dll, "Module32Next"); 760 761 hModuleSnap = (*create_snap) (TH32CS_SNAPMODULE, 0); 762 if (hModuleSnap == INVALID_HANDLE_VALUE) { 763 FreeLibrary(dll); 764 DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED); 765 return NULL; 766 } 767 768 me32.dwSize = sizeof(me32); 769 770 if (!(*module_first) (hModuleSnap, &me32)) { 771 (*close_snap) (hModuleSnap); 772 FreeLibrary(dll); 773 return NULL; 774 } 775 776 do { 777 if ((ret = GetProcAddress(me32.hModule, name))) { 778 (*close_snap) (hModuleSnap); 779 FreeLibrary(dll); 780 return ret; 781 } 782 } while ((*module_next) (hModuleSnap, &me32)); 783 784 (*close_snap) (hModuleSnap); 785 FreeLibrary(dll); 786 return NULL; 787} 788#endif /* DSO_WIN32 */ 789