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