netstat: Initial implementation.
[wine] / dlls / dbghelp / type.c
1 /*
2  * File types.c - management of types (hierarchical tree)
3  *
4  * Copyright (C) 1997, Eric Youngdale.
5  *               2004, 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  * Note: This really doesn't do much at the moment, but it forms the framework
22  * upon which full support for datatype handling will eventually be built.
23  */
24
25 #define NONAMELESSUNION
26
27 #include "config.h"
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <assert.h>
31
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winnls.h"
35 #include "wine/debug.h"
36 #include "dbghelp_private.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
39 WINE_DECLARE_DEBUG_CHANNEL(dbghelp_symt);
40
41 static const char* symt_get_tag_str(DWORD tag)
42 {
43     switch (tag)
44     {
45     case SymTagNull:                    return "SymTagNull";
46     case SymTagExe:                     return "SymTagExe";
47     case SymTagCompiland:               return "SymTagCompiland";
48     case SymTagCompilandDetails:        return "SymTagCompilandDetails";
49     case SymTagCompilandEnv:            return "SymTagCompilandEnv";
50     case SymTagFunction:                return "SymTagFunction";
51     case SymTagBlock:                   return "SymTagBlock";
52     case SymTagData:                    return "SymTagData";
53     case SymTagAnnotation:              return "SymTagAnnotation";
54     case SymTagLabel:                   return "SymTagLabel";
55     case SymTagPublicSymbol:            return "SymTagPublicSymbol";
56     case SymTagUDT:                     return "SymTagUDT";
57     case SymTagEnum:                    return "SymTagEnum";
58     case SymTagFunctionType:            return "SymTagFunctionType";
59     case SymTagPointerType:             return "SymTagPointerType";
60     case SymTagArrayType:               return "SymTagArrayType";
61     case SymTagBaseType:                return "SymTagBaseType";
62     case SymTagTypedef:                 return "SymTagTypedef,";
63     case SymTagBaseClass:               return "SymTagBaseClass";
64     case SymTagFriend:                  return "SymTagFriend";
65     case SymTagFunctionArgType:         return "SymTagFunctionArgType,";
66     case SymTagFuncDebugStart:          return "SymTagFuncDebugStart,";
67     case SymTagFuncDebugEnd:            return "SymTagFuncDebugEnd";
68     case SymTagUsingNamespace:          return "SymTagUsingNamespace,";
69     case SymTagVTableShape:             return "SymTagVTableShape";
70     case SymTagVTable:                  return "SymTagVTable";
71     case SymTagCustom:                  return "SymTagCustom";
72     case SymTagThunk:                   return "SymTagThunk";
73     case SymTagCustomType:              return "SymTagCustomType";
74     case SymTagManagedType:             return "SymTagManagedType";
75     case SymTagDimension:               return "SymTagDimension";
76     default:                            return "---";
77     }
78 }
79
80 const char* symt_get_name(const struct symt* sym)
81 {
82     switch (sym->tag)
83     {
84     /* lexical tree */
85     case SymTagData:            return ((const struct symt_data*)sym)->hash_elt.name;
86     case SymTagFunction:        return ((const struct symt_function*)sym)->hash_elt.name;
87     case SymTagPublicSymbol:    return ((const struct symt_public*)sym)->hash_elt.name;
88     case SymTagBaseType:        return ((const struct symt_basic*)sym)->hash_elt.name;
89     case SymTagLabel:           return ((const struct symt_hierarchy_point*)sym)->hash_elt.name;
90     case SymTagThunk:           return ((const struct symt_thunk*)sym)->hash_elt.name;
91     /* hierarchy tree */
92     case SymTagEnum:            return ((const struct symt_enum*)sym)->name;
93     case SymTagTypedef:         return ((const struct symt_typedef*)sym)->hash_elt.name;
94     case SymTagUDT:             return ((const struct symt_udt*)sym)->hash_elt.name;
95     default:
96         FIXME("Unsupported sym-tag %s\n", symt_get_tag_str(sym->tag));
97         /* fall through */
98     case SymTagArrayType:
99     case SymTagPointerType:
100     case SymTagFunctionType:
101         return NULL;
102     }
103 }
104
105 WCHAR* symt_get_nameW(const struct symt* sym)
106 {
107     const char* name = symt_get_name(sym);
108     WCHAR* nameW;
109     DWORD sz;
110
111     if (!name) return NULL;
112     sz = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
113     if ((nameW = HeapAlloc(GetProcessHeap(), 0, sz * sizeof(WCHAR))))
114         MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, sz);
115     return nameW;
116 }
117
118 BOOL symt_get_address(const struct symt* type, ULONG64* addr)
119 {
120     switch (type->tag)
121     {
122     case SymTagData:
123         switch (((const struct symt_data*)type)->kind)
124         {
125         case DataIsGlobal:
126         case DataIsFileStatic:
127             *addr = ((const struct symt_data*)type)->u.var.offset;
128             break;
129         default: return FALSE;
130         }
131         break;
132     case SymTagFunction:
133         *addr = ((const struct symt_function*)type)->address;
134         break;
135     case SymTagPublicSymbol:
136         *addr = ((const struct symt_public*)type)->address;
137         break;
138     case SymTagFuncDebugStart:
139     case SymTagFuncDebugEnd:
140     case SymTagLabel:
141         if (!((const struct symt_hierarchy_point*)type)->parent ||
142             !symt_get_address(((const struct symt_hierarchy_point*)type)->parent, addr))
143             return FALSE;
144         *addr += ((const struct symt_hierarchy_point*)type)->loc.offset;
145         break;
146     case SymTagThunk:
147         *addr = ((const struct symt_thunk*)type)->address;
148         break;
149     case SymTagCompiland:
150         *addr = ((const struct symt_compiland*)type)->address;
151         break;
152     default:
153         FIXME("Unsupported sym-tag %s for get-address\n", symt_get_tag_str(type->tag));
154         return FALSE;
155     }
156     return TRUE;
157 }
158
159 static struct symt* symt_find_type_by_name(const struct module* module,
160                                            enum SymTagEnum sym_tag, 
161                                            const char* typename)
162 {
163     void*                       ptr;
164     struct symt_ht*             type;
165     struct hash_table_iter      hti;
166
167     assert(typename);
168     assert(module);
169
170     hash_table_iter_init(&module->ht_types, &hti, typename);
171     while ((ptr = hash_table_iter_up(&hti)))
172     {
173         type = GET_ENTRY(ptr, struct symt_ht, hash_elt);
174
175         if ((sym_tag == SymTagNull || type->symt.tag == sym_tag) &&
176             type->hash_elt.name && !strcmp(type->hash_elt.name, typename))
177             return &type->symt;
178     }
179     SetLastError(ERROR_INVALID_NAME); /* FIXME ?? */
180     return NULL;
181 }
182
183 static void symt_add_type(struct module* module, struct symt* symt)
184 {
185     struct symt**       p;
186     p = vector_add(&module->vtypes, &module->pool);
187     assert(p);
188     *p = symt;
189 }
190
191 struct symt_basic* symt_new_basic(struct module* module, enum BasicType bt, 
192                                   const char* typename, unsigned size)
193 {
194     struct symt_basic*          sym;
195
196     if (typename)
197     {
198         sym = (struct symt_basic*)symt_find_type_by_name(module, SymTagBaseType,
199                                                          typename);
200         if (sym && sym->bt == bt && sym->size == size)
201             return sym;
202     }
203     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
204     {
205         sym->symt.tag = SymTagBaseType;
206         if (typename)
207         {
208             sym->hash_elt.name = pool_strdup(&module->pool, typename);
209             hash_table_add(&module->ht_types, &sym->hash_elt);
210         } else sym->hash_elt.name = NULL;
211         sym->bt = bt;
212         sym->size = size;
213         symt_add_type(module, &sym->symt);
214     }
215     return sym;
216 }
217
218 struct symt_udt* symt_new_udt(struct module* module, const char* typename, 
219                               unsigned size, enum UdtKind kind)
220 {
221     struct symt_udt*            sym;
222
223     TRACE_(dbghelp_symt)("Adding udt %s:%s\n",
224                          debugstr_w(module->module.ModuleName), typename);
225     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
226     {
227         sym->symt.tag = SymTagUDT;
228         sym->kind     = kind;
229         sym->size     = size;
230         if (typename)
231         {
232             sym->hash_elt.name = pool_strdup(&module->pool, typename);
233             hash_table_add(&module->ht_types, &sym->hash_elt);
234         } else sym->hash_elt.name = NULL;
235         vector_init(&sym->vchildren, sizeof(struct symt*), 8);
236         symt_add_type(module, &sym->symt);
237     }
238     return sym;
239 }
240
241 BOOL symt_set_udt_size(struct module* module, struct symt_udt* udt, unsigned size)
242 {
243     assert(udt->symt.tag == SymTagUDT);
244     if (vector_length(&udt->vchildren) != 0)
245     {
246         if (udt->size != size)
247             FIXME_(dbghelp_symt)("Changing size for %s from %u to %u\n", 
248                                  udt->hash_elt.name, udt->size, size);
249         return TRUE;
250     }
251     udt->size = size;
252     return TRUE;
253 }
254
255 /******************************************************************
256  *              symt_add_udt_element
257  *
258  * add an element to a udt (struct, class, union)
259  * the size & offset parameters are expressed in bits (not bytes) so that
260  * we can mix in the single call bytes aligned elements (regular fields) and
261  * the others (bit fields)
262  */
263 BOOL symt_add_udt_element(struct module* module, struct symt_udt* udt_type,
264                           const char* name, struct symt* elt_type,
265                           unsigned offset, unsigned size)
266 {
267     struct symt_data*   m;
268     struct symt**       p;
269
270     assert(udt_type->symt.tag == SymTagUDT);
271
272     TRACE_(dbghelp_symt)("Adding %s to UDT %s\n", name, udt_type->hash_elt.name);
273     if (name)
274     {
275         unsigned int    i;
276         for (i=0; i<vector_length(&udt_type->vchildren); i++)
277         {
278             m = *(struct symt_data**)vector_at(&udt_type->vchildren, i);
279             assert(m);
280             assert(m->symt.tag == SymTagData);
281             if (strcmp(m->hash_elt.name, name) == 0)
282                 return TRUE;
283         }
284     }
285
286     if ((m = pool_alloc(&module->pool, sizeof(*m))) == NULL) return FALSE;
287     memset(m, 0, sizeof(*m));
288     m->symt.tag      = SymTagData;
289     m->hash_elt.name = name ? pool_strdup(&module->pool, name) : "";
290     m->hash_elt.next = NULL;
291
292     m->kind            = DataIsMember;
293     m->container       = &udt_type->symt;
294     m->type            = elt_type;
295     m->u.member.offset = offset;
296     m->u.member.length = ((offset & 7) || (size & 7)) ? size : 0;
297     p = vector_add(&udt_type->vchildren, &module->pool);
298     *p = &m->symt;
299
300     return TRUE;
301 }
302
303 struct symt_enum* symt_new_enum(struct module* module, const char* typename,
304                                 struct symt* basetype)
305 {
306     struct symt_enum*   sym;
307
308     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
309     {
310         sym->symt.tag            = SymTagEnum;
311         sym->name = (typename) ? pool_strdup(&module->pool, typename) : NULL;
312         sym->base_type           = basetype;
313         vector_init(&sym->vchildren, sizeof(struct symt*), 8);
314     }
315     return sym;
316 }
317
318 BOOL symt_add_enum_element(struct module* module, struct symt_enum* enum_type,
319                            const char* name, int value)
320 {
321     struct symt_data*   e;
322     struct symt**       p;
323
324     assert(enum_type->symt.tag == SymTagEnum);
325     e = pool_alloc(&module->pool, sizeof(*e));
326     if (e == NULL) return FALSE;
327
328     e->symt.tag = SymTagData;
329     e->hash_elt.name = pool_strdup(&module->pool, name);
330     e->hash_elt.next = NULL;
331     e->kind = DataIsConstant;
332     e->container = &enum_type->symt;
333     e->type = enum_type->base_type;
334     e->u.value.n1.n2.vt = VT_I4;
335     e->u.value.n1.n2.n3.lVal = value;
336
337     p = vector_add(&enum_type->vchildren, &module->pool);
338     if (!p) return FALSE; /* FIXME we leak e */
339     *p = &e->symt;
340
341     return TRUE;
342 }
343
344 struct symt_array* symt_new_array(struct module* module, int min, int max, 
345                                   struct symt* base, struct symt* index)
346 {
347     struct symt_array*  sym;
348
349     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
350     {
351         sym->symt.tag   = SymTagArrayType;
352         sym->start      = min;
353         sym->end        = max;
354         sym->base_type  = base;
355         sym->index_type = index;
356         symt_add_type(module, &sym->symt);
357     }
358     return sym;
359 }
360
361 static inline DWORD symt_array_count(struct module* module, const struct symt_array* array)
362 {
363     if (array->end < 0)
364     {
365         DWORD64 elem_size;
366         /* One could want to also set the array->end field in array, but we won't do it
367          * as long as all the get_type() helpers use const objects
368          */
369         if (symt_get_info(module, array->base_type, TI_GET_LENGTH, &elem_size) && elem_size)
370             return -array->end / (DWORD)elem_size;
371         return 0;
372     }
373     return array->end - array->start + 1;
374 }
375
376 struct symt_function_signature* symt_new_function_signature(struct module* module, 
377                                                             struct symt* ret_type,
378                                                             enum CV_call_e call_conv)
379 {
380     struct symt_function_signature*     sym;
381
382     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
383     {
384         sym->symt.tag = SymTagFunctionType;
385         sym->rettype  = ret_type;
386         vector_init(&sym->vchildren, sizeof(struct symt*), 4);
387         sym->call_conv = call_conv;
388         symt_add_type(module, &sym->symt);
389     }
390     return sym;
391 }
392
393 BOOL symt_add_function_signature_parameter(struct module* module,
394                                            struct symt_function_signature* sig_type,
395                                            struct symt* param)
396 {
397     struct symt**                       p;
398     struct symt_function_arg_type*      arg;
399
400     assert(sig_type->symt.tag == SymTagFunctionType);
401     arg = pool_alloc(&module->pool, sizeof(*arg));
402     if (!arg) return FALSE;
403     arg->symt.tag = SymTagFunctionArgType;
404     arg->arg_type = param;
405     arg->container = &sig_type->symt;
406     p = vector_add(&sig_type->vchildren, &module->pool);
407     if (!p) return FALSE; /* FIXME we leak arg */
408     *p = &arg->symt;
409
410     return TRUE;
411 }
412
413 struct symt_pointer* symt_new_pointer(struct module* module, struct symt* ref_type, unsigned long size)
414 {
415     struct symt_pointer*        sym;
416
417     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
418     {
419         sym->symt.tag = SymTagPointerType;
420         sym->pointsto = ref_type;
421         sym->size     = size;
422         symt_add_type(module, &sym->symt);
423     }
424     return sym;
425 }
426
427 struct symt_typedef* symt_new_typedef(struct module* module, struct symt* ref, 
428                                       const char* name)
429 {
430     struct symt_typedef* sym;
431
432     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
433     {
434         sym->symt.tag = SymTagTypedef;
435         sym->type     = ref;
436         sym->hash_elt.name = pool_strdup(&module->pool, name);
437         hash_table_add(&module->ht_types, &sym->hash_elt);
438         symt_add_type(module, &sym->symt);
439     }
440     return sym;
441 }
442
443 /******************************************************************
444  *              SymEnumTypes (DBGHELP.@)
445  *
446  */
447 BOOL WINAPI SymEnumTypes(HANDLE hProcess, ULONG64 BaseOfDll,
448                          PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
449                          PVOID UserContext)
450 {
451     struct module_pair  pair;
452     char                buffer[sizeof(SYMBOL_INFO) + 256];
453     SYMBOL_INFO*        sym_info = (SYMBOL_INFO*)buffer;
454     const char*         tmp;
455     struct symt*        type;
456     DWORD64             size;
457     unsigned int        i;
458
459     TRACE("(%p %s %p %p)\n",
460           hProcess, wine_dbgstr_longlong(BaseOfDll), EnumSymbolsCallback,
461           UserContext);
462
463     if (!(pair.pcs = process_find_by_handle(hProcess))) return FALSE;
464     pair.requested = module_find_by_addr(pair.pcs, BaseOfDll, DMT_UNKNOWN);
465     if (!module_get_debug(&pair)) return FALSE;
466
467     sym_info->SizeOfStruct = sizeof(SYMBOL_INFO);
468     sym_info->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO);
469
470     for (i=0; i<vector_length(&pair.effective->vtypes); i++)
471     {
472         type = *(struct symt**)vector_at(&pair.effective->vtypes, i);
473         sym_info->TypeIndex = symt_ptr2index(pair.effective, type);
474         sym_info->info = 0; /* FIXME */
475         symt_get_info(pair.effective, type, TI_GET_LENGTH, &size);
476         sym_info->Size = size;
477         sym_info->ModBase = pair.requested->module.BaseOfImage;
478         sym_info->Flags = 0; /* FIXME */
479         sym_info->Value = 0; /* FIXME */
480         sym_info->Address = 0; /* FIXME */
481         sym_info->Register = 0; /* FIXME */
482         sym_info->Scope = 0; /* FIXME */
483         sym_info->Tag = type->tag;
484         tmp = symt_get_name(type);
485         if (tmp)
486         {
487             sym_info->NameLen = min(strlen(tmp),sym_info->MaxNameLen-1);
488             memcpy(sym_info->Name, tmp, sym_info->NameLen);
489             sym_info->Name[sym_info->NameLen] = '\0';
490         }
491         else
492            sym_info->Name[sym_info->NameLen = 0] = '\0';
493         if (!EnumSymbolsCallback(sym_info, sym_info->Size, UserContext)) break;
494     }
495     return TRUE;
496 }
497
498 struct enum_types_AtoW
499 {
500     char                                buffer[sizeof(SYMBOL_INFOW) + 256 * sizeof(WCHAR)];
501     void*                               user;
502     PSYM_ENUMERATESYMBOLS_CALLBACKW     callback;
503 };
504
505 static BOOL CALLBACK enum_types_AtoW(PSYMBOL_INFO si, ULONG addr, PVOID _et)
506 {
507     struct enum_types_AtoW*     et = _et;
508     SYMBOL_INFOW*               siW = (SYMBOL_INFOW*)et->buffer;
509
510     copy_symbolW(siW, si);
511     return et->callback(siW, addr, et->user);
512 }
513
514 /******************************************************************
515  *              SymEnumTypesW (DBGHELP.@)
516  *
517  */
518 BOOL WINAPI SymEnumTypesW(HANDLE hProcess, ULONG64 BaseOfDll,
519                           PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback,
520                           PVOID UserContext)
521 {
522     struct enum_types_AtoW     et;
523
524     et.callback = EnumSymbolsCallback;
525     et.user = UserContext;
526
527     return SymEnumTypes(hProcess, BaseOfDll, enum_types_AtoW, &et);
528 }
529
530 /******************************************************************
531  *              symt_get_info
532  *
533  * Retrieves information about a symt (either symbol or type)
534  */
535 BOOL symt_get_info(struct module* module, const struct symt* type,
536                    IMAGEHLP_SYMBOL_TYPE_INFO req, void* pInfo)
537 {
538     unsigned            len;
539
540     if (!type) return FALSE;
541
542 /* helper to typecast pInfo to its expected type (_t) */
543 #define X(_t) (*((_t*)pInfo))
544
545     switch (req)
546     {
547     case TI_FINDCHILDREN:
548         {
549             const struct vector*        v;
550             struct symt**               pt;
551             unsigned                    i;
552             TI_FINDCHILDREN_PARAMS*     tifp = pInfo;
553
554             switch (type->tag)
555             {
556             case SymTagUDT:          v = &((const struct symt_udt*)type)->vchildren; break;
557             case SymTagEnum:         v = &((const struct symt_enum*)type)->vchildren; break;
558             case SymTagFunctionType: v = &((const struct symt_function_signature*)type)->vchildren; break;
559             case SymTagFunction:     v = &((const struct symt_function*)type)->vchildren; break;
560             default:
561                 FIXME("Unsupported sym-tag %s for find-children\n", 
562                       symt_get_tag_str(type->tag));
563                 return FALSE;
564             }
565             for (i = 0; i < tifp->Count; i++)
566             {
567                 if (!(pt = vector_at(v, tifp->Start + i))) return FALSE;
568                 tifp->ChildId[i] = symt_ptr2index(module, *pt);
569             }
570         }
571         break;
572
573     case TI_GET_ADDRESS:
574         return symt_get_address(type, (ULONG64*)pInfo);
575
576     case TI_GET_BASETYPE:
577         switch (type->tag)
578         {
579         case SymTagBaseType:
580             X(DWORD) = ((const struct symt_basic*)type)->bt;
581             break;
582         case SymTagEnum:
583             X(DWORD) = btInt;
584             break;
585         default:
586             return FALSE;
587         }
588         break;
589
590     case TI_GET_BITPOSITION:
591         if (type->tag == SymTagData &&
592             ((const struct symt_data*)type)->kind == DataIsMember &&
593             ((const struct symt_data*)type)->u.member.length != 0)
594             X(DWORD) = ((const struct symt_data*)type)->u.member.offset & 7;
595         else return FALSE;
596         break;
597
598     case TI_GET_CHILDRENCOUNT:
599         switch (type->tag)
600         {
601         case SymTagUDT:
602             X(DWORD) = vector_length(&((const struct symt_udt*)type)->vchildren);
603             break;
604         case SymTagEnum:
605             X(DWORD) = vector_length(&((const struct symt_enum*)type)->vchildren);
606             break;
607         case SymTagFunctionType:
608             X(DWORD) = vector_length(&((const struct symt_function_signature*)type)->vchildren);
609             break;
610         case SymTagFunction:
611             X(DWORD) = vector_length(&((const struct symt_function*)type)->vchildren);
612             break;
613         case SymTagPointerType: /* MS does it that way */
614         case SymTagArrayType: /* MS does it that way */
615         case SymTagThunk: /* MS does it that way */
616             X(DWORD) = 0;
617             break;
618         default:
619             FIXME("Unsupported sym-tag %s for get-children-count\n", 
620                   symt_get_tag_str(type->tag));
621             /* fall through */
622         case SymTagData:
623         case SymTagPublicSymbol:
624         case SymTagBaseType:
625             return FALSE;
626         }
627         break;
628
629     case TI_GET_COUNT:
630         switch (type->tag)
631         {
632         case SymTagArrayType:
633             X(DWORD) = symt_array_count(module, (const struct symt_array*)type);
634             break;
635         case SymTagFunctionType:
636             /* this seems to be wrong for (future) C++ methods, where 'this' parameter
637              * should be included in this value (and not in GET_CHILDREN_COUNT)
638              */
639             X(DWORD) = vector_length(&((const struct symt_function_signature*)type)->vchildren);
640             break;
641         default: return FALSE;
642         }
643         break;
644
645     case TI_GET_DATAKIND:
646         if (type->tag != SymTagData) return FALSE;
647         X(DWORD) = ((const struct symt_data*)type)->kind;
648         break;
649
650     case TI_GET_LENGTH:
651         switch (type->tag)
652         {
653         case SymTagBaseType:
654             X(DWORD64) = ((const struct symt_basic*)type)->size;
655             break;
656         case SymTagFunction:
657             X(DWORD64) = ((const struct symt_function*)type)->size;
658             break;
659         case SymTagPointerType:
660             X(DWORD64) = ((const struct symt_pointer*)type)->size;
661             break;
662         case SymTagUDT:
663             X(DWORD64) = ((const struct symt_udt*)type)->size;
664             break;
665         case SymTagEnum:
666             X(DWORD64) = sizeof(int); /* FIXME: should be size of base-type of enum !!! */
667             break;
668         case SymTagData:
669             if (((const struct symt_data*)type)->kind != DataIsMember ||
670                 !((const struct symt_data*)type)->u.member.length)
671                 return FALSE;
672             X(DWORD64) = ((const struct symt_data*)type)->u.member.length;
673             break;
674         case SymTagArrayType:
675             if (!symt_get_info(module, ((const struct symt_array*)type)->base_type,
676                                TI_GET_LENGTH, pInfo))
677                 return FALSE;
678             X(DWORD64) *= symt_array_count(module, (const struct symt_array*)type);
679             break;
680         case SymTagPublicSymbol:
681             X(DWORD64) = ((const struct symt_public*)type)->size;
682             break;
683         case SymTagTypedef:
684             return symt_get_info(module, ((const struct symt_typedef*)type)->type, TI_GET_LENGTH, pInfo);
685         case SymTagThunk:
686             X(DWORD64) = ((const struct symt_thunk*)type)->size;
687             break;
688         case SymTagLabel:
689             X(DWORD64) = 0;
690             break;
691         default:
692             FIXME("Unsupported sym-tag %s for get-length\n", 
693                   symt_get_tag_str(type->tag));
694             /* fall through */
695         case SymTagFunctionType:
696             return 0;
697         }
698         break;
699
700     case TI_GET_LEXICALPARENT:
701         switch (type->tag)
702         {
703         case SymTagBlock:
704             X(DWORD) = symt_ptr2index(module, ((const struct symt_block*)type)->container);
705             break;
706         case SymTagData:
707             X(DWORD) = symt_ptr2index(module, ((const struct symt_data*)type)->container);
708             break;
709         case SymTagFunction:
710             X(DWORD) = symt_ptr2index(module, ((const struct symt_function*)type)->container);
711             break;
712         case SymTagThunk:
713             X(DWORD) = symt_ptr2index(module, ((const struct symt_thunk*)type)->container);
714             break;
715         case SymTagFunctionArgType:
716             X(DWORD) = symt_ptr2index(module, ((const struct symt_function_arg_type*)type)->container);
717             break;
718         default:
719             FIXME("Unsupported sym-tag %s for get-lexical-parent\n", 
720                   symt_get_tag_str(type->tag));
721             return FALSE;
722         }
723         break;
724
725     case TI_GET_NESTED:
726         switch (type->tag)
727         {
728         case SymTagUDT:
729         case SymTagEnum:
730             X(DWORD) = 0;
731             break;
732         default:
733             return FALSE;
734         }
735         break;
736
737     case TI_GET_OFFSET:
738         switch (type->tag)
739         {
740         case SymTagData:
741             switch (((const struct symt_data*)type)->kind)
742             {
743             case DataIsParam:
744             case DataIsLocal:
745                 X(ULONG) = ((const struct symt_data*)type)->u.var.offset; 
746                 break;
747             case DataIsMember:
748                 X(ULONG) = ((const struct symt_data*)type)->u.member.offset >> 3; 
749                 break;
750             default:
751                 FIXME("Unknown kind (%u) for get-offset\n",     
752                       ((const struct symt_data*)type)->kind);
753                 return FALSE;
754             }
755             break;
756         default:
757             FIXME("Unsupported sym-tag %s for get-offset\n", 
758                   symt_get_tag_str(type->tag));
759             return FALSE;
760         }
761         break;
762
763     case TI_GET_SYMNAME:
764         {
765             const char* name = symt_get_name(type);
766             if (!name) return FALSE;
767             len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
768             X(WCHAR*) = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
769             if (!X(WCHAR*)) return FALSE;
770             MultiByteToWideChar(CP_ACP, 0, name, -1, X(WCHAR*), len);
771         }
772         break;
773
774     case TI_GET_SYMTAG:
775         X(DWORD) = type->tag;
776         break;
777
778     case TI_GET_TYPE:
779     case TI_GET_TYPEID:
780         switch (type->tag)
781         {
782             /* hierarchical => hierarchical */
783         case SymTagArrayType:
784             X(DWORD) = symt_ptr2index(module, ((const struct symt_array*)type)->base_type);
785             break;
786         case SymTagPointerType:
787             X(DWORD) = symt_ptr2index(module, ((const struct symt_pointer*)type)->pointsto);
788             break;
789         case SymTagFunctionType:
790             X(DWORD) = symt_ptr2index(module, ((const struct symt_function_signature*)type)->rettype);
791             break;
792         case SymTagTypedef:
793             X(DWORD) = symt_ptr2index(module, ((const struct symt_typedef*)type)->type);
794             break;
795             /* lexical => hierarchical */
796         case SymTagData:
797             X(DWORD) = symt_ptr2index(module, ((const struct symt_data*)type)->type);
798             break;
799         case SymTagFunction:
800             X(DWORD) = symt_ptr2index(module, ((const struct symt_function*)type)->type);
801             break;
802         case SymTagEnum:
803             X(DWORD) = symt_ptr2index(module, ((const struct symt_enum*)type)->base_type);
804             break;
805         case SymTagFunctionArgType:
806             X(DWORD) = symt_ptr2index(module, ((const struct symt_function_arg_type*)type)->arg_type);
807             break;
808         default:
809             FIXME("Unsupported sym-tag %s for get-type\n", 
810                   symt_get_tag_str(type->tag));
811         /* fall through */
812         case SymTagPublicSymbol:
813         case SymTagThunk:
814         case SymTagLabel:
815             return FALSE;
816         }
817         break;
818
819     case TI_GET_UDTKIND:
820         if (type->tag != SymTagUDT) return FALSE;
821         X(DWORD) = ((const struct symt_udt*)type)->kind;
822         break;
823
824     case TI_GET_VALUE:
825         if (type->tag != SymTagData) return FALSE;
826         switch (((const struct symt_data*)type)->kind)
827         {
828         case DataIsConstant: X(VARIANT) = ((const struct symt_data*)type)->u.value; break;
829         case DataIsLocal:
830         case DataIsParam:
831             {
832                 struct location loc = ((const struct symt_data*)type)->u.var;
833                 unsigned                i;
834                 struct module_format*   modfmt;
835
836                 if (loc.kind < loc_user) return FALSE;
837                 for (i = 0; i < DFI_LAST; i++)
838                 {
839                     modfmt = module->format_info[i];
840                     if (modfmt && modfmt->loc_compute)
841                     {
842                         modfmt->loc_compute(module->process, modfmt,
843                                             (const struct symt_function*)((const struct symt_data*)type)->container, &loc);
844                         break;
845                     }
846                 }
847                 if (loc.kind != loc_absolute) return FALSE;
848                 X(VARIANT).n1.n2.vt = VT_UI4; /* FIXME */
849                 X(VARIANT).n1.n2.n3.uiVal = loc.offset;
850             }
851             break;
852         default: return FALSE;
853         }
854         break;
855
856     case TI_GET_CALLING_CONVENTION:
857         if (type->tag != SymTagFunctionType) return FALSE;
858         if (((const struct symt_function_signature*)type)->call_conv == -1)
859         {
860             FIXME("No support for calling convention for this signature\n");
861             X(DWORD) = CV_CALL_FAR_C; /* FIXME */
862         }
863         else X(DWORD) = ((const struct symt_function_signature*)type)->call_conv;
864         break;
865     case TI_GET_ARRAYINDEXTYPEID:
866         if (type->tag != SymTagArrayType) return FALSE;
867         X(DWORD) = symt_ptr2index(module, ((const struct symt_array*)type)->index_type);
868         break;
869
870     case TI_GET_CLASSPARENTID:
871         /* FIXME: we don't support properly C++ for now, pretend this symbol doesn't
872          * belong to a parent class
873          */
874         return FALSE;
875
876 #undef X
877
878     case TI_GET_ADDRESSOFFSET:
879     case TI_GET_SYMINDEX:
880     case TI_GET_THISADJUST:
881     case TI_GET_VIRTUALBASECLASS:
882     case TI_GET_VIRTUALBASEPOINTEROFFSET:
883     case TI_GET_VIRTUALTABLESHAPEID:
884     case TI_IS_EQUIV_TO:
885         FIXME("Unsupported GetInfo request (%u)\n", req);
886         return FALSE;
887     default:
888         FIXME("Unknown GetInfo request (%u)\n", req);
889         return FALSE;
890     }
891
892     return TRUE;
893 }
894
895 /******************************************************************
896  *              SymGetTypeInfo (DBGHELP.@)
897  *
898  */
899 BOOL WINAPI SymGetTypeInfo(HANDLE hProcess, DWORD64 ModBase,
900                            ULONG TypeId, IMAGEHLP_SYMBOL_TYPE_INFO GetType,
901                            PVOID pInfo)
902 {
903     struct module_pair  pair;
904
905     pair.pcs = process_find_by_handle(hProcess);
906     if (!pair.pcs) return FALSE;
907
908     pair.requested = module_find_by_addr(pair.pcs, ModBase, DMT_UNKNOWN);
909     if (!module_get_debug(&pair))
910     {
911         FIXME("Someone didn't properly set ModBase (%s)\n", wine_dbgstr_longlong(ModBase));
912         return FALSE;
913     }
914
915     return symt_get_info(pair.effective, symt_index2ptr(pair.effective, TypeId), GetType, pInfo);
916 }
917
918 /******************************************************************
919  *              SymGetTypeFromName (DBGHELP.@)
920  *
921  */
922 BOOL WINAPI SymGetTypeFromName(HANDLE hProcess, ULONG64 BaseOfDll,
923                                PCSTR Name, PSYMBOL_INFO Symbol)
924 {
925     struct process*     pcs = process_find_by_handle(hProcess);
926     struct module_pair  pair;
927     struct symt*        type;
928
929     if (!pcs) return FALSE;
930     pair.requested = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
931     if (!module_get_debug(&pair)) return FALSE;
932     type = symt_find_type_by_name(pair.effective, SymTagNull, Name);
933     if (!type) return FALSE;
934     Symbol->TypeIndex = symt_ptr2index(pair.effective, type);
935
936     return TRUE;
937 }