Added stub for CreateRemoteThread().
[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 ((const struct symt_data*)sym)->hash_elt.name;
84     case SymTagFunction:        return ((const struct symt_function*)sym)->hash_elt.name;
85     case SymTagPublicSymbol:    return ((const struct symt_public*)sym)->hash_elt.name;
86     case SymTagBaseType:        return ((const struct symt_basic*)sym)->hash_elt.name;
87     case SymTagLabel:           return ((const struct symt_function_point*)sym)->name;
88     case SymTagThunk:           return ((const struct symt_thunk*)sym)->hash_elt.name;
89     /* hierarchy tree */
90     case SymTagEnum:            return ((const struct symt_enum*)sym)->name;
91     case SymTagTypedef:         return ((const struct symt_typedef*)sym)->hash_elt.name;
92     case SymTagUDT:             return ((const struct symt_udt*)sym)->hash_elt.name;
93     default:
94         FIXME("Unsupported sym-tag %s\n", symt_get_tag_str(sym->tag));
95         /* fall through */
96     case SymTagArrayType:
97     case SymTagPointerType:
98     case SymTagFunctionType:
99         return NULL;
100     }
101 }
102
103 static struct symt* symt_find_type_by_name(struct module* module, 
104                                            enum SymTagEnum sym_tag, 
105                                            const char* typename)
106 {
107     void*                       ptr;
108     struct symt_ht*             type;
109     struct hash_table_iter      hti;
110
111     assert(typename);
112     assert(module);
113
114     hash_table_iter_init(&module->ht_types, &hti, typename);
115     while ((ptr = hash_table_iter_up(&hti)))
116     {
117         type = GET_ENTRY(ptr, struct symt_ht, hash_elt);
118
119         if ((sym_tag == SymTagNull || type->symt.tag == sym_tag) &&
120             type->hash_elt.name && !strcmp(type->hash_elt.name, typename))
121             return &type->symt;
122     }
123     SetLastError(ERROR_INVALID_NAME); /* FIXME ?? */
124     return NULL;
125 }
126
127 struct symt_basic* symt_new_basic(struct module* module, enum BasicType bt, 
128                                   const char* typename, unsigned size)
129 {
130     struct symt_basic*          sym;
131
132     if (typename)
133     {
134         sym = (struct symt_basic*)symt_find_type_by_name(module, SymTagBaseType,
135                                                          typename);
136         if (sym && sym->bt == bt && sym->size == size)
137             return sym;
138     }
139     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
140     {
141         sym->symt.tag = SymTagBaseType;
142         if (typename)
143         {
144             sym->hash_elt.name = pool_strdup(&module->pool, typename);
145             hash_table_add(&module->ht_types, &sym->hash_elt);
146         } else sym->hash_elt.name = NULL;
147         sym->bt = bt;
148         sym->size = size;
149     }
150     return sym;
151 }
152
153 struct symt_udt* symt_new_udt(struct module* module, const char* typename, 
154                               unsigned size, enum UdtKind kind)
155 {
156     struct symt_udt*            sym;
157
158     TRACE_(dbghelp_symt)("Adding udt %s:%s\n", module->module.ModuleName, typename);
159     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
160     {
161         sym->symt.tag = SymTagUDT;
162         sym->kind     = kind;
163         sym->size     = size;
164         if (typename)
165         {
166             sym->hash_elt.name = pool_strdup(&module->pool, typename);
167             hash_table_add(&module->ht_types, &sym->hash_elt);
168         } else sym->hash_elt.name = NULL;
169         vector_init(&sym->vchildren, sizeof(struct symt*), 8);
170     }
171     return sym;
172 }
173
174 BOOL symt_set_udt_size(struct module* module, struct symt_udt* udt, unsigned size)
175 {
176     assert(udt->symt.tag == SymTagUDT);
177     if (vector_length(&udt->vchildren) != 0)
178     {
179         if (udt->size != size)
180             FIXME_(dbghelp_symt)("Changing size for %s from %u to %u\n", 
181                                  udt->hash_elt.name, udt->size, size);
182         return TRUE;
183     }
184     udt->size = size;
185     return TRUE;
186 }
187
188 /******************************************************************
189  *              symt_add_udt_element
190  *
191  * add an element to a udt (struct, class, union)
192  * the size & offset parameters are expressed in bits (not bytes) so that
193  * we can mix in the single call bytes aligned elements (regular fields) and
194  * the others (bit fields)
195  */
196 BOOL symt_add_udt_element(struct module* module, struct symt_udt* udt_type,
197                           const char* name, struct symt* elt_type,
198                           unsigned offset, unsigned size)
199 {
200     struct symt_data*   m;
201     struct symt**       p;
202
203     assert(udt_type->symt.tag == SymTagUDT);
204
205     TRACE_(dbghelp_symt)("Adding %s to UDT %s\n", name, udt_type->hash_elt.name);
206     p = NULL;
207     while ((p = vector_iter_up(&udt_type->vchildren, p)))
208     {
209         m = (struct symt_data*)*p;
210         assert(m);
211         assert(m->symt.tag == SymTagData);
212         if (m->hash_elt.name[0] == name[0] && strcmp(m->hash_elt.name, name) == 0)
213             return TRUE;
214     }
215
216     if ((m = pool_alloc(&module->pool, sizeof(*m))) == NULL) return FALSE;
217     memset(m, 0, sizeof(*m));
218     m->symt.tag      = SymTagData;
219     m->hash_elt.name = pool_strdup(&module->pool, name);
220     m->hash_elt.next = NULL;
221
222     m->kind          = DataIsMember;
223     m->container     = &udt_type->symt;
224     m->type          = elt_type;
225     m->u.s.offset    = offset;
226     m->u.s.length    = ((offset & 7) || (size & 7)) ? size : 0;
227     m->u.s.reg_id    = 0;
228     p = vector_add(&udt_type->vchildren, &module->pool);
229     *p = &m->symt;
230
231     return TRUE;
232 }
233
234 struct symt_enum* symt_new_enum(struct module* module, const char* typename)
235 {
236     struct symt_enum*   sym;
237
238     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
239     {
240         sym->symt.tag            = SymTagEnum;
241         sym->name = (typename) ? pool_strdup(&module->pool, typename) : NULL;
242         vector_init(&sym->vchildren, sizeof(struct symt*), 8);
243     }
244     return sym;
245 }
246
247 BOOL symt_add_enum_element(struct module* module, struct symt_enum* enum_type,
248                            const char* name, int value)
249 {
250     struct symt_data*   e;
251     struct symt**       p;
252
253     assert(enum_type->symt.tag == SymTagEnum);
254     e = pool_alloc(&module->pool, sizeof(*e));
255     if (e == NULL) return FALSE;
256
257     e->symt.tag = SymTagData;
258     e->hash_elt.name = pool_strdup(&module->pool, name);
259     e->hash_elt.next = NULL;
260     e->kind = DataIsConstant;
261     e->container = &enum_type->symt;
262     /* CV defines the underlying type for the enumeration */
263     e->type = &symt_new_basic(module, btInt, "int", 4)->symt;
264     e->u.value.n1.n2.vt = VT_I4;
265     e->u.value.n1.n2.n3.lVal = value;
266
267     p = vector_add(&enum_type->vchildren, &module->pool);
268     if (!p) return FALSE; /* FIXME we leak e */
269     *p = &e->symt;
270
271     return TRUE;
272 }
273
274 struct symt_array* symt_new_array(struct module* module, int min, int max, 
275                                   struct symt* base)
276 {
277     struct symt_array*  sym;
278
279     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
280     {
281         sym->symt.tag  = SymTagArrayType;
282         sym->start     = min;
283         sym->end       = max;
284         sym->basetype  = base;
285     }
286     return sym;
287 }
288
289 struct symt_function_signature* symt_new_function_signature(struct module* module, 
290                                                             struct symt* ret_type)
291 {
292     struct symt_function_signature*     sym;
293
294     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
295     {
296         sym->symt.tag = SymTagFunctionType;
297         sym->rettype  = ret_type;
298         vector_init(&sym->vchildren, sizeof(struct symt*), 4);
299     }
300     return sym;
301 }
302
303 BOOL symt_add_function_signature_parameter(struct module* module,
304                                            struct symt_function_signature* sig_type,
305                                            struct symt* param)
306 {
307     struct symt**       p;
308
309     assert(sig_type->symt.tag == SymTagFunctionType);
310     p = vector_add(&sig_type->vchildren, &module->pool);
311     if (!p) return FALSE; /* FIXME we leak e */
312     *p = param;
313
314     return TRUE;
315 }
316
317 struct symt_pointer* symt_new_pointer(struct module* module, struct symt* ref_type)
318 {
319     struct symt_pointer*        sym;
320
321     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
322     {
323         sym->symt.tag = SymTagPointerType;
324         sym->pointsto = ref_type;
325     }
326     return sym;
327 }
328
329 struct symt_typedef* symt_new_typedef(struct module* module, struct symt* ref, 
330                                       const char* name)
331 {
332     struct symt_typedef* sym;
333
334     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
335     {
336         sym->symt.tag = SymTagTypedef;
337         sym->type     = ref;
338         sym->hash_elt.name = pool_strdup(&module->pool, name);
339         hash_table_add(&module->ht_types, &sym->hash_elt);
340     }
341     return sym;
342 }
343
344 /******************************************************************
345  *              SymEnumTypes (DBGHELP.@)
346  *
347  */
348 BOOL WINAPI SymEnumTypes(HANDLE hProcess, unsigned long BaseOfDll,
349                          PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
350                          void* UserContext)
351 {
352     struct process*             pcs;
353     struct module*              module;
354     struct symt_ht*             type;
355     void*                       ptr;
356     char                        buffer[sizeof(SYMBOL_INFO) + 256];
357     SYMBOL_INFO*                sym_info = (SYMBOL_INFO*)buffer;
358     struct hash_table_iter      hti;
359     const char*                 tmp;
360
361     TRACE("(%p %08lx %p %p)\n",
362           hProcess, BaseOfDll, EnumSymbolsCallback, UserContext);
363
364     if (!(pcs = process_find_by_handle(hProcess))) 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 = &((const struct symt_udt*)type)->vchildren; break;
421             case SymTagEnum:         v = &((const struct symt_enum*)type)->vchildren; break;
422             case SymTagFunctionType: v = &((const struct symt_function_signature*)type)->vchildren; break;
423             case SymTagFunction:     v = &((const 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 (((const struct symt_data*)type)->kind)
442             {
443             case DataIsGlobal:
444             case DataIsFileStatic:
445                 X(DWORD) = ((const struct symt_data*)type)->u.address;
446                 break;
447             default: return FALSE;
448             }
449             break;
450         case SymTagFunction:
451             X(DWORD) = ((const struct symt_function*)type)->address;
452             break;
453         case SymTagPublicSymbol:
454             X(DWORD) = ((const struct symt_public*)type)->address;
455             break;
456         case SymTagFuncDebugStart:
457         case SymTagFuncDebugEnd:
458         case SymTagLabel:
459             X(DWORD) = ((const struct symt_function_point*)type)->parent->address + 
460                 ((const struct symt_function_point*)type)->offset;
461             break;
462         case SymTagThunk:
463             X(DWORD) = ((const struct symt_thunk*)type)->address;
464             break;
465         default:
466             FIXME("Unsupported sym-tag %s for get-address\n", 
467                   symt_get_tag_str(type->tag));
468             return FALSE;
469         }
470         break;
471
472     case TI_GET_BASETYPE:
473         switch (type->tag)
474         {
475         case SymTagBaseType:
476             X(DWORD) = ((const struct symt_basic*)type)->bt;
477             break;
478         case SymTagEnum:
479             X(DWORD) = btInt;
480             break;
481         default:
482             return FALSE;
483         }
484         break;
485
486     case TI_GET_BITPOSITION:
487         if (type->tag != SymTagData || 
488             ((const struct symt_data*)type)->kind != DataIsMember ||
489             ((const struct symt_data*)type)->u.s.length == 0)
490             return FALSE;
491         X(DWORD) = ((const struct symt_data*)type)->u.s.offset & 7;
492         break;
493
494     case TI_GET_CHILDRENCOUNT:
495         switch (type->tag)
496         {
497         case SymTagUDT:
498             X(DWORD) = vector_length(&((const struct symt_udt*)type)->vchildren);
499             break;
500         case SymTagEnum:
501             X(DWORD) = vector_length(&((const struct symt_enum*)type)->vchildren);
502             break;
503         case SymTagFunctionType:
504             X(DWORD) = vector_length(&((const struct symt_function_signature*)type)->vchildren);
505             break;
506         case SymTagFunction:
507             X(DWORD) = vector_length(&((const struct symt_function*)type)->vchildren);
508             break;
509         case SymTagPointerType: /* MS does it that way */
510         case SymTagArrayType: /* MS does it that way */
511         case SymTagThunk: /* MS does it that way */
512             X(DWORD) = 0;
513             break;
514         default:
515             FIXME("Unsupported sym-tag %s for get-children-count\n", 
516                   symt_get_tag_str(type->tag));
517             /* fall through */
518         case SymTagData:
519         case SymTagPublicSymbol:
520         case SymTagBaseType:
521             return FALSE;
522         }
523         break;
524
525     case TI_GET_COUNT:
526         /* it seems that FunctionType also react to GET_COUNT (same value as
527          * GET_CHILDREN_COUNT ?, except for C++ methods, where it seems to
528          * also include 'this' (GET_CHILDREN_COUNT+1)
529          */
530         if (type->tag != SymTagArrayType) return FALSE;
531         X(DWORD) = ((const struct symt_array*)type)->end - 
532             ((const struct symt_array*)type)->start + 1;
533         break;
534
535     case TI_GET_DATAKIND:
536         if (type->tag != SymTagData) return FALSE;
537         X(DWORD) = ((const struct symt_data*)type)->kind;
538         break;
539
540     case TI_GET_LENGTH:
541         switch (type->tag)
542         {
543         case SymTagBaseType:
544             X(DWORD) = ((const struct symt_basic*)type)->size;
545             break;
546         case SymTagFunction:
547             X(DWORD) = ((const struct symt_function*)type)->size;
548             break;
549         case SymTagPointerType:
550             X(DWORD) = sizeof(void*);
551             break;
552         case SymTagUDT:
553             X(DWORD) = ((const struct symt_udt*)type)->size;
554             break;
555         case SymTagEnum:
556             X(DWORD) = sizeof(int); /* FIXME: should be size of base-type of enum !!! */
557             break;
558         case SymTagData:
559             if (((const struct symt_data*)type)->kind != DataIsMember ||
560                 !((const struct symt_data*)type)->u.s.length)
561                 return FALSE;
562             X(DWORD) = ((const struct symt_data*)type)->u.s.length;
563             break;
564         case SymTagArrayType:   
565             if (!symt_get_info(((const struct symt_array*)type)->basetype, 
566                                TI_GET_LENGTH, pInfo))
567                 return FALSE;
568             X(DWORD) *= ((const struct symt_array*)type)->end - 
569                 ((const struct symt_array*)type)->start + 1;
570             break;
571         case SymTagPublicSymbol:
572             X(DWORD) = ((const struct symt_public*)type)->size;
573             break;
574         case SymTagTypedef:
575             return symt_get_info(((const struct symt_typedef*)type)->type, TI_GET_LENGTH, pInfo);
576             break;
577         case SymTagThunk:
578             X(DWORD) = ((const struct symt_thunk*)type)->size;
579             break;
580         default:
581             FIXME("Unsupported sym-tag %s for get-length\n", 
582                   symt_get_tag_str(type->tag));
583             return 0;
584         }
585         break;
586
587     case TI_GET_LEXICALPARENT:
588         switch (type->tag)
589         {
590         case SymTagBlock:
591             X(DWORD) = (DWORD)((const struct symt_block*)type)->container;
592             break;
593         case SymTagData:
594             X(DWORD) = (DWORD)((const struct symt_data*)type)->container;
595             break;
596         case SymTagFunction:
597             X(DWORD) = (DWORD)((const struct symt_function*)type)->container;
598             break;
599         case SymTagThunk:
600             X(DWORD) = (DWORD)((const struct symt_thunk*)type)->container;
601             break;
602         default:
603             FIXME("Unsupported sym-tag %s for get-lexical-parent\n", 
604                   symt_get_tag_str(type->tag));
605             return FALSE;
606         }
607         break;
608
609     case TI_GET_NESTED:
610         switch (type->tag)
611         {
612         case SymTagUDT:
613         case SymTagEnum:
614             X(DWORD) = 0;
615             break;
616         default:
617             return FALSE;
618         }
619         break;
620
621     case TI_GET_OFFSET:
622         switch (type->tag)
623         {
624         case SymTagData:
625             switch (((const struct symt_data*)type)->kind)
626             {
627             case DataIsParam:
628             case DataIsLocal:
629             case DataIsMember:
630                 X(ULONG) = ((const struct symt_data*)type)->u.s.offset >> 3; 
631                 break;
632             default:
633                 FIXME("Unknown kind (%u) for get-offset\n",     
634                       ((const struct symt_data*)type)->kind);
635                 return FALSE;
636             }
637             break;
638         default:
639             FIXME("Unsupported sym-tag %s for get-offset\n", 
640                   symt_get_tag_str(type->tag));
641             return FALSE;
642         }
643         break;
644
645     case TI_GET_SYMNAME:
646         {
647             const char* name = symt_get_name(type);
648             if (!name) return FALSE;
649             len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
650             X(WCHAR*) = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
651             if (!X(WCHAR*)) return FALSE;
652             MultiByteToWideChar(CP_ACP, 0, name, -1, X(WCHAR*), len);
653         }
654         break;
655
656     case TI_GET_SYMTAG:
657         X(DWORD) = type->tag;
658         break;
659
660     case TI_GET_TYPE:
661     case TI_GET_TYPEID:
662         switch (type->tag)
663         {
664             /* hierarchical => hierarchical */
665         case SymTagArrayType:
666             X(DWORD) = (DWORD)((const struct symt_array*)type)->basetype;
667             break;
668         case SymTagPointerType:
669             X(DWORD) = (DWORD)((const struct symt_pointer*)type)->pointsto;
670             break;
671         case SymTagFunctionType:
672             X(DWORD) = (DWORD)((const struct symt_function_signature*)type)->rettype;
673             break;
674         case SymTagTypedef:
675             X(DWORD) = (DWORD)((const struct symt_typedef*)type)->type;
676             break;
677             /* lexical => hierarchical */
678         case SymTagData:
679             X(DWORD) = (DWORD)((const struct symt_data*)type)->type; 
680             break;
681         case SymTagFunction:
682             X(DWORD) = (DWORD)((const struct symt_function*)type)->type;
683             break;
684             /* FIXME: should also work for enums and FunctionArgType */
685         default:
686             FIXME("Unsupported sym-tag %s for get-type\n", 
687                   symt_get_tag_str(type->tag));
688         case SymTagThunk:
689             return FALSE;
690         }
691         break;
692
693     case TI_GET_UDTKIND:
694         if (type->tag != SymTagUDT) return FALSE;
695         X(DWORD) = ((const struct symt_udt*)type)->kind;
696         break;
697
698     case TI_GET_VALUE:
699         if (type->tag != SymTagData || ((const struct symt_data*)type)->kind != DataIsConstant)
700             return FALSE;
701         X(VARIANT) = ((const struct symt_data*)type)->u.value;
702         break;
703
704 #undef X
705
706     case TI_GET_ADDRESSOFFSET:
707     case TI_GET_ARRAYINDEXTYPEID:
708     case TI_GET_CALLING_CONVENTION:
709     case TI_GET_CLASSPARENTID:
710     case TI_GET_SYMINDEX:
711     case TI_GET_THISADJUST:
712     case TI_GET_VIRTUALBASECLASS:
713     case TI_GET_VIRTUALBASEPOINTEROFFSET:
714     case TI_GET_VIRTUALTABLESHAPEID:
715     case TI_IS_EQUIV_TO:
716         FIXME("Unsupported GetInfo request (%u)\n", req);
717         return FALSE;
718     }
719
720     return TRUE;
721 }
722
723 /******************************************************************
724  *              SymGetTypeInfo (DBGHELP.@)
725  *
726  */
727 BOOL WINAPI SymGetTypeInfo(HANDLE hProcess, unsigned long ModBase,
728                            ULONG TypeId, IMAGEHLP_SYMBOL_TYPE_INFO GetType,
729                            PVOID pInfo)
730 {
731     struct process*     pcs = process_find_by_handle(hProcess);
732     struct module*      module;
733
734     if (!pcs) return FALSE;
735
736     module = module_find_by_addr(pcs, ModBase, DMT_UNKNOWN);
737     if (!(module = module_get_debug(pcs, module)))
738     {
739         FIXME("Someone didn't properly set ModBase (0x%08lx)\n", ModBase);
740         return FALSE;
741     }
742
743     return symt_get_info((struct symt*)TypeId, GetType, pInfo);
744 }
745
746 /******************************************************************
747  *              SymGetTypeFromName (DBGHELP.@)
748  *
749  */
750 BOOL WINAPI SymGetTypeFromName(HANDLE hProcess, unsigned long BaseOfDll,
751                                LPSTR Name, PSYMBOL_INFO Symbol)
752 {
753     struct process*     pcs = process_find_by_handle(hProcess);
754     struct module*      module;
755     struct symt*        type;
756
757     if (!pcs) return FALSE;
758     module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
759     if (!module) return FALSE;
760     type = symt_find_type_by_name(module, SymTagNull, Name);
761     if (!type) return FALSE;
762     Symbol->TypeIndex = (DWORD)type;
763
764     return TRUE;
765 }