- fixed some bugs in StackWalk (claimed for but forgotten in last
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 #include "config.h"
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <assert.h>
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winreg.h"
32 #include "winnls.h"
33 #include "wine/debug.h"
34 #include "dbghelp_private.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
37 WINE_DECLARE_DEBUG_CHANNEL(dbghelp_symt);
38
39 static const char* symt_get_tag_str(DWORD tag)
40 {
41     switch (tag)
42     {
43     case SymTagNull:                    return "SymTagNull";
44     case SymTagExe:                     return "SymTagExe";
45     case SymTagCompiland:               return "SymTagCompiland";
46     case SymTagCompilandDetails:        return "SymTagCompilandDetails";
47     case SymTagCompilandEnv:            return "SymTagCompilandEnv";
48     case SymTagFunction:                return "SymTagFunction";
49     case SymTagBlock:                   return "SymTagBlock";
50     case SymTagData:                    return "SymTagData";
51     case SymTagAnnotation:              return "SymTagAnnotation";
52     case SymTagLabel:                   return "SymTagLabel";
53     case SymTagPublicSymbol:            return "SymTagPublicSymbol";
54     case SymTagUDT:                     return "SymTagUDT";
55     case SymTagEnum:                    return "SymTagEnum";
56     case SymTagFunctionType:            return "SymTagFunctionType";
57     case SymTagPointerType:             return "SymTagPointerType";
58     case SymTagArrayType:               return "SymTagArrayType";
59     case SymTagBaseType:                return "SymTagBaseType";
60     case SymTagTypedef:                 return "SymTagTypedef,";
61     case SymTagBaseClass:               return "SymTagBaseClass";
62     case SymTagFriend:                  return "SymTagFriend";
63     case SymTagFunctionArgType:         return "SymTagFunctionArgType,";
64     case SymTagFuncDebugStart:          return "SymTagFuncDebugStart,";
65     case SymTagFuncDebugEnd:            return "SymTagFuncDebugEnd";
66     case SymTagUsingNamespace:          return "SymTagUsingNamespace,";
67     case SymTagVTableShape:             return "SymTagVTableShape";
68     case SymTagVTable:                  return "SymTagVTable";
69     case SymTagCustom:                  return "SymTagCustom";
70     case SymTagThunk:                   return "SymTagThunk";
71     case SymTagCustomType:              return "SymTagCustomType";
72     case SymTagManagedType:             return "SymTagManagedType";
73     case SymTagDimension:               return "SymTagDimension";
74     default:                            return "---";
75     }
76 }
77
78 const char* symt_get_name(const struct symt* sym)
79 {
80     switch (sym->tag)
81     {
82     /* lexical tree */
83     case SymTagData:            return ((struct symt_data*)sym)->hash_elt.name;
84     case SymTagFunction:        return ((struct symt_function*)sym)->hash_elt.name;
85     case SymTagPublicSymbol:    return ((struct symt_public*)sym)->hash_elt.name;
86     case SymTagBaseType:        return ((struct symt_basic*)sym)->hash_elt.name;
87     case SymTagLabel:           return ((struct symt_function_point*)sym)->name;
88     /* hierarchy tree */
89     case SymTagEnum:            return ((struct symt_enum*)sym)->name;
90     case SymTagTypedef:         return ((struct symt_typedef*)sym)->hash_elt.name;
91     case SymTagUDT:             return ((struct symt_udt*)sym)->hash_elt.name;
92     default:
93         FIXME("Unsupported sym-tag %s\n", symt_get_tag_str(sym->tag));
94         /* fall through */
95     case SymTagArrayType:
96     case SymTagPointerType:
97     case SymTagFunctionType:
98         return NULL;
99     }
100 }
101
102 static struct symt* symt_find_type_by_name(struct module* module, 
103                                            enum SymTagEnum sym_tag, 
104                                            const char* typename)
105 {
106     void*                       ptr;
107     struct symt_ht*             type;
108     struct hash_table_iter      hti;
109
110     assert(typename);
111     assert(module);
112
113     hash_table_iter_init(&module->ht_types, &hti, typename);
114     while ((ptr = hash_table_iter_up(&hti)))
115     {
116         type = GET_ENTRY(ptr, struct symt_ht, hash_elt);
117
118         if ((sym_tag == SymTagNull || type->symt.tag == sym_tag) &&
119             type->hash_elt.name && !strcmp(type->hash_elt.name, typename))
120             return &type->symt;
121     }
122     SetLastError(ERROR_INVALID_NAME); /* FIXME ?? */
123     return NULL;
124 }
125
126 struct symt_basic* symt_new_basic(struct module* module, enum BasicType bt, 
127                                   const char* typename, unsigned size)
128 {
129     struct symt_basic*          sym;
130
131     if (typename)
132     {
133         sym = (struct symt_basic*)symt_find_type_by_name(module, SymTagBaseType,
134                                                          typename);
135         if (sym && sym->bt == bt && sym->size == size)
136             return sym;
137     }
138     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
139     {
140         sym->symt.tag = SymTagBaseType;
141         if (typename)
142         {
143             sym->hash_elt.name = pool_strdup(&module->pool, typename);
144             hash_table_add(&module->ht_types, &sym->hash_elt);
145         } else sym->hash_elt.name = NULL;
146         sym->bt = bt;
147         sym->size = size;
148     }
149     return sym;
150 }
151
152 struct symt_udt* symt_new_udt(struct module* module, const char* typename, 
153                               unsigned size, enum UdtKind kind)
154 {
155     struct symt_udt*            sym;
156
157     TRACE_(dbghelp_symt)("Adding udt %s:%s\n", module->module.ModuleName, typename);
158     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
159     {
160         sym->symt.tag = SymTagUDT;
161         sym->kind     = kind;
162         sym->size     = size;
163         if (typename)
164         {
165             sym->hash_elt.name = pool_strdup(&module->pool, typename);
166             hash_table_add(&module->ht_types, &sym->hash_elt);
167         } else sym->hash_elt.name = NULL;
168         vector_init(&sym->vchildren, sizeof(struct symt*), 8);
169     }
170     return sym;
171 }
172
173 BOOL symt_set_udt_size(struct module* module, struct symt_udt* udt, unsigned size)
174 {
175     assert(udt->symt.tag == SymTagUDT);
176     if (vector_length(&udt->vchildren) != 0)
177     {
178         if (udt->size != size)
179             FIXME_(dbghelp_symt)("Changing size for %s from %u to %u\n", 
180                                  udt->hash_elt.name, udt->size, size);
181         return TRUE;
182     }
183     udt->size = size;
184     return TRUE;
185 }
186
187 /******************************************************************
188  *              symt_add_udt_element
189  *
190  * add an element to a udt (struct, class, union)
191  * the size & offset parameters are expressed in bits (not bytes) so that
192  * we can mix in the single call bytes aligned elements (regular fields) and
193  * the others (bit fields)
194  */
195 BOOL symt_add_udt_element(struct module* module, struct symt_udt* udt_type,
196                           const char* name, struct symt* elt_type,
197                           unsigned offset, unsigned size)
198 {
199     struct symt_data*   m;
200     struct symt**       p;
201
202     assert(udt_type->symt.tag == SymTagUDT);
203
204     TRACE_(dbghelp_symt)("Adding %s to UDT %s\n", name, udt_type->hash_elt.name);
205     p = NULL;
206     while ((p = vector_iter_up(&udt_type->vchildren, p)))
207     {
208         m = (struct symt_data*)*p;
209         assert(m);
210         assert(m->symt.tag == SymTagData);
211         if (m->hash_elt.name[0] == name[0] && strcmp(m->hash_elt.name, name) == 0)
212             return TRUE;
213     }
214
215     if ((m = pool_alloc(&module->pool, sizeof(*m))) == NULL) return FALSE;
216     memset(m, 0, sizeof(*m));
217     m->symt.tag      = SymTagData;
218     m->hash_elt.name = pool_strdup(&module->pool, name);
219     m->hash_elt.next = NULL;
220
221     m->kind          = DataIsMember;
222     m->container     = &udt_type->symt;
223     m->type          = elt_type;
224     m->u.s.offset    = offset;
225     m->u.s.length    = ((offset & 7) || (size & 7)) ? size : 0;
226     m->u.s.reg_id    = 0;
227     p = vector_add(&udt_type->vchildren, &module->pool);
228     *p = &m->symt;
229
230     return TRUE;
231 }
232
233 struct symt_enum* symt_new_enum(struct module* module, const char* typename)
234 {
235     struct symt_enum*   sym;
236
237     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
238     {
239         sym->symt.tag            = SymTagEnum;
240         sym->name = pool_strdup(&module->pool, typename);
241         vector_init(&sym->vchildren, sizeof(struct symt*), 8);
242     }
243     return sym;
244 }
245
246 BOOL symt_add_enum_element(struct module* module, struct symt_enum* enum_type,
247                            const char* name, int value)
248 {
249     struct symt_data*   e;
250     struct symt**       p;
251
252     assert(enum_type->symt.tag == SymTagEnum);
253     e = pool_alloc(&module->pool, sizeof(*e));
254     if (e == NULL) return FALSE;
255
256     e->symt.tag = SymTagData;
257     e->hash_elt.name = pool_strdup(&module->pool, name);
258     e->hash_elt.next = NULL;
259     e->kind = DataIsConstant;
260     e->container = &enum_type->symt;
261     /* CV defines the underlying type for the enumeration */
262     e->type = &symt_new_basic(module, btInt, "int", 4)->symt;
263     e->u.value.n1.n2.vt = VT_I4;
264     e->u.value.n1.n2.n3.lVal = value;
265
266     p = vector_add(&enum_type->vchildren, &module->pool);
267     if (!p) return FALSE; /* FIXME we leak e */
268     *p = &e->symt;
269
270     return TRUE;
271 }
272
273 struct symt_array* symt_new_array(struct module* module, int min, int max, 
274                                   struct symt* base)
275 {
276     struct symt_array*  sym;
277
278     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
279     {
280         sym->symt.tag  = SymTagArrayType;
281         sym->start     = min;
282         sym->end       = max;
283         sym->basetype  = base;
284     }
285     return sym;
286 }
287
288 struct symt_function_signature* symt_new_function_signature(struct module* module, 
289                                                             struct symt* ret_type)
290 {
291     struct symt_function_signature*     sym;
292
293     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
294     {
295         sym->symt.tag = SymTagFunctionType;
296         sym->rettype  = ret_type;
297         vector_init(&sym->vchildren, sizeof(struct symt*), 4);
298     }
299     return sym;
300 }
301
302 BOOL symt_add_function_signature_parameter(struct module* module,
303                                            struct symt_function_signature* sig_type,
304                                            struct symt* param)
305 {
306     struct symt**       p;
307
308     assert(sig_type->symt.tag == SymTagFunctionType);
309     p = vector_add(&sig_type->vchildren, &module->pool);
310     if (!p) return FALSE; /* FIXME we leak e */
311     *p = param;
312
313     return TRUE;
314 }
315
316 struct symt_pointer* symt_new_pointer(struct module* module, struct symt* ref_type)
317 {
318     struct symt_pointer*        sym;
319
320     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
321     {
322         sym->symt.tag = SymTagPointerType;
323         sym->pointsto = ref_type;
324     }
325     return sym;
326 }
327
328 struct symt_typedef* symt_new_typedef(struct module* module, struct symt* ref, 
329                                       const char* name)
330 {
331     struct symt_typedef* sym;
332
333     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
334     {
335         sym->symt.tag = SymTagTypedef;
336         sym->type     = ref;
337         sym->hash_elt.name = pool_strdup(&module->pool, name);
338         hash_table_add(&module->ht_types, &sym->hash_elt);
339     }
340     return sym;
341 }
342
343 /******************************************************************
344  *              SymEnumTypes (DBGHELP.@)
345  *
346  */
347 BOOL WINAPI SymEnumTypes(HANDLE hProcess, unsigned long BaseOfDll,
348                          PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
349                          void* UserContext)
350 {
351     struct process*             pcs;
352     struct module*              module;
353     struct symt_ht*             type;
354     void*                       ptr;
355     char                        buffer[sizeof(SYMBOL_INFO) + 256];
356     SYMBOL_INFO*                sym_info = (SYMBOL_INFO*)buffer;
357     struct hash_table_iter      hti;
358     const char*                 tmp;
359
360     TRACE("(%p %08lx %p %p)\n",
361           hProcess, BaseOfDll, EnumSymbolsCallback, UserContext);
362
363     pcs = process_find_by_handle(hProcess);
364     if (!pcs) return FALSE;
365     module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
366     if (!(module = module_get_debug(pcs, module))) return FALSE;
367
368     sym_info->SizeOfStruct = sizeof(SYMBOL_INFO);
369     sym_info->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO);
370
371     hash_table_iter_init(&module->ht_types, &hti, NULL);
372     while ((ptr = hash_table_iter_up(&hti)))
373     {
374         type = GET_ENTRY(ptr, struct symt_ht, hash_elt);
375         sym_info->TypeIndex = (DWORD)type;
376         sym_info->info = 0; /* FIXME */
377         symt_get_info(&type->symt, TI_GET_LENGTH, &sym_info->Size);
378         sym_info->ModBase = module->module.BaseOfImage;
379         sym_info->Flags = 0; /* FIXME */
380         sym_info->Value = 0; /* FIXME */
381         sym_info->Address = 0; /* FIXME */
382         sym_info->Register = 0; /* FIXME */
383         sym_info->Scope = 0; /* FIXME */
384         sym_info->Tag = type->symt.tag;
385         tmp = symt_get_name(&type->symt);
386         sym_info->NameLen = strlen(tmp) + 1;
387         strncpy(sym_info->Name, tmp, min(sym_info->NameLen, sym_info->MaxNameLen));
388         sym_info->Name[sym_info->MaxNameLen - 1] = '\0';
389         if (!EnumSymbolsCallback(sym_info, sym_info->Size, UserContext)) break;
390     }
391     return TRUE;
392 }
393
394 /******************************************************************
395  *              symt_get_info
396  *
397  * Retrieves inforamtion about a symt (either symbol or type)
398  */
399 BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req, 
400                    void* pInfo)
401 {
402     unsigned            len;
403
404     if (!type) return FALSE;
405
406 /* helper to typecast pInfo to its expected type (_t) */
407 #define X(_t) (*((_t*)pInfo))
408
409     switch (req)
410     {
411     case TI_FINDCHILDREN:
412         {
413             const struct vector*        v;
414             struct symt**               pt;
415             unsigned                    i;
416             TI_FINDCHILDREN_PARAMS*     tifp = pInfo;
417
418             switch (type->tag)
419             {
420             case SymTagUDT:          v = &((struct symt_udt*)type)->vchildren; break;
421             case SymTagEnum:         v = &((struct symt_enum*)type)->vchildren; break;
422             case SymTagFunctionType: v = &((struct symt_function_signature*)type)->vchildren; break;
423             case SymTagFunction:     v = &((struct symt_function*)type)->vchildren; break;
424             default:
425                 FIXME("Unsupported sym-tag %s for find-children\n", 
426                       symt_get_tag_str(type->tag));
427                 return FALSE;
428             }
429             for (i = 0; i < tifp->Count; i++)
430             {
431                 if (!(pt = vector_at(v, tifp->Start + i))) return FALSE;
432                 tifp->ChildId[i] = (DWORD)*pt;
433             }
434         }
435         break;
436
437     case TI_GET_ADDRESS:
438         switch (type->tag)
439         {
440         case SymTagData:
441             switch (((struct symt_data*)type)->kind)
442             {
443             case DataIsGlobal:
444             case DataIsFileStatic:
445                 X(DWORD) = ((struct symt_data*)type)->u.address;
446                 break;
447             default: return FALSE;
448             }
449             break;
450         case SymTagFunction:
451             X(DWORD) = ((struct symt_function*)type)->addr;
452             break;
453         case SymTagPublicSymbol:
454             X(DWORD) = ((struct symt_public*)type)->address;
455             break;
456         case SymTagFuncDebugStart:
457         case SymTagFuncDebugEnd:
458         case SymTagLabel:
459             X(DWORD) = ((struct symt_function_point*)type)->parent->addr + 
460                 ((struct symt_function_point*)type)->offset;
461             break;
462         default:
463             FIXME("Unsupported sym-tag %s for get-address\n", 
464                   symt_get_tag_str(type->tag));
465             return FALSE;
466         }
467         break;
468
469     case TI_GET_BASETYPE:
470         switch (type->tag)
471         {
472         case SymTagBaseType:
473             X(DWORD) = ((struct symt_basic*)type)->bt;
474             break;
475         case SymTagEnum:
476             X(DWORD) = btInt;
477             break;
478         default:
479             return FALSE;
480         }
481         break;
482
483     case TI_GET_BITPOSITION:
484         if (type->tag != SymTagData || 
485             ((struct symt_data*)type)->kind != DataIsMember ||
486             ((struct symt_data*)type)->u.s.length == 0)
487             return FALSE;
488         X(DWORD) = ((struct symt_data*)type)->u.s.offset & 7;
489         break;
490
491     case TI_GET_CHILDRENCOUNT:
492         switch (type->tag)
493         {
494         case SymTagUDT:
495             X(DWORD) = vector_length(&((struct symt_udt*)type)->vchildren);
496             break;
497         case SymTagEnum:
498             X(DWORD) = vector_length(&((struct symt_enum*)type)->vchildren);
499             break;
500         case SymTagFunctionType:
501             X(DWORD) = vector_length(&((struct symt_function_signature*)type)->vchildren);
502             break;
503         case SymTagFunction:
504             X(DWORD) = vector_length(&((struct symt_function*)type)->vchildren);
505             break;
506         case SymTagPointerType: /* MS does it that way */
507         case SymTagArrayType: /* MS does it that way */
508             X(DWORD) = 0;
509             break;
510         default:
511             FIXME("Unsupported sym-tag %s for get-children-count\n", 
512                   symt_get_tag_str(type->tag));
513             /* fall through */
514         case SymTagData:
515         case SymTagPublicSymbol:
516         case SymTagBaseType:
517             return FALSE;
518         }
519         break;
520
521     case TI_GET_COUNT:
522         /* it seems that FunctionType also react to GET_COUNT (same value as
523          * GET_CHILDREN_COUNT ?, except for C++ methods, where it seems to
524          * also include 'this' (GET_CHILDREN_COUNT+1)
525          */
526         if (type->tag != SymTagArrayType) return FALSE;
527         X(DWORD) = ((struct symt_array*)type)->end - 
528             ((struct symt_array*)type)->start;
529         break;
530
531     case TI_GET_DATAKIND:
532         if (type->tag != SymTagData) return FALSE;
533         X(DWORD) = ((struct symt_data*)type)->kind;
534         break;
535
536     case TI_GET_LENGTH:
537         switch (type->tag)
538         {
539         case SymTagBaseType:
540             X(DWORD) = ((struct symt_basic*)type)->size;
541             break;
542         case SymTagFunction:
543             X(DWORD) = ((struct symt_function*)type)->size;
544             break;
545         case SymTagPointerType:
546             X(DWORD) = sizeof(void*);
547             break;
548         case SymTagUDT:
549             X(DWORD) = ((struct symt_udt*)type)->size;
550             break;
551         case SymTagEnum:
552             X(DWORD) = sizeof(int); /* FIXME: should be size of base-type of enum !!! */
553             break;
554         case SymTagData:
555             if (((struct symt_data*)type)->kind != DataIsMember ||
556                 !((struct symt_data*)type)->u.s.length)
557                 return FALSE;
558             X(DWORD) = ((struct symt_data*)type)->u.s.length;
559             break;
560         case SymTagArrayType:   
561             if (!symt_get_info(((struct symt_array*)type)->basetype, 
562                                TI_GET_LENGTH, pInfo))
563                 return FALSE;
564             X(DWORD) *= ((struct symt_array*)type)->end - 
565                 ((struct symt_array*)type)->start;
566             break;
567         case SymTagPublicSymbol:
568             X(DWORD) = ((struct symt_public*)type)->size;
569             break;
570         case SymTagTypedef:
571             return symt_get_info(((struct symt_typedef*)type)->type, TI_GET_LENGTH, pInfo);
572             break;
573         default:
574             FIXME("Unsupported sym-tag %s for get-length\n", 
575                   symt_get_tag_str(type->tag));
576             return 0;
577         }
578         break;
579
580     case TI_GET_LEXICALPARENT:
581         switch (type->tag)
582         {
583         case SymTagBlock:
584             X(DWORD) = (DWORD)((struct symt_block*)type)->container;
585             break;
586         case SymTagData:
587             X(DWORD) = (DWORD)((struct symt_data*)type)->container;
588             break;
589         default:
590             FIXME("Unsupported sym-tag %s for get-lexical-parent\n", 
591                   symt_get_tag_str(type->tag));
592             return FALSE;
593         }
594         break;
595
596     case TI_GET_NESTED:
597         switch (type->tag)
598         {
599         case SymTagUDT:
600         case SymTagEnum:
601             X(DWORD) = 0;
602             break;
603         default:
604             return FALSE;
605         }
606         break;
607
608     case TI_GET_OFFSET:
609         switch (type->tag)
610         {
611         case SymTagData:
612             switch (((struct symt_data*)type)->kind)
613             {
614             case DataIsParam:
615             case DataIsLocal:
616             case DataIsMember:
617                 X(ULONG) = ((struct symt_data*)type)->u.s.offset >> 3; 
618                 break;
619             default:
620                 FIXME("Unknown kind (%u) for get-offset\n",     
621                       ((struct symt_data*)type)->kind);
622                 return FALSE;
623             }
624             break;
625         default:
626             FIXME("Unsupported sym-tag %s for get-offset\n", 
627                   symt_get_tag_str(type->tag));
628             return FALSE;
629         }
630         break;
631
632     case TI_GET_SYMNAME:
633         {
634             const char* name = symt_get_name(type);
635             if (!name) return FALSE;
636             len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
637             X(WCHAR*) = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
638             if (!X(WCHAR*)) return FALSE;
639             MultiByteToWideChar(CP_ACP, 0, name, -1, X(WCHAR*), len);
640         }
641         break;
642
643     case TI_GET_SYMTAG:
644         X(DWORD) = type->tag;
645         break;
646
647     case TI_GET_TYPE:
648     case TI_GET_TYPEID:
649         switch (type->tag)
650         {
651             /* hierarchical => hierarchical */
652         case SymTagArrayType:
653             X(DWORD) = (DWORD)((struct symt_array*)type)->basetype;
654             break;
655         case SymTagPointerType:
656             X(DWORD) = (DWORD)((struct symt_pointer*)type)->pointsto;
657             break;
658         case SymTagFunctionType:
659             X(DWORD) = (DWORD)((struct symt_function_signature*)type)->rettype;
660             break;
661         case SymTagTypedef:
662             X(DWORD) = (DWORD)((struct symt_typedef*)type)->type;
663             break;
664             /* lexical => hierarchical */
665         case SymTagData:
666             X(DWORD) = (DWORD)((struct symt_data*)type)->type; 
667             break;
668         case SymTagFunction:
669             X(DWORD) = (DWORD)((struct symt_function*)type)->type;
670             break;
671             /* FIXME: should also work for enums and FunctionArgType */
672         default:
673             FIXME("Unsupported sym-tag %s for get-type\n", 
674                   symt_get_tag_str(type->tag));
675             return FALSE;
676         }
677         break;
678
679     case TI_GET_UDTKIND:
680         if (type->tag != SymTagUDT) return FALSE;
681         X(DWORD) = ((struct symt_udt*)type)->kind;
682         break;
683
684     case TI_GET_VALUE:
685         if (type->tag != SymTagData || ((struct symt_data*)type)->kind != DataIsConstant)
686             return FALSE;
687         X(VARIANT) = ((struct symt_data*)type)->u.value;
688         break;
689
690 #undef X
691
692     case TI_GET_ADDRESSOFFSET:
693     case TI_GET_ARRAYINDEXTYPEID:
694     case TI_GET_CALLING_CONVENTION:
695     case TI_GET_CLASSPARENTID:
696     case TI_GET_SYMINDEX:
697     case TI_GET_THISADJUST:
698     case TI_GET_VIRTUALBASECLASS:
699     case TI_GET_VIRTUALBASEPOINTEROFFSET:
700     case TI_GET_VIRTUALTABLESHAPEID:
701     case TI_IS_EQUIV_TO:
702         FIXME("Unsupported GetInfo request (%u)\n", req);
703         return FALSE;
704     }
705
706     return TRUE;
707 }
708
709 /******************************************************************
710  *              SymGetTypeInfo (DBGHELP.@)
711  *
712  */
713 BOOL WINAPI SymGetTypeInfo(HANDLE hProcess, unsigned long ModBase,
714                            ULONG TypeId, IMAGEHLP_SYMBOL_TYPE_INFO GetType,
715                            PVOID pInfo)
716 {
717     struct process*     pcs = process_find_by_handle(hProcess);
718
719     if (!pcs) return FALSE;
720 #if 0
721     struct module*      module;
722     module = module_find_by_addr(pcs, ModBase, DMT_UNKNOWN);
723     if (!(module = module_get_debug(pcs, module))) return FALSE;
724 #endif
725
726     return symt_get_info((struct symt*)TypeId, GetType, pInfo);
727 }
728
729 /******************************************************************
730  *              SymGetTypeFromName (DBGHELP.@)
731  *
732  */
733 BOOL WINAPI SymGetTypeFromName(HANDLE hProcess, unsigned long BaseOfDll,
734                                LPSTR Name, PSYMBOL_INFO Symbol)
735 {
736     struct process*     pcs = process_find_by_handle(hProcess);
737     struct module*      module;
738     struct symt*        type;
739
740     if (!pcs) return FALSE;
741     module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
742     if (!module) return FALSE;
743     type = symt_find_type_by_name(module, SymTagNull, Name);
744     if (!type) return FALSE;
745     Symbol->TypeIndex = (DWORD)type;
746
747     return TRUE;
748 }