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