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