OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
dso_win32.c
Go to the documentation of this file.
1 /* dso_win32.c -*- mode:C; c-file-style: "eay" -*- */
2 /* Written by Geoff Thorpe ([email protected]) 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
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  * ([email protected]). This product includes software written by Tim
55  * Hudson ([email protected]).
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)
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 
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  {
175  goto err;
176  }
177  h = LoadLibraryA(filename);
178  if(h == NULL)
179  {
181  ERR_add_error_data(3, "filename(", filename, ")");
182  goto err;
183  }
184  p = (HINSTANCE *)OPENSSL_malloc(sizeof(HINSTANCE));
185  if(p == NULL)
186  {
188  goto err;
189  }
190  *p = h;
191  if(!sk_void_push(dso->meth_data, p))
192  {
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  {
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  {
224  return(0);
225  }
226  if(!FreeLibrary(*p))
227  {
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  {
249  return(NULL);
250  }
251  if(sk_void_num(dso->meth_data) < 1)
252  {
254  return(NULL);
255  }
256  ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
257  if(ptr == NULL)
258  {
260  return(NULL);
261  }
262  sym = GetProcAddress(*ptr, symname);
263  if(sym == NULL)
264  {
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  {
280  return(NULL);
281  }
282  if(sk_void_num(dso->meth_data) < 1)
283  {
285  return(NULL);
286  }
287  ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
288  if(ptr == NULL)
289  {
291  return(NULL);
292  }
293  sym = GetProcAddress(*ptr, symname);
294  if(sym == NULL)
295  {
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  {
323  /*goto err;*/
324  return(NULL);
325  }
326 
327  result = OPENSSL_malloc(sizeof(struct file_st));
328  if(result == NULL)
329  {
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  {
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  {
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  {
471  return(NULL);
472  }
473 
474  result = OPENSSL_malloc(len + 1);
475  if (!result)
476  {
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  {
556  return(NULL);
557  }
558  if (!filespec2)
559  {
560  merged = OPENSSL_malloc(strlen(filespec1) + 1);
561  if(!merged)
562  {
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  {
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  {
587  return(NULL);
588  }
589  filespec2_split = win32_splitter(dso, filespec2, 1);
590  if (!filespec2_split)
591  {
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  {
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  {
705  return -1;
706  }
707 
708  create_snap = (CREATETOOLHELP32SNAPSHOT)
709  GetProcAddress(dll,"CreateToolhelp32Snapshot");
710  if (create_snap == NULL)
711  {
712  FreeLibrary(dll);
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);
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);
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  {
793  return NULL;
794  }
795 
796  create_snap = (CREATETOOLHELP32SNAPSHOT)
797  GetProcAddress(dll,"CreateToolhelp32Snapshot");
798  if (create_snap == NULL)
799  {
800  FreeLibrary(dll);
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);
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 */