]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/dso/dso_win32.c
Identify and move common internal libcrypto header files
[thirdparty/openssl.git] / crypto / dso / dso_win32.c
CommitLineData
cbecb3ac 1/* dso_win32.c -*- mode:C; c-file-style: "eay" -*- */
0f113f3e
MC
2/*
3 * Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project
4 * 2000.
8f4fac7f
GT
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
0f113f3e 14 * notice, this list of conditions and the following disclaimer.
8f4fac7f
GT
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>
22a41547 61#include <string.h>
b39fc560 62#include "internal/cryptlib.h"
8f4fac7f
GT
63#include <openssl/dso.h>
64
16420007 65#if !defined(DSO_WIN32)
8f4fac7f 66DSO_METHOD *DSO_METHOD_win32(void)
0f113f3e
MC
67{
68 return NULL;
69}
8f4fac7f
GT
70#else
71
0f113f3e
MC
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
b37fb16d 90
19bd66fe 91static HINSTANCE LoadLibraryA(LPCSTR lpLibFileName)
0f113f3e
MC
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
83e68987 114
b9e63915 115/* Part of the hack in "win32_load" ... */
0f113f3e 116# define DSO_MAX_TRANSLATED_SIZE 256
b9e63915 117
51c8dc37 118static int win32_load(DSO *dso);
8f4fac7f 119static int win32_unload(DSO *dso);
e9a68cfb
GT
120static void *win32_bind_var(DSO *dso, const char *symname);
121static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname);
51c8dc37 122static char *win32_name_converter(DSO *dso, const char *filename);
cbecb3ac 123static char *win32_merger(DSO *dso, const char *filespec1,
0f113f3e
MC
124 const char *filespec2);
125static int win32_pathbyaddr(void *addr, char *path, int sz);
c6cb42e4 126static void *win32_globallookup(const char *name);
8f4fac7f 127
74e3931f
DSH
128static const char *openssl_strnchr(const char *string, int c, size_t len);
129
8f4fac7f 130static DSO_METHOD dso_meth_win32 = {
0f113f3e
MC
131 "OpenSSL 'win32' shared library method",
132 win32_load,
133 win32_unload,
134 win32_bind_var,
135 win32_bind_func,
0f113f3e
MC
136 NULL, /* ctrl */
137 win32_name_converter,
138 win32_merger,
139 NULL, /* init */
140 NULL, /* finish */
141 win32_pathbyaddr,
142 win32_globallookup
143};
8f4fac7f
GT
144
145DSO_METHOD *DSO_METHOD_win32(void)
0f113f3e
MC
146{
147 return (&dso_meth_win32);
148}
8f4fac7f 149
0f113f3e
MC
150/*
151 * For this DSO_METHOD, our meth_data STACK will contain; (i) a pointer to
152 * the handle (HINSTANCE) returned from LoadLibrary(), and copied.
8f4fac7f
GT
153 */
154
51c8dc37 155static int win32_load(DSO *dso)
0f113f3e
MC
156{
157 HINSTANCE h = NULL, *p = NULL;
158 /* See applicable comments from dso_dl.c */
159 char *filename = DSO_convert_filename(dso, NULL);
160
161 if (filename == NULL) {
162 DSOerr(DSO_F_WIN32_LOAD, DSO_R_NO_FILENAME);
163 goto err;
164 }
165 h = LoadLibraryA(filename);
166 if (h == NULL) {
167 DSOerr(DSO_F_WIN32_LOAD, DSO_R_LOAD_FAILED);
168 ERR_add_error_data(3, "filename(", filename, ")");
169 goto err;
170 }
b4faea50 171 p = OPENSSL_malloc(sizeof(*p));
0f113f3e
MC
172 if (p == NULL) {
173 DSOerr(DSO_F_WIN32_LOAD, ERR_R_MALLOC_FAILURE);
174 goto err;
175 }
176 *p = h;
177 if (!sk_void_push(dso->meth_data, p)) {
178 DSOerr(DSO_F_WIN32_LOAD, DSO_R_STACK_ERROR);
179 goto err;
180 }
181 /* Success */
182 dso->loaded_filename = filename;
183 return (1);
184 err:
185 /* Cleanup ! */
b548a1f1
RS
186 OPENSSL_free(filename);
187 OPENSSL_free(p);
0f113f3e
MC
188 if (h != NULL)
189 FreeLibrary(h);
190 return (0);
191}
8f4fac7f
GT
192
193static int win32_unload(DSO *dso)
0f113f3e
MC
194{
195 HINSTANCE *p;
196 if (dso == NULL) {
197 DSOerr(DSO_F_WIN32_UNLOAD, ERR_R_PASSED_NULL_PARAMETER);
198 return (0);
199 }
200 if (sk_void_num(dso->meth_data) < 1)
201 return (1);
202 p = sk_void_pop(dso->meth_data);
203 if (p == NULL) {
204 DSOerr(DSO_F_WIN32_UNLOAD, DSO_R_NULL_HANDLE);
205 return (0);
206 }
207 if (!FreeLibrary(*p)) {
208 DSOerr(DSO_F_WIN32_UNLOAD, DSO_R_UNLOAD_FAILED);
209 /*
210 * We should push the value back onto the stack in case of a retry.
211 */
212 sk_void_push(dso->meth_data, p);
213 return (0);
214 }
215 /* Cleanup */
216 OPENSSL_free(p);
217 return (1);
218}
219
220/*
221 * Using GetProcAddress for variables? TODO: Check this out in the Win32 API
222 * docs, there's probably a variant for variables.
223 */
e9a68cfb 224static void *win32_bind_var(DSO *dso, const char *symname)
0f113f3e
MC
225{
226 HINSTANCE *ptr;
227 void *sym;
228
229 if ((dso == NULL) || (symname == NULL)) {
230 DSOerr(DSO_F_WIN32_BIND_VAR, ERR_R_PASSED_NULL_PARAMETER);
231 return (NULL);
232 }
233 if (sk_void_num(dso->meth_data) < 1) {
234 DSOerr(DSO_F_WIN32_BIND_VAR, DSO_R_STACK_ERROR);
235 return (NULL);
236 }
237 ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
238 if (ptr == NULL) {
239 DSOerr(DSO_F_WIN32_BIND_VAR, DSO_R_NULL_HANDLE);
240 return (NULL);
241 }
242 sym = GetProcAddress(*ptr, symname);
243 if (sym == NULL) {
244 DSOerr(DSO_F_WIN32_BIND_VAR, DSO_R_SYM_FAILURE);
245 ERR_add_error_data(3, "symname(", symname, ")");
246 return (NULL);
247 }
248 return (sym);
249}
e9a68cfb
GT
250
251static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname)
0f113f3e
MC
252{
253 HINSTANCE *ptr;
254 void *sym;
255
256 if ((dso == NULL) || (symname == NULL)) {
257 DSOerr(DSO_F_WIN32_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);
258 return (NULL);
259 }
260 if (sk_void_num(dso->meth_data) < 1) {
261 DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_STACK_ERROR);
262 return (NULL);
263 }
264 ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
265 if (ptr == NULL) {
266 DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_NULL_HANDLE);
267 return (NULL);
268 }
269 sym = GetProcAddress(*ptr, symname);
270 if (sym == NULL) {
271 DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_SYM_FAILURE);
272 ERR_add_error_data(3, "symname(", symname, ")");
273 return (NULL);
274 }
275 return ((DSO_FUNC_TYPE)sym);
276}
277
278struct file_st {
279 const char *node;
280 int nodelen;
281 const char *device;
282 int devicelen;
283 const char *predir;
284 int predirlen;
285 const char *dir;
286 int dirlen;
287 const char *file;
288 int filelen;
289};
cbecb3ac
RL
290
291static struct file_st *win32_splitter(DSO *dso, const char *filename,
0f113f3e
MC
292 int assume_last_is_dir)
293{
294 struct file_st *result = NULL;
295 enum { IN_NODE, IN_DEVICE, IN_FILE } position;
296 const char *start = filename;
297 char last;
298
299 if (!filename) {
300 DSOerr(DSO_F_WIN32_SPLITTER, DSO_R_NO_FILENAME);
301 /*
302 * goto err;
303 */
304 return (NULL);
305 }
306
b4faea50 307 result = OPENSSL_malloc(sizeof(*result));
0f113f3e
MC
308 if (result == NULL) {
309 DSOerr(DSO_F_WIN32_SPLITTER, ERR_R_MALLOC_FAILURE);
310 return (NULL);
311 }
312
16f8d4eb 313 memset(result, 0, sizeof(*result));
0f113f3e
MC
314 position = IN_DEVICE;
315
316 if ((filename[0] == '\\' && filename[1] == '\\')
317 || (filename[0] == '/' && filename[1] == '/')) {
318 position = IN_NODE;
319 filename += 2;
320 start = filename;
321 result->node = start;
322 }
323
324 do {
325 last = filename[0];
326 switch (last) {
327 case ':':
328 if (position != IN_DEVICE) {
329 DSOerr(DSO_F_WIN32_SPLITTER, DSO_R_INCORRECT_FILE_SYNTAX);
330 /*
331 * goto err;
332 */
333 OPENSSL_free(result);
334 return (NULL);
335 }
336 result->device = start;
337 result->devicelen = (int)(filename - start);
338 position = IN_FILE;
339 start = ++filename;
340 result->dir = start;
341 break;
342 case '\\':
343 case '/':
344 if (position == IN_NODE) {
345 result->nodelen = (int)(filename - start);
346 position = IN_FILE;
347 start = ++filename;
348 result->dir = start;
349 } else if (position == IN_DEVICE) {
350 position = IN_FILE;
351 filename++;
352 result->dir = start;
353 result->dirlen = (int)(filename - start);
354 start = filename;
355 } else {
356 filename++;
357 result->dirlen += (int)(filename - start);
358 start = filename;
359 }
360 break;
361 case '\0':
362 if (position == IN_NODE) {
363 result->nodelen = (int)(filename - start);
364 } else {
365 if (filename - start > 0) {
366 if (assume_last_is_dir) {
367 if (position == IN_DEVICE) {
368 result->dir = start;
369 result->dirlen = 0;
370 }
371 result->dirlen += (int)(filename - start);
372 } else {
373 result->file = start;
374 result->filelen = (int)(filename - start);
375 }
376 }
377 }
378 break;
379 default:
380 filename++;
381 break;
382 }
383 }
384 while (last);
385
386 if (!result->nodelen)
387 result->node = NULL;
388 if (!result->devicelen)
389 result->device = NULL;
390 if (!result->dirlen)
391 result->dir = NULL;
392 if (!result->filelen)
393 result->file = NULL;
394
395 return (result);
396}
cbecb3ac 397
74e3931f 398static char *win32_joiner(DSO *dso, const struct file_st *file_split)
0f113f3e
MC
399{
400 int len = 0, offset = 0;
401 char *result = NULL;
402 const char *start;
403
404 if (!file_split) {
405 DSOerr(DSO_F_WIN32_JOINER, ERR_R_PASSED_NULL_PARAMETER);
406 return (NULL);
407 }
408 if (file_split->node) {
409 len += 2 + file_split->nodelen; /* 2 for starting \\ */
410 if (file_split->predir || file_split->dir || file_split->file)
411 len++; /* 1 for ending \ */
412 } else if (file_split->device) {
413 len += file_split->devicelen + 1; /* 1 for ending : */
414 }
415 len += file_split->predirlen;
416 if (file_split->predir && (file_split->dir || file_split->file)) {
417 len++; /* 1 for ending \ */
418 }
419 len += file_split->dirlen;
420 if (file_split->dir && file_split->file) {
421 len++; /* 1 for ending \ */
422 }
423 len += file_split->filelen;
424
425 if (!len) {
426 DSOerr(DSO_F_WIN32_JOINER, DSO_R_EMPTY_FILE_STRUCTURE);
427 return (NULL);
428 }
429
430 result = OPENSSL_malloc(len + 1);
431 if (!result) {
432 DSOerr(DSO_F_WIN32_JOINER, ERR_R_MALLOC_FAILURE);
433 return (NULL);
434 }
435
436 if (file_split->node) {
437 strcpy(&result[offset], "\\\\");
438 offset += 2;
439 strncpy(&result[offset], file_split->node, file_split->nodelen);
440 offset += file_split->nodelen;
441 if (file_split->predir || file_split->dir || file_split->file) {
442 result[offset] = '\\';
443 offset++;
444 }
445 } else if (file_split->device) {
446 strncpy(&result[offset], file_split->device, file_split->devicelen);
447 offset += file_split->devicelen;
448 result[offset] = ':';
449 offset++;
450 }
451 start = file_split->predir;
452 while (file_split->predirlen > (start - file_split->predir)) {
453 const char *end = openssl_strnchr(start, '/',
454 file_split->predirlen - (start -
455 file_split->predir));
456 if (!end)
457 end = start
458 + file_split->predirlen - (start - file_split->predir);
459 strncpy(&result[offset], start, end - start);
460 offset += (int)(end - start);
461 result[offset] = '\\';
462 offset++;
463 start = end + 1;
464 }
0f113f3e
MC
465 start = file_split->dir;
466 while (file_split->dirlen > (start - file_split->dir)) {
467 const char *end = openssl_strnchr(start, '/',
468 file_split->dirlen - (start -
469 file_split->dir));
470 if (!end)
471 end = start + file_split->dirlen - (start - file_split->dir);
472 strncpy(&result[offset], start, end - start);
473 offset += (int)(end - start);
474 result[offset] = '\\';
475 offset++;
476 start = end + 1;
477 }
0f113f3e
MC
478 strncpy(&result[offset], file_split->file, file_split->filelen);
479 offset += file_split->filelen;
480 result[offset] = '\0';
481 return (result);
482}
483
484static char *win32_merger(DSO *dso, const char *filespec1,
485 const char *filespec2)
486{
487 char *merged = NULL;
488 struct file_st *filespec1_split = NULL;
489 struct file_st *filespec2_split = NULL;
490
491 if (!filespec1 && !filespec2) {
492 DSOerr(DSO_F_WIN32_MERGER, ERR_R_PASSED_NULL_PARAMETER);
493 return (NULL);
494 }
495 if (!filespec2) {
496 merged = OPENSSL_malloc(strlen(filespec1) + 1);
497 if (!merged) {
498 DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE);
499 return (NULL);
500 }
501 strcpy(merged, filespec1);
502 } else if (!filespec1) {
503 merged = OPENSSL_malloc(strlen(filespec2) + 1);
504 if (!merged) {
505 DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE);
506 return (NULL);
507 }
508 strcpy(merged, filespec2);
509 } else {
510 filespec1_split = win32_splitter(dso, filespec1, 0);
511 if (!filespec1_split) {
512 DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE);
513 return (NULL);
514 }
515 filespec2_split = win32_splitter(dso, filespec2, 1);
516 if (!filespec2_split) {
517 DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE);
518 OPENSSL_free(filespec1_split);
519 return (NULL);
520 }
521
522 /* Fill in into filespec1_split */
523 if (!filespec1_split->node && !filespec1_split->device) {
524 filespec1_split->node = filespec2_split->node;
525 filespec1_split->nodelen = filespec2_split->nodelen;
526 filespec1_split->device = filespec2_split->device;
527 filespec1_split->devicelen = filespec2_split->devicelen;
528 }
529 if (!filespec1_split->dir) {
530 filespec1_split->dir = filespec2_split->dir;
531 filespec1_split->dirlen = filespec2_split->dirlen;
532 } else if (filespec1_split->dir[0] != '\\'
533 && filespec1_split->dir[0] != '/') {
534 filespec1_split->predir = filespec2_split->dir;
535 filespec1_split->predirlen = filespec2_split->dirlen;
536 }
537 if (!filespec1_split->file) {
538 filespec1_split->file = filespec2_split->file;
539 filespec1_split->filelen = filespec2_split->filelen;
540 }
541
542 merged = win32_joiner(dso, filespec1_split);
543 }
544 OPENSSL_free(filespec1_split);
545 OPENSSL_free(filespec2_split);
546 return (merged);
547}
cbecb3ac 548
51c8dc37 549static char *win32_name_converter(DSO *dso, const char *filename)
0f113f3e
MC
550{
551 char *translated;
552 int len, transform;
553
554 len = strlen(filename);
555 transform = ((strstr(filename, "/") == NULL) &&
556 (strstr(filename, "\\") == NULL) &&
557 (strstr(filename, ":") == NULL));
558 if (transform)
559 /* We will convert this to "%s.dll" */
560 translated = OPENSSL_malloc(len + 5);
561 else
562 /* We will simply duplicate filename */
563 translated = OPENSSL_malloc(len + 1);
564 if (translated == NULL) {
565 DSOerr(DSO_F_WIN32_NAME_CONVERTER, DSO_R_NAME_TRANSLATION_FAILED);
566 return (NULL);
567 }
568 if (transform)
569 sprintf(translated, "%s.dll", filename);
570 else
571 sprintf(translated, "%s", filename);
572 return (translated);
573}
51c8dc37 574
74e3931f 575static const char *openssl_strnchr(const char *string, int c, size_t len)
0f113f3e
MC
576{
577 size_t i;
578 const char *p;
579 for (i = 0, p = string; i < len && *p; i++, p++) {
580 if (*p == c)
581 return p;
582 }
583 return NULL;
584}
585
586# include <tlhelp32.h>
587# ifdef _WIN32_WCE
588# define DLLNAME "TOOLHELP.DLL"
589# else
590# ifdef MODULEENTRY32
591# undef MODULEENTRY32 /* unmask the ASCII version! */
592# endif
593# define DLLNAME "KERNEL32.DLL"
7ed87653 594# endif
0f113f3e
MC
595
596typedef HANDLE(WINAPI *CREATETOOLHELP32SNAPSHOT) (DWORD, DWORD);
597typedef BOOL(WINAPI *CLOSETOOLHELP32SNAPSHOT) (HANDLE);
598typedef BOOL(WINAPI *MODULE32) (HANDLE, MODULEENTRY32 *);
599
600static int win32_pathbyaddr(void *addr, char *path, int sz)
601{
602 HMODULE dll;
603 HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
604 MODULEENTRY32 me32;
605 CREATETOOLHELP32SNAPSHOT create_snap;
606 CLOSETOOLHELP32SNAPSHOT close_snap;
607 MODULE32 module_first, module_next;
608
609 if (addr == NULL) {
610 union {
611 int (*f) (void *, char *, int);
612 void *p;
613 } t = {
614 win32_pathbyaddr
615 };
616 addr = t.p;
617 }
618
619 dll = LoadLibrary(TEXT(DLLNAME));
620 if (dll == NULL) {
621 DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_UNSUPPORTED);
622 return -1;
623 }
624
625 create_snap = (CREATETOOLHELP32SNAPSHOT)
626 GetProcAddress(dll, "CreateToolhelp32Snapshot");
627 if (create_snap == NULL) {
628 FreeLibrary(dll);
629 DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_UNSUPPORTED);
630 return -1;
631 }
632 /* We take the rest for granted... */
633# ifdef _WIN32_WCE
634 close_snap = (CLOSETOOLHELP32SNAPSHOT)
635 GetProcAddress(dll, "CloseToolhelp32Snapshot");
7ed87653 636# else
0f113f3e 637 close_snap = (CLOSETOOLHELP32SNAPSHOT) CloseHandle;
7ed87653 638# endif
0f113f3e
MC
639 module_first = (MODULE32) GetProcAddress(dll, "Module32First");
640 module_next = (MODULE32) GetProcAddress(dll, "Module32Next");
641
642 hModuleSnap = (*create_snap) (TH32CS_SNAPMODULE, 0);
643 if (hModuleSnap == INVALID_HANDLE_VALUE) {
644 FreeLibrary(dll);
645 DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_UNSUPPORTED);
646 return -1;
647 }
648
649 me32.dwSize = sizeof(me32);
650
651 if (!(*module_first) (hModuleSnap, &me32)) {
652 (*close_snap) (hModuleSnap);
653 FreeLibrary(dll);
654 DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_FAILURE);
655 return -1;
656 }
657
658 do {
659 if ((BYTE *) addr >= me32.modBaseAddr &&
660 (BYTE *) addr < me32.modBaseAddr + me32.modBaseSize) {
661 (*close_snap) (hModuleSnap);
662 FreeLibrary(dll);
663# ifdef _WIN32_WCE
664# if _WIN32_WCE >= 101
665 return WideCharToMultiByte(CP_ACP, 0, me32.szExePath, -1,
666 path, sz, NULL, NULL);
667# else
668 {
669 int i, len = (int)wcslen(me32.szExePath);
670 if (sz <= 0)
671 return len + 1;
672 if (len >= sz)
673 len = sz - 1;
674 for (i = 0; i < len; i++)
675 path[i] = (char)me32.szExePath[i];
676 path[len++] = 0;
677 return len;
678 }
679# endif
680# else
681 {
682 int len = (int)strlen(me32.szExePath);
683 if (sz <= 0)
684 return len + 1;
685 if (len >= sz)
686 len = sz - 1;
687 memcpy(path, me32.szExePath, len);
688 path[len++] = 0;
689 return len;
690 }
691# endif
692 }
693 } while ((*module_next) (hModuleSnap, &me32));
694
695 (*close_snap) (hModuleSnap);
696 FreeLibrary(dll);
697 return 0;
698}
68b64fb6 699
c6cb42e4 700static void *win32_globallookup(const char *name)
0f113f3e
MC
701{
702 HMODULE dll;
703 HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
704 MODULEENTRY32 me32;
705 CREATETOOLHELP32SNAPSHOT create_snap;
706 CLOSETOOLHELP32SNAPSHOT close_snap;
707 MODULE32 module_first, module_next;
708 FARPROC ret = NULL;
709
710 dll = LoadLibrary(TEXT(DLLNAME));
711 if (dll == NULL) {
712 DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED);
713 return NULL;
714 }
715
716 create_snap = (CREATETOOLHELP32SNAPSHOT)
717 GetProcAddress(dll, "CreateToolhelp32Snapshot");
718 if (create_snap == NULL) {
719 FreeLibrary(dll);
720 DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED);
721 return NULL;
722 }
723 /* We take the rest for granted... */
724# ifdef _WIN32_WCE
725 close_snap = (CLOSETOOLHELP32SNAPSHOT)
726 GetProcAddress(dll, "CloseToolhelp32Snapshot");
727# else
728 close_snap = (CLOSETOOLHELP32SNAPSHOT) CloseHandle;
729# endif
730 module_first = (MODULE32) GetProcAddress(dll, "Module32First");
731 module_next = (MODULE32) GetProcAddress(dll, "Module32Next");
732
733 hModuleSnap = (*create_snap) (TH32CS_SNAPMODULE, 0);
734 if (hModuleSnap == INVALID_HANDLE_VALUE) {
735 FreeLibrary(dll);
736 DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED);
737 return NULL;
738 }
739
740 me32.dwSize = sizeof(me32);
741
742 if (!(*module_first) (hModuleSnap, &me32)) {
743 (*close_snap) (hModuleSnap);
744 FreeLibrary(dll);
745 return NULL;
746 }
747
748 do {
749 if ((ret = GetProcAddress(me32.hModule, name))) {
750 (*close_snap) (hModuleSnap);
751 FreeLibrary(dll);
752 return ret;
753 }
754 } while ((*module_next) (hModuleSnap, &me32));
755
756 (*close_snap) (hModuleSnap);
757 FreeLibrary(dll);
758 return NULL;
759}
760#endif /* DSO_WIN32 */