crypt32/tests: Fix some test failures on Win9x.
[wine] / dlls / dbghelp / module.c
1 /*
2  * File module.c - module handling for the wine debugger
3  *
4  * Copyright (C) 1993,      Eric Youngdale.
5  *               2000-2007, Eric Pouech
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <assert.h>
27
28 #include "dbghelp_private.h"
29 #include "psapi.h"
30 #include "winternl.h"
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
34
35 const WCHAR        S_ElfW[]         = {'<','e','l','f','>','\0'};
36 const WCHAR        S_WineLoaderW[]  = {'<','w','i','n','e','-','l','o','a','d','e','r','>','\0'};
37 static const WCHAR S_DotSoW[]       = {'.','s','o','\0'};
38 static const WCHAR S_DotPdbW[]      = {'.','p','d','b','\0'};
39 static const WCHAR S_DotDbgW[]      = {'.','d','b','g','\0'};
40 const WCHAR        S_WineW[]        = {'w','i','n','e',0};
41 const WCHAR        S_SlashW[]       = {'/','\0'};
42
43 static const WCHAR S_AcmW[] = {'.','a','c','m','\0'};
44 static const WCHAR S_DllW[] = {'.','d','l','l','\0'};
45 static const WCHAR S_DrvW[] = {'.','d','r','v','\0'};
46 static const WCHAR S_ExeW[] = {'.','e','x','e','\0'};
47 static const WCHAR S_OcxW[] = {'.','o','c','x','\0'};
48 static const WCHAR S_VxdW[] = {'.','v','x','d','\0'};
49 static const WCHAR * const ext[] = {S_AcmW, S_DllW, S_DrvW, S_ExeW, S_OcxW, S_VxdW, NULL};
50
51 static int match_ext(const WCHAR* ptr, size_t len)
52 {
53     const WCHAR* const *e;
54     size_t      l;
55
56     for (e = ext; *e; e++)
57     {
58         l = strlenW(*e);
59         if (l >= len) return FALSE;
60         if (strncmpiW(&ptr[len - l], *e, l)) continue;
61         return l;
62     }
63     return 0;
64 }
65
66 static const WCHAR* get_filename(const WCHAR* name, const WCHAR* endptr)
67 {
68     const WCHAR*        ptr;
69
70     if (!endptr) endptr = name + strlenW(name);
71     for (ptr = endptr - 1; ptr >= name; ptr--)
72     {
73         if (*ptr == '/' || *ptr == '\\') break;
74     }
75     return ++ptr;
76 }
77
78 static void module_fill_module(const WCHAR* in, WCHAR* out, size_t size)
79 {
80     const WCHAR *ptr, *endptr;
81     size_t      len, l;
82
83     ptr = get_filename(in, endptr = in + strlenW(in));
84     len = min(endptr - ptr, size - 1);
85     memcpy(out, ptr, len * sizeof(WCHAR));
86     out[len] = '\0';
87     if (len > 4 && (l = match_ext(out, len)))
88         out[len - l] = '\0';
89     else if (len > 4 && !strcmpiW(out + len - 4, S_WineW))
90         lstrcpynW(out, S_WineLoaderW, size);
91     else
92     {
93         if (len > 3 && !strcmpiW(&out[len - 3], S_DotSoW) &&
94             (l = match_ext(out, len - 3)))
95             strcpyW(&out[len - l - 3], S_ElfW);
96     }
97     while ((*out = tolowerW(*out))) out++;
98 }
99
100 void module_set_module(struct module* module, const WCHAR* name)
101 {
102     module_fill_module(name, module->module.ModuleName, sizeof(module->module.ModuleName));
103     WideCharToMultiByte(CP_ACP, 0, module->module.ModuleName, -1,
104                         module->module_name, sizeof(module->module_name),
105                         NULL, NULL);
106 }
107
108 static const char*      get_module_type(enum module_type type, BOOL virtual)
109 {
110     switch (type)
111     {
112     case DMT_ELF: return virtual ? "Virtual ELF" : "ELF";
113     case DMT_PE: return virtual ? "Virtual PE" : "PE";
114     default: return "---";
115     }
116 }
117
118 /***********************************************************************
119  * Creates and links a new module to a process
120  */
121 struct module* module_new(struct process* pcs, const WCHAR* name,
122                           enum module_type type, BOOL virtual,
123                           unsigned long mod_addr, unsigned long size,
124                           unsigned long stamp, unsigned long checksum)
125 {
126     struct module*      module;
127
128     assert(type == DMT_ELF || type == DMT_PE);
129     if (!(module = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*module))))
130         return NULL;
131
132     module->next = pcs->lmodules;
133     pcs->lmodules = module;
134
135     TRACE("=> %s %08lx-%08lx %s\n",
136           get_module_type(type, virtual), mod_addr, mod_addr + size,
137           debugstr_w(name));
138
139     pool_init(&module->pool, 65536);
140
141     module->module.SizeOfStruct = sizeof(module->module);
142     module->module.BaseOfImage = mod_addr;
143     module->module.ImageSize = size;
144     module_set_module(module, name);
145     module->module.ImageName[0] = '\0';
146     lstrcpynW(module->module.LoadedImageName, name, sizeof(module->module.LoadedImageName) / sizeof(WCHAR));
147     module->module.SymType = SymNone;
148     module->module.NumSyms = 0;
149     module->module.TimeDateStamp = stamp;
150     module->module.CheckSum = checksum;
151
152     memset(module->module.LoadedPdbName, 0, sizeof(module->module.CVData));
153     module->module.CVSig = 0;
154     memset(module->module.CVData, 0, sizeof(module->module.CVData));
155     module->module.PdbSig = 0;
156     memset(&module->module.PdbSig70, 0, sizeof(module->module.PdbSig70));
157     module->module.PdbAge = 0;
158     module->module.PdbUnmatched = FALSE;
159     module->module.DbgUnmatched = FALSE;
160     module->module.LineNumbers = FALSE;
161     module->module.GlobalSymbols = FALSE;
162     module->module.TypeInfo = FALSE;
163     module->module.SourceIndexed = FALSE;
164     module->module.Publics = FALSE;
165
166     module->type              = type;
167     module->is_virtual        = virtual ? TRUE : FALSE;
168     module->sortlist_valid    = FALSE;
169     module->addr_sorttab      = NULL;
170     /* FIXME: this seems a bit too high (on a per module basis)
171      * need some statistics about this
172      */
173     hash_table_init(&module->pool, &module->ht_symbols, 4096);
174     hash_table_init(&module->pool, &module->ht_types,   4096);
175     vector_init(&module->vtypes, sizeof(struct symt*),  32);
176
177     module->sources_used      = 0;
178     module->sources_alloc     = 0;
179     module->sources           = 0;
180
181     return module;
182 }
183
184 /***********************************************************************
185  *      module_find_by_name
186  *
187  */
188 static struct module* module_find_by_name(const struct process* pcs, const WCHAR* name)
189 {
190     struct module*      module;
191
192     for (module = pcs->lmodules; module; module = module->next)
193     {
194         if (!strcmpiW(name, module->module.ModuleName)) return module;
195     }
196     SetLastError(ERROR_INVALID_NAME);
197     return NULL;
198 }
199
200 struct module* module_find_by_nameA(const struct process* pcs, const char* name)
201 {
202     WCHAR wname[MAX_PATH];
203
204     MultiByteToWideChar(CP_ACP, 0, name, -1, wname, sizeof(wname) / sizeof(WCHAR));
205     return module_find_by_name(pcs, wname);
206 }
207
208 /***********************************************************************
209  *      module_is_already_loaded
210  *
211  */
212 struct module* module_is_already_loaded(const struct process* pcs, const WCHAR* name)
213 {
214     struct module*      module;
215     const WCHAR*        filename;
216
217     /* first compare the loaded image name... */
218     for (module = pcs->lmodules; module; module = module->next)
219     {
220         if (!strcmpiW(name, module->module.LoadedImageName))
221             return module;
222     }
223     /* then compare the standard filenames (without the path) ... */
224     filename = get_filename(name, NULL);
225     for (module = pcs->lmodules; module; module = module->next)
226     {
227         if (!strcmpiW(filename, get_filename(module->module.LoadedImageName, NULL)))
228             return module;
229     }
230     SetLastError(ERROR_INVALID_NAME);
231     return NULL;
232 }
233
234 /***********************************************************************
235  *           module_get_container
236  *
237  */
238 static struct module* module_get_container(const struct process* pcs,
239                                     const struct module* inner)
240 {
241     struct module*      module;
242      
243     for (module = pcs->lmodules; module; module = module->next)
244     {
245         if (module != inner &&
246             module->module.BaseOfImage <= inner->module.BaseOfImage &&
247             module->module.BaseOfImage + module->module.ImageSize >=
248             inner->module.BaseOfImage + inner->module.ImageSize)
249             return module;
250     }
251     return NULL;
252 }
253
254 /***********************************************************************
255  *           module_get_containee
256  *
257  */
258 struct module* module_get_containee(const struct process* pcs, 
259                                     const struct module* outter)
260 {
261     struct module*      module;
262      
263     for (module = pcs->lmodules; module; module = module->next)
264     {
265         if (module != outter &&
266             outter->module.BaseOfImage <= module->module.BaseOfImage &&
267             outter->module.BaseOfImage + outter->module.ImageSize >=
268             module->module.BaseOfImage + module->module.ImageSize)
269             return module;
270     }
271     return NULL;
272 }
273
274 /******************************************************************
275  *              module_get_debug
276  *
277  * get the debug information from a module:
278  * - if the module's type is deferred, then force loading of debug info (and return
279  *   the module itself)
280  * - if the module has no debug info and has an ELF container, then return the ELF
281  *   container (and also force the ELF container's debug info loading if deferred)
282  * - otherwise return the module itself if it has some debug info
283  */
284 BOOL module_get_debug(struct module_pair* pair)
285 {
286     IMAGEHLP_DEFERRED_SYMBOL_LOADW64    idslW64;
287
288     if (!pair->requested) return FALSE;
289     /* for a PE builtin, always get info from container */
290     if (!(pair->effective = module_get_container(pair->pcs, pair->requested)))
291         pair->effective = pair->requested;
292     /* if deferred, force loading */
293     if (pair->effective->module.SymType == SymDeferred)
294     {
295         BOOL ret;
296         
297         if (pair->effective->is_virtual) ret = FALSE;
298         else switch (pair->effective->type)
299         {
300         case DMT_ELF:
301             ret = elf_load_debug_info(pair->effective, NULL);
302             break;
303         case DMT_PE:
304             idslW64.SizeOfStruct = sizeof(idslW64);
305             idslW64.BaseOfImage = pair->effective->module.BaseOfImage;
306             idslW64.CheckSum = pair->effective->module.CheckSum;
307             idslW64.TimeDateStamp = pair->effective->module.TimeDateStamp;
308             memcpy(idslW64.FileName, pair->effective->module.ImageName,
309                    sizeof(pair->effective->module.ImageName));
310             idslW64.Reparse = FALSE;
311             idslW64.hFile = INVALID_HANDLE_VALUE;
312
313             pcs_callback(pair->pcs, CBA_DEFERRED_SYMBOL_LOAD_START, &idslW64);
314             ret = pe_load_debug_info(pair->pcs, pair->effective);
315             pcs_callback(pair->pcs,
316                          ret ? CBA_DEFERRED_SYMBOL_LOAD_COMPLETE : CBA_DEFERRED_SYMBOL_LOAD_FAILURE,
317                          &idslW64);
318             break;
319         default:
320             ret = FALSE;
321             break;
322         }
323         if (!ret) pair->effective->module.SymType = SymNone;
324         assert(pair->effective->module.SymType != SymDeferred);
325         pair->effective->module.NumSyms = pair->effective->ht_symbols.num_elts;
326     }
327     return pair->effective->module.SymType != SymNone;
328 }
329
330 /***********************************************************************
331  *      module_find_by_addr
332  *
333  * either the addr where module is loaded, or any address inside the 
334  * module
335  */
336 struct module* module_find_by_addr(const struct process* pcs, unsigned long addr, 
337                                    enum module_type type)
338 {
339     struct module*      module;
340     
341     if (type == DMT_UNKNOWN)
342     {
343         if ((module = module_find_by_addr(pcs, addr, DMT_PE)) ||
344             (module = module_find_by_addr(pcs, addr, DMT_ELF)))
345             return module;
346     }
347     else
348     {
349         for (module = pcs->lmodules; module; module = module->next)
350         {
351             if (type == module->type && addr >= module->module.BaseOfImage &&
352                 addr < module->module.BaseOfImage + module->module.ImageSize) 
353                 return module;
354         }
355     }
356     SetLastError(ERROR_INVALID_ADDRESS);
357     return module;
358 }
359
360 /******************************************************************
361  *              module_is_container_loaded
362  *
363  * checks whether the native container, for a (supposed) PE builtin is
364  * already loaded
365  */
366 static BOOL module_is_container_loaded(const struct process* pcs,
367                                        const WCHAR* ImageName, DWORD base)
368 {
369     size_t              len;
370     struct module*      module;
371     PCWSTR              filename, modname;
372
373     if (!base) return FALSE;
374     filename = get_filename(ImageName, NULL);
375     len = strlenW(filename);
376
377     for (module = pcs->lmodules; module; module = module->next)
378     {
379         if (module->type == DMT_ELF &&
380             base >= module->module.BaseOfImage &&
381             base < module->module.BaseOfImage + module->module.ImageSize)
382         {
383             modname = get_filename(module->module.LoadedImageName, NULL);
384             if (!strncmpiW(modname, filename, len) &&
385                 !memcmp(modname + len, S_DotSoW, 3 * sizeof(WCHAR)))
386             {
387                 return TRUE;
388             }
389         }
390     }
391     /* likely a native PE module */
392     WARN("Couldn't find container for %s\n", debugstr_w(ImageName));
393     return FALSE;
394 }
395
396 /******************************************************************
397  *              module_get_type_by_name
398  *
399  * Guesses a filename type from its extension
400  */
401 enum module_type module_get_type_by_name(const WCHAR* name)
402 {
403     int len = strlenW(name);
404
405     /* Skip all version extensions (.[digits]) regex: "(\.\d+)*$" */
406     do
407     {
408         int i = len;
409
410         while (i && isdigit(name[i - 1])) i--;
411
412         if (i && name[i - 1] == '.')
413             len = i - 1;
414         else
415             break;
416     } while (len);
417
418     /* check for terminating .so or .so.[digit] */
419     if (len > 3 && !memcmp(name + len - 3, S_DotSoW, 3))
420         return DMT_ELF;
421
422     if (len > 4 && !strncmpiW(name + len - 4, S_DotPdbW, 4))
423         return DMT_PDB;
424
425     if (len > 4 && !strncmpiW(name + len - 4, S_DotDbgW, 4))
426         return DMT_DBG;
427
428     /* wine is also an ELF module */
429     if (((len > 4 && name[len - 5] == '/') || len == 4) && !strcmpiW(name + len - 4, S_WineW))
430         return DMT_ELF;
431
432     return DMT_PE;
433 }
434
435 /***********************************************************************
436  *                      SymLoadModule (DBGHELP.@)
437  */
438 DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, PCSTR ImageName,
439                            PCSTR ModuleName, DWORD BaseOfDll, DWORD SizeOfDll)
440 {
441     return SymLoadModuleEx(hProcess, hFile, ImageName, ModuleName, BaseOfDll,
442                            SizeOfDll, NULL, 0);
443 }
444
445 /***********************************************************************
446  *                      SymLoadModuleEx (DBGHELP.@)
447  */
448 DWORD64 WINAPI  SymLoadModuleEx(HANDLE hProcess, HANDLE hFile, PCSTR ImageName,
449                                 PCSTR ModuleName, DWORD64 BaseOfDll, DWORD DllSize,
450                                 PMODLOAD_DATA Data, DWORD Flags)
451 {
452     PWSTR       wImageName, wModuleName;
453     unsigned    len;
454     DWORD64     ret;
455
456     TRACE("(%p %p %s %s %s %08x %p %08x)\n",
457           hProcess, hFile, debugstr_a(ImageName), debugstr_a(ModuleName),
458           wine_dbgstr_longlong(BaseOfDll), DllSize, Data, Flags);
459
460     if (ImageName)
461     {
462         len = MultiByteToWideChar(CP_ACP, 0, ImageName, -1, NULL, 0);
463         wImageName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
464         MultiByteToWideChar(CP_ACP, 0, ImageName, -1, wImageName, len);
465     }
466     else wImageName = NULL;
467     if (ModuleName)
468     {
469         len = MultiByteToWideChar(CP_ACP, 0, ModuleName, -1, NULL, 0);
470         wModuleName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
471         MultiByteToWideChar(CP_ACP, 0, ModuleName, -1, wModuleName, len);
472     }
473     else wModuleName = NULL;
474
475     ret = SymLoadModuleExW(hProcess, hFile, wImageName, wModuleName,
476                           BaseOfDll, DllSize, Data, Flags);
477     HeapFree(GetProcessHeap(), 0, wImageName);
478     HeapFree(GetProcessHeap(), 0, wModuleName);
479     return ret;
480 }
481
482 /***********************************************************************
483  *                      SymLoadModuleExW (DBGHELP.@)
484  */
485 DWORD64 WINAPI  SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageName,
486                                  PCWSTR wModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll,
487                                  PMODLOAD_DATA Data, DWORD Flags)
488 {
489     struct process*     pcs;
490     struct module*      module = NULL;
491
492     TRACE("(%p %p %s %s %s %08x %p %08x)\n",
493           hProcess, hFile, debugstr_w(wImageName), debugstr_w(wModuleName),
494           wine_dbgstr_longlong(BaseOfDll), SizeOfDll, Data, Flags);
495
496     if (Data)
497         FIXME("Unsupported load data parameter %p for %s\n",
498               Data, debugstr_w(wImageName));
499     if (!validate_addr64(BaseOfDll)) return FALSE;
500
501     if (!(pcs = process_find_by_handle(hProcess))) return FALSE;
502
503     if (Flags & SLMFLAG_VIRTUAL)
504     {
505         module = module_new(pcs, wImageName, module_get_type_by_name(wImageName),
506                             TRUE, (DWORD)BaseOfDll, SizeOfDll, 0, 0);
507         if (!module) return FALSE;
508         if (wModuleName) module_set_module(module, wModuleName);
509         module->module.SymType = SymVirtual;
510
511         return TRUE;
512     }
513     if (Flags & ~(SLMFLAG_VIRTUAL))
514         FIXME("Unsupported Flags %08x for %s\n", Flags, debugstr_w(wImageName));
515
516     /* force transparent ELF loading / unloading */
517     elf_synchronize_module_list(pcs);
518
519     /* this is a Wine extension to the API just to redo the synchronisation */
520     if (!wImageName && !hFile) return 0;
521
522     /* check if the module is already loaded, or if it's a builtin PE module with
523      * an containing ELF module
524      */
525     if (wImageName)
526     {
527         module = module_is_already_loaded(pcs, wImageName);
528         if (!module && module_is_container_loaded(pcs, wImageName, BaseOfDll))
529         {
530             /* force the loading of DLL as builtin */
531             module = pe_load_builtin_module(pcs, wImageName, BaseOfDll, SizeOfDll);
532         }
533     }
534     if (!module)
535     {
536         /* otherwise, try a regular PE module */
537         if (!(module = pe_load_native_module(pcs, wImageName, hFile, BaseOfDll, SizeOfDll)))
538         {
539             /* and finally and ELF module */
540             if (wImageName && (module_get_type_by_name(wImageName) == DMT_ELF))
541                 module = elf_load_module(pcs, wImageName, BaseOfDll);
542         }
543     }
544     if (!module)
545     {
546         WARN("Couldn't locate %s\n", debugstr_w(wImageName));
547         return 0;
548     }
549     module->module.NumSyms = module->ht_symbols.num_elts;
550     /* by default module_new fills module.ModuleName from a derivation
551      * of LoadedImageName. Overwrite it, if we have better information
552      */
553     if (wModuleName)
554         module_set_module(module, wModuleName);
555     lstrcpynW(module->module.ImageName, wImageName,
556               sizeof(module->module.ImageName) / sizeof(WCHAR));
557
558     return module->module.BaseOfImage;
559 }
560
561 /***********************************************************************
562  *                     SymLoadModule64 (DBGHELP.@)
563  */
564 DWORD64 WINAPI SymLoadModule64(HANDLE hProcess, HANDLE hFile, PCSTR ImageName,
565                                PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll)
566 {
567     if (!validate_addr64(BaseOfDll)) return FALSE;
568     return SymLoadModule(hProcess, hFile, ImageName, ModuleName, (DWORD)BaseOfDll, SizeOfDll);
569 }
570
571 /******************************************************************
572  *              module_remove
573  *
574  */
575 BOOL module_remove(struct process* pcs, struct module* module)
576 {
577     struct module**     p;
578
579     TRACE("%s (%p)\n", debugstr_w(module->module.ModuleName), module);
580     hash_table_destroy(&module->ht_symbols);
581     hash_table_destroy(&module->ht_types);
582     HeapFree(GetProcessHeap(), 0, module->sources);
583     HeapFree(GetProcessHeap(), 0, module->addr_sorttab);
584     HeapFree(GetProcessHeap(), 0, module->dwarf2_info);
585     pool_destroy(&module->pool);
586     /* native dbghelp doesn't invoke registered callback(,CBA_SYMBOLS_UNLOADED,) here
587      * so do we
588      */
589     for (p = &pcs->lmodules; *p; p = &(*p)->next)
590     {
591         if (*p == module)
592         {
593             *p = module->next;
594             HeapFree(GetProcessHeap(), 0, module);
595             return TRUE;
596         }
597     }
598     FIXME("This shouldn't happen\n");
599     return FALSE;
600 }
601
602 /******************************************************************
603  *              SymUnloadModule (DBGHELP.@)
604  *
605  */
606 BOOL WINAPI SymUnloadModule(HANDLE hProcess, DWORD BaseOfDll)
607 {
608     struct process*     pcs;
609     struct module*      module;
610
611     pcs = process_find_by_handle(hProcess);
612     if (!pcs) return FALSE;
613     module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
614     if (!module) return FALSE;
615     return module_remove(pcs, module);
616 }
617
618 /******************************************************************
619  *              SymUnloadModule64 (DBGHELP.@)
620  *
621  */
622 BOOL WINAPI SymUnloadModule64(HANDLE hProcess, DWORD64 BaseOfDll)
623 {
624     struct process*     pcs;
625     struct module*      module;
626
627     pcs = process_find_by_handle(hProcess);
628     if (!pcs) return FALSE;
629     if (!validate_addr64(BaseOfDll)) return FALSE;
630     module = module_find_by_addr(pcs, (DWORD)BaseOfDll, DMT_UNKNOWN);
631     if (!module) return FALSE;
632     return module_remove(pcs, module);
633 }
634
635 /******************************************************************
636  *              SymEnumerateModules (DBGHELP.@)
637  *
638  */
639 struct enum_modW64_32
640 {
641     PSYM_ENUMMODULES_CALLBACK   cb;
642     PVOID                       user;
643     char                        module[MAX_PATH];
644 };
645
646 static BOOL CALLBACK enum_modW64_32(PCWSTR name, DWORD64 base, PVOID user)
647 {
648     struct enum_modW64_32*      x = user;
649
650     WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL);
651     return x->cb(x->module, (DWORD)base, x->user);
652 }
653
654 BOOL  WINAPI SymEnumerateModules(HANDLE hProcess,
655                                  PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,  
656                                  PVOID UserContext)
657 {
658     struct enum_modW64_32       x;
659
660     x.cb = EnumModulesCallback;
661     x.user = UserContext;
662
663     return SymEnumerateModulesW64(hProcess, enum_modW64_32, &x);
664 }
665
666 /******************************************************************
667  *              SymEnumerateModules64 (DBGHELP.@)
668  *
669  */
670 struct enum_modW64_64
671 {
672     PSYM_ENUMMODULES_CALLBACK64 cb;
673     PVOID                       user;
674     char                        module[MAX_PATH];
675 };
676
677 static BOOL CALLBACK enum_modW64_64(PCWSTR name, DWORD64 base, PVOID user)
678 {
679     struct enum_modW64_64*      x = user;
680
681     WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL);
682     return x->cb(x->module, base, x->user);
683 }
684
685 BOOL  WINAPI SymEnumerateModules64(HANDLE hProcess,
686                                    PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback,  
687                                    PVOID UserContext)
688 {
689     struct enum_modW64_64       x;
690
691     x.cb = EnumModulesCallback;
692     x.user = UserContext;
693
694     return SymEnumerateModulesW64(hProcess, enum_modW64_64, &x);
695 }
696
697 /******************************************************************
698  *              SymEnumerateModulesW64 (DBGHELP.@)
699  *
700  */
701 BOOL  WINAPI SymEnumerateModulesW64(HANDLE hProcess,
702                                     PSYM_ENUMMODULES_CALLBACKW64 EnumModulesCallback,
703                                     PVOID UserContext)
704 {
705     struct process*     pcs = process_find_by_handle(hProcess);
706     struct module*      module;
707
708     if (!pcs) return FALSE;
709     
710     for (module = pcs->lmodules; module; module = module->next)
711     {
712         if (!(dbghelp_options & SYMOPT_WINE_WITH_NATIVE_MODULES) && module->type == DMT_ELF)
713             continue;
714         if (!EnumModulesCallback(module->module.ModuleName,
715                                  module->module.BaseOfImage, UserContext))
716             break;
717     }
718     return TRUE;
719 }
720
721 /******************************************************************
722  *              EnumerateLoadedModules64 (DBGHELP.@)
723  *
724  */
725 struct enum_load_modW64_64
726 {
727     PENUMLOADED_MODULES_CALLBACK64      cb;
728     PVOID                               user;
729     char                                module[MAX_PATH];
730 };
731
732 static BOOL CALLBACK enum_load_modW64_64(PCWSTR name, DWORD64 base, ULONG size,
733                                          PVOID user)
734 {
735     struct enum_load_modW64_64* x = user;
736
737     WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL);
738     return x->cb(x->module, base, size, x->user);
739 }
740
741 BOOL  WINAPI EnumerateLoadedModules64(HANDLE hProcess,
742                                       PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback,
743                                       PVOID UserContext)
744 {
745     struct enum_load_modW64_64  x;
746
747     x.cb = EnumLoadedModulesCallback;
748     x.user = UserContext;
749
750     return EnumerateLoadedModulesW64(hProcess, enum_load_modW64_64, &x);
751 }
752
753 /******************************************************************
754  *              EnumerateLoadedModules (DBGHELP.@)
755  *
756  */
757 struct enum_load_modW64_32
758 {
759     PENUMLOADED_MODULES_CALLBACK        cb;
760     PVOID                               user;
761     char                                module[MAX_PATH];
762 };
763
764 static BOOL CALLBACK enum_load_modW64_32(PCWSTR name, DWORD64 base, ULONG size,
765                                          PVOID user)
766 {
767     struct enum_load_modW64_32* x = user;
768     WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL);
769     return x->cb(x->module, (DWORD)base, size, x->user);
770 }
771
772 BOOL  WINAPI EnumerateLoadedModules(HANDLE hProcess,
773                                     PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback,
774                                     PVOID UserContext)
775 {
776     struct enum_load_modW64_32  x;
777
778     x.cb = EnumLoadedModulesCallback;
779     x.user = UserContext;
780
781     return EnumerateLoadedModulesW64(hProcess, enum_load_modW64_32, &x);
782 }
783
784 /******************************************************************
785  *              EnumerateLoadedModulesW64 (DBGHELP.@)
786  *
787  */
788 BOOL  WINAPI EnumerateLoadedModulesW64(HANDLE hProcess,
789                                        PENUMLOADED_MODULES_CALLBACKW64 EnumLoadedModulesCallback,
790                                        PVOID UserContext)
791 {
792     HMODULE*    hMods;
793     WCHAR       baseW[256], modW[256];
794     DWORD       i, sz;
795     MODULEINFO  mi;
796
797     hMods = HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(hMods[0]));
798     if (!hMods) return FALSE;
799
800     if (!EnumProcessModules(hProcess, hMods, 256 * sizeof(hMods[0]), &sz))
801     {
802         /* hProcess should also be a valid process handle !! */
803         FIXME("If this happens, bump the number in mod\n");
804         HeapFree(GetProcessHeap(), 0, hMods);
805         return FALSE;
806     }
807     sz /= sizeof(HMODULE);
808     for (i = 0; i < sz; i++)
809     {
810         if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
811             !GetModuleBaseNameW(hProcess, hMods[i], baseW, sizeof(baseW) / sizeof(WCHAR)))
812             continue;
813         module_fill_module(baseW, modW, sizeof(modW) / sizeof(CHAR));
814         EnumLoadedModulesCallback(modW, (DWORD_PTR)mi.lpBaseOfDll, mi.SizeOfImage,
815                                   UserContext);
816     }
817     HeapFree(GetProcessHeap(), 0, hMods);
818
819     return sz != 0 && i == sz;
820 }
821
822 /******************************************************************
823  *              SymGetModuleInfo (DBGHELP.@)
824  *
825  */
826 BOOL  WINAPI SymGetModuleInfo(HANDLE hProcess, DWORD dwAddr,
827                               PIMAGEHLP_MODULE ModuleInfo)
828 {
829     IMAGEHLP_MODULE     mi;
830     IMAGEHLP_MODULEW64  miw64;
831
832     if (sizeof(mi) < ModuleInfo->SizeOfStruct) FIXME("Wrong size\n");
833
834     miw64.SizeOfStruct = sizeof(miw64);
835     if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE;
836
837     mi.SizeOfStruct  = miw64.SizeOfStruct;
838     mi.BaseOfImage   = miw64.BaseOfImage;
839     mi.ImageSize     = miw64.ImageSize;
840     mi.TimeDateStamp = miw64.TimeDateStamp;
841     mi.CheckSum      = miw64.CheckSum;
842     mi.NumSyms       = miw64.NumSyms;
843     mi.SymType       = miw64.SymType;
844     WideCharToMultiByte(CP_ACP, 0, miw64.ModuleName, -1,
845                         mi.ModuleName, sizeof(mi.ModuleName), NULL, NULL);
846     WideCharToMultiByte(CP_ACP, 0, miw64.ImageName, -1,
847                         mi.ImageName, sizeof(mi.ImageName), NULL, NULL);
848     WideCharToMultiByte(CP_ACP, 0, miw64.LoadedImageName, -1,
849                         mi.LoadedImageName, sizeof(mi.LoadedImageName), NULL, NULL);
850
851     memcpy(ModuleInfo, &mi, ModuleInfo->SizeOfStruct);
852
853     return TRUE;
854 }
855
856 /******************************************************************
857  *              SymGetModuleInfoW (DBGHELP.@)
858  *
859  */
860 BOOL  WINAPI SymGetModuleInfoW(HANDLE hProcess, DWORD dwAddr,
861                                PIMAGEHLP_MODULEW ModuleInfo)
862 {
863     IMAGEHLP_MODULEW64  miw64;
864     IMAGEHLP_MODULEW    miw;
865
866     if (sizeof(miw) < ModuleInfo->SizeOfStruct) FIXME("Wrong size\n");
867
868     miw64.SizeOfStruct = sizeof(miw64);
869     if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE;
870
871     miw.SizeOfStruct  = miw64.SizeOfStruct;
872     miw.BaseOfImage   = miw64.BaseOfImage;
873     miw.ImageSize     = miw64.ImageSize;
874     miw.TimeDateStamp = miw64.TimeDateStamp;
875     miw.CheckSum      = miw64.CheckSum;
876     miw.NumSyms       = miw64.NumSyms;
877     miw.SymType       = miw64.SymType;
878     strcpyW(miw.ModuleName, miw64.ModuleName);
879     strcpyW(miw.ImageName, miw64.ImageName);
880     strcpyW(miw.LoadedImageName, miw64.LoadedImageName);
881     memcpy(ModuleInfo, &miw, ModuleInfo->SizeOfStruct);
882
883     return TRUE;
884 }
885
886 /******************************************************************
887  *              SymGetModuleInfo64 (DBGHELP.@)
888  *
889  */
890 BOOL  WINAPI SymGetModuleInfo64(HANDLE hProcess, DWORD64 dwAddr,
891                                 PIMAGEHLP_MODULE64 ModuleInfo)
892 {
893     IMAGEHLP_MODULE64   mi64;
894     IMAGEHLP_MODULEW64  miw64;
895
896     if (sizeof(mi64) < ModuleInfo->SizeOfStruct)
897     {
898         SetLastError(ERROR_MOD_NOT_FOUND); /* NOTE: native returns this error */
899         WARN("Wrong size %u\n", ModuleInfo->SizeOfStruct);
900         return FALSE;
901     }
902
903     miw64.SizeOfStruct = sizeof(miw64);
904     if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE;
905
906     mi64.SizeOfStruct  = miw64.SizeOfStruct;
907     mi64.BaseOfImage   = miw64.BaseOfImage;
908     mi64.ImageSize     = miw64.ImageSize;
909     mi64.TimeDateStamp = miw64.TimeDateStamp;
910     mi64.CheckSum      = miw64.CheckSum;
911     mi64.NumSyms       = miw64.NumSyms;
912     mi64.SymType       = miw64.SymType;
913     WideCharToMultiByte(CP_ACP, 0, miw64.ModuleName, -1,
914                         mi64.ModuleName, sizeof(mi64.ModuleName), NULL, NULL);
915     WideCharToMultiByte(CP_ACP, 0, miw64.ImageName, -1,
916                         mi64.ImageName, sizeof(mi64.ImageName), NULL, NULL);
917     WideCharToMultiByte(CP_ACP, 0, miw64.LoadedImageName, -1,
918                         mi64.LoadedImageName, sizeof(mi64.LoadedImageName), NULL, NULL);
919     WideCharToMultiByte(CP_ACP, 0, miw64.LoadedPdbName, -1,
920                         mi64.LoadedPdbName, sizeof(mi64.LoadedPdbName), NULL, NULL);
921
922     mi64.CVSig         = miw64.CVSig;
923     WideCharToMultiByte(CP_ACP, 0, miw64.CVData, -1,
924                         mi64.CVData, sizeof(mi64.CVData), NULL, NULL);
925     mi64.PdbSig        = miw64.PdbSig;
926     mi64.PdbSig70      = miw64.PdbSig70;
927     mi64.PdbAge        = miw64.PdbAge;
928     mi64.PdbUnmatched  = miw64.PdbUnmatched;
929     mi64.DbgUnmatched  = miw64.DbgUnmatched;
930     mi64.LineNumbers   = miw64.LineNumbers;
931     mi64.GlobalSymbols = miw64.GlobalSymbols;
932     mi64.TypeInfo      = miw64.TypeInfo;
933     mi64.SourceIndexed = miw64.SourceIndexed;
934     mi64.Publics       = miw64.Publics;
935
936     memcpy(ModuleInfo, &mi64, ModuleInfo->SizeOfStruct);
937
938     return TRUE;
939 }
940
941 /******************************************************************
942  *              SymGetModuleInfoW64 (DBGHELP.@)
943  *
944  */
945 BOOL  WINAPI SymGetModuleInfoW64(HANDLE hProcess, DWORD64 dwAddr,
946                                  PIMAGEHLP_MODULEW64 ModuleInfo)
947 {
948     struct process*     pcs = process_find_by_handle(hProcess);
949     struct module*      module;
950     IMAGEHLP_MODULEW64  miw64;
951
952     TRACE("%p %s %p\n", hProcess, wine_dbgstr_longlong(dwAddr), ModuleInfo);
953
954     if (!pcs) return FALSE;
955     if (ModuleInfo->SizeOfStruct > sizeof(*ModuleInfo)) return FALSE;
956     module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
957     if (!module) return FALSE;
958
959     miw64 = module->module;
960
961     /* update debug information from container if any */
962     if (module->module.SymType == SymNone)
963     {
964         module = module_get_container(pcs, module);
965         if (module && module->module.SymType != SymNone)
966         {
967             miw64.SymType = module->module.SymType;
968             miw64.NumSyms = module->module.NumSyms;
969         }
970     }
971     memcpy(ModuleInfo, &miw64, ModuleInfo->SizeOfStruct);
972     return TRUE;
973 }
974
975 /***********************************************************************
976  *              SymGetModuleBase (DBGHELP.@)
977  */
978 DWORD WINAPI SymGetModuleBase(HANDLE hProcess, DWORD dwAddr)
979 {
980     struct process*     pcs = process_find_by_handle(hProcess);
981     struct module*      module;
982
983     if (!pcs) return 0;
984     module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
985     if (!module) return 0;
986     return module->module.BaseOfImage;
987 }
988
989 /***********************************************************************
990  *              SymGetModuleBase64 (DBGHELP.@)
991  */
992 DWORD64 WINAPI SymGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr)
993 {
994     if (!validate_addr64(dwAddr)) return 0;
995     return SymGetModuleBase(hProcess, (DWORD)dwAddr);
996 }
997
998 /******************************************************************
999  *              module_reset_debug_info
1000  * Removes any debug information linked to a given module.
1001  */
1002 void module_reset_debug_info(struct module* module)
1003 {
1004     module->sortlist_valid = TRUE;
1005     module->addr_sorttab = NULL;
1006     hash_table_destroy(&module->ht_symbols);
1007     module->ht_symbols.num_buckets = 0;
1008     module->ht_symbols.buckets = NULL;
1009     hash_table_destroy(&module->ht_types);
1010     module->ht_types.num_buckets = 0;
1011     module->ht_types.buckets = NULL;
1012     module->vtypes.num_elts = 0;
1013     hash_table_destroy(&module->ht_symbols);
1014     module->sources_used = module->sources_alloc = 0;
1015     module->sources = NULL;
1016 }