comctl32: A couple fixes for tab icon offsets.
[wine] / programs / winedbg / types.c
1 /*
2  * File types.c - datatype handling stuff for internal debugger.
3  *
4  * Copyright (C) 1997, Eric Youngdale.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * Note: This really doesn't do much at the moment, but it forms the framework
21  * upon which full support for datatype handling will eventually be built.
22  */
23
24 #include "config.h"
25 #include <stdlib.h>
26
27 #include "debugger.h"
28 #include "wine/debug.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
31
32 /******************************************************************
33  *              types_extract_as_integer
34  *
35  * Given a lvalue, try to get an integral (or pointer/address) value
36  * out of it
37  */
38 long int types_extract_as_integer(const struct dbg_lvalue* lvalue)
39 {
40     long int            rtn = 0;
41     LONGLONG            val;
42     DWORD               tag, bt;
43     DWORD64             size;
44
45     if (lvalue->type.id == dbg_itype_none ||
46         !types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag))
47         return 0;
48
49     if (lvalue->type.id == dbg_itype_segptr)
50     {
51         return (long int)memory_to_linear_addr(&lvalue->addr);
52     }
53
54     switch (tag)
55     {
56     case SymTagBaseType:
57         if (!types_get_info(&lvalue->type, TI_GET_LENGTH, &size) ||
58             !types_get_info(&lvalue->type, TI_GET_BASETYPE, &bt))
59         {
60             WINE_ERR("Couldn't get information\n");
61             RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
62         }
63         if (size > sizeof(rtn))
64         {
65             WINE_ERR("Size too large (%s)\n", wine_dbgstr_longlong(size));
66             return 0;
67         }
68         switch (bt)
69         {
70         case btChar:
71         case btInt:
72             if (!be_cpu->fetch_integer(lvalue, (unsigned)size, TRUE, &val)) return 0;
73             rtn = (long)val;
74             break;
75         case btUInt:
76             if (!be_cpu->fetch_integer(lvalue, (unsigned)size, FALSE, &val)) return 0;
77             rtn = (DWORD)(DWORD64)val;
78             break;
79         case btFloat:
80             RaiseException(DEBUG_STATUS_NOT_AN_INTEGER, 0, 0, NULL);
81         }
82         break;
83     case SymTagPointerType:
84         if (!memory_read_value(lvalue, sizeof(void*), &rtn)) return 0;
85         break;
86     case SymTagArrayType:
87     case SymTagUDT:
88         assert(lvalue->cookie == DLV_TARGET);
89         if (!memory_read_value(lvalue, sizeof(rtn), &rtn)) return 0;
90         break;
91     case SymTagEnum:
92         assert(lvalue->cookie == DLV_TARGET);
93         if (!memory_read_value(lvalue, sizeof(rtn), &rtn)) return 0;
94         break;
95     default:
96         WINE_FIXME("Unsupported tag %lu\n", tag);
97         rtn = 0;
98         break;
99     }
100
101     return rtn;
102 }
103
104 /******************************************************************
105  *              types_extract_as_address
106  *
107  *
108  */
109 void types_extract_as_address(const struct dbg_lvalue* lvalue, ADDRESS* addr)
110 {
111     if (lvalue->type.id == dbg_itype_segptr && lvalue->type.module == 0)
112     {
113         *addr = lvalue->addr;
114     }
115     else
116     {
117         addr->Mode = AddrModeFlat;
118         addr->Offset = types_extract_as_integer( lvalue );
119     }
120 }
121
122 /******************************************************************
123  *              types_deref
124  *
125  */
126 BOOL types_deref(const struct dbg_lvalue* lvalue, struct dbg_lvalue* result)
127 {
128     DWORD       tag;
129
130     memset(result, 0, sizeof(*result));
131     result->type.id = dbg_itype_none;
132     result->type.module = 0;
133
134     /*
135      * Make sure that this really makes sense.
136      */
137     if (!types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag) ||
138         tag != SymTagPointerType ||
139         !memory_read_value(lvalue, sizeof(result->addr.Offset), &result->addr.Offset) ||
140         !types_get_info(&lvalue->type, TI_GET_TYPE, &result->type.id))
141         return FALSE;
142     result->type.module = lvalue->type.module;
143     result->cookie = DLV_TARGET;
144     /* FIXME: this is currently buggy.
145      * there is no way to tell were the deref:ed value is...
146      * for example:
147      *  x is a pointer to struct s, x being on the stack
148      *          => lvalue is in debuggee, result is in debugger
149      *  x is a pointer to struct s, x being optimized into a reg
150      *          => lvalue is debugger, result is debuggee
151      *  x is a pointer to internal variable x
152      *          => lvalue is debugger, result is debuggee
153      * so we force debuggee address space, because dereferencing pointers to
154      * internal variables is very unlikely. A correct fix would be
155      * rather large.
156      */
157     result->addr.Mode = AddrModeFlat;
158     return TRUE;
159 }
160
161 /******************************************************************
162  *              types_get_udt_element_lvalue
163  *
164  * Implement a structure derefencement
165  */
166 static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue, 
167                                          const struct dbg_type* type, long int* tmpbuf)
168 {
169     DWORD       offset, bitoffset;
170     DWORD       bt;
171     DWORD64     length;
172
173     unsigned    mask;
174
175     types_get_info(type, TI_GET_TYPE, &lvalue->type.id);
176     lvalue->type.module = type->module;
177     if (!types_get_info(type, TI_GET_OFFSET, &offset)) return FALSE;
178     lvalue->addr.Offset += offset;
179
180     if (types_get_info(type, TI_GET_BITPOSITION, &bitoffset))
181     {
182         types_get_info(type, TI_GET_LENGTH, &length);
183         /* FIXME: this test isn't sufficient, depending on start of bitfield
184          * (ie a 32 bit field can spread across 5 bytes)
185          */
186         if (length > 8 * sizeof(*tmpbuf)) return FALSE;
187         lvalue->addr.Offset += bitoffset >> 3;
188         /*
189          * Bitfield operation.  We have to extract the field and store
190          * it in a temporary buffer so that we get it all right.
191          */
192         if (!memory_read_value(lvalue, sizeof(*tmpbuf), tmpbuf)) return FALSE;
193         mask = 0xffffffff << (DWORD)length;
194         *tmpbuf >>= bitoffset & 7;
195         *tmpbuf &= ~mask;
196
197         lvalue->cookie      = DLV_HOST;
198         lvalue->addr.Offset = (DWORD)tmpbuf;
199
200         /*
201          * OK, now we have the correct part of the number.
202          * Check to see whether the basic type is signed or not, and if so,
203          * we need to sign extend the number.
204          */
205         if (types_get_info(&lvalue->type, TI_GET_BASETYPE, &bt) && 
206             bt == btInt && (*tmpbuf & (1 << ((DWORD)length - 1))))
207         {
208             *tmpbuf |= mask;
209         }
210     }
211     else
212     {
213         if (!memory_read_value(lvalue, sizeof(*tmpbuf), tmpbuf)) return FALSE;
214
215     }
216     return TRUE;
217 }
218
219 /******************************************************************
220  *              types_udt_find_element
221  *
222  */
223 BOOL types_udt_find_element(struct dbg_lvalue* lvalue, const char* name, long int* tmpbuf)
224 {
225     DWORD                       tag, count;
226     char                        buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
227     TI_FINDCHILDREN_PARAMS*     fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
228     WCHAR*                      ptr;
229     char                        tmp[256];
230     int                         i;
231     struct dbg_type             type;
232
233     if (!types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag) ||
234         tag != SymTagUDT)
235         return FALSE;
236
237     if (types_get_info(&lvalue->type, TI_GET_CHILDRENCOUNT, &count))
238     {
239         fcp->Start = 0;
240         while (count)
241         {
242             fcp->Count = min(count, 256);
243             if (types_get_info(&lvalue->type, TI_FINDCHILDREN, fcp))
244             {
245                 type.module = lvalue->type.module;
246                 for (i = 0; i < min(fcp->Count, count); i++)
247                 {
248                     ptr = NULL;
249                     type.id = fcp->ChildId[i];
250                     types_get_info(&type, TI_GET_SYMNAME, &ptr);
251                     if (!ptr) continue;
252                     WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
253                     HeapFree(GetProcessHeap(), 0, ptr);
254                     if (strcmp(tmp, name)) continue;
255
256                     return types_get_udt_element_lvalue(lvalue, &type, tmpbuf);
257                 }
258             }
259             count -= min(count, 256);
260             fcp->Start += 256;
261         }
262     }
263     return FALSE;
264 }
265
266 /******************************************************************
267  *              types_array_index
268  *
269  * Grab an element from an array
270  */
271 BOOL types_array_index(const struct dbg_lvalue* lvalue, int index, 
272                        struct dbg_lvalue* result)
273 {
274     DWORD       tag, count;
275     DWORD64     length;
276
277     if (!types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag))
278         return FALSE;
279     switch (tag)
280     {
281     case SymTagArrayType:
282         types_get_info(&lvalue->type, TI_GET_COUNT, &count);
283         if (index < 0 || index >= count) return FALSE;
284         /* fall through */
285     case SymTagPointerType:
286         /* Contents of array share same data (addr mode, module...) */
287         *result = *lvalue;
288         /*
289          * Get the base type, so we know how much to index by.
290          */
291         types_get_info(&lvalue->type, TI_GET_TYPE, &result->type.id);
292         types_get_info(&result->type, TI_GET_LENGTH, &length);
293         memory_read_value(lvalue, sizeof(result->addr.Offset), &result->addr.Offset);
294         result->addr.Offset += index * (DWORD)length;
295         break;
296     default:
297         assert(FALSE);
298     }
299     return TRUE;
300 }
301
302 struct type_find_t
303 {
304     unsigned long       result; /* out: the found type */
305     enum SymTagEnum     tag;    /* in: the tag to look for */
306     union
307     {
308         unsigned long           typeid; /* when tag is SymTagUDT */
309         const char*             name;   /* when tag is SymTagPointerType */
310     } u;
311 };
312
313 static BOOL CALLBACK types_cb(PSYMBOL_INFO sym, ULONG size, void* _user)
314 {
315     struct type_find_t* user = (struct type_find_t*)_user;
316     BOOL                ret = TRUE;
317     struct dbg_type     type;
318     DWORD               type_id;
319
320     if (sym->Tag == user->tag)
321     {
322         switch (user->tag)
323         {
324         case SymTagUDT:
325             if (!strcmp(user->u.name, sym->Name))
326             {
327                 user->result = sym->TypeIndex;
328                 ret = FALSE;
329             }
330             break;
331         case SymTagPointerType:
332             type.module = sym->ModBase;
333             type.id = sym->TypeIndex;
334             if (types_get_info(&type, TI_GET_TYPE, &type_id) && type_id == user->u.typeid)
335             {
336                 user->result = sym->TypeIndex;
337                 ret = FALSE;
338             }
339             break;
340         default: break;
341         }
342     }
343     return ret;
344 }
345
346 /******************************************************************
347  *              types_find_pointer
348  *
349  * Should look up in module based at linear whether (typeid*) exists
350  * Otherwise, we could create it locally
351  */
352 struct dbg_type types_find_pointer(const struct dbg_type* type)
353 {
354     struct type_find_t  f;
355     struct dbg_type     ret;
356
357     f.result = dbg_itype_none;
358     f.tag = SymTagPointerType;
359     f.u.typeid = type->id;
360     SymEnumTypes(dbg_curr_process->handle, type->module, types_cb, &f);
361     ret.module = type->module;
362     ret.id = f.result;
363     return ret;
364 }
365
366 /******************************************************************
367  *              types_find_type
368  *
369  * Should look up in the module based at linear address whether a type
370  * named 'name' and with the correct tag exists
371  */
372 struct dbg_type types_find_type(unsigned long linear, const char* name, enum SymTagEnum tag)
373
374 {
375     struct type_find_t  f;
376     struct dbg_type     ret;
377
378     f.result = dbg_itype_none;
379     f.tag = tag;
380     f.u.name = name;
381     SymEnumTypes(dbg_curr_process->handle, linear, types_cb, &f);
382     ret.module = linear;
383     ret.id = f.result;
384     return ret;
385 }
386
387 /***********************************************************************
388  *           print_value
389  *
390  * Implementation of the 'print' command.
391  */
392 void print_value(const struct dbg_lvalue* lvalue, char format, int level)
393 {
394     struct dbg_lvalue   lvalue_field;
395     int                 i;
396     DWORD               tag;
397     DWORD               count;
398     DWORD64             size;
399
400     if (lvalue->type.id == dbg_itype_none)
401     {
402         /* No type, just print the addr value */
403         print_bare_address(&lvalue->addr);
404         goto leave;
405     }
406
407     if (format == 'i' || format == 's' || format == 'w' || format == 'b' || format == 'g')
408     {
409         dbg_printf("Format specifier '%c' is meaningless in 'print' command\n", format);
410         format = '\0';
411     }
412
413     if (!types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag))
414     {
415         WINE_FIXME("---error\n");
416         return;
417     }
418     switch (tag)
419     {
420     case SymTagBaseType:
421     case SymTagEnum:
422     case SymTagPointerType:
423         print_basic(lvalue, 1, format);
424         break;
425     case SymTagUDT:
426         if (types_get_info(&lvalue->type, TI_GET_CHILDRENCOUNT, &count))
427         {
428             char                        buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
429             TI_FINDCHILDREN_PARAMS*     fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
430             WCHAR*                      ptr;
431             char                        tmp[256];
432             long int                    tmpbuf;
433             struct dbg_type             type;
434
435             dbg_printf("{");
436             fcp->Start = 0;
437             while (count)
438             {
439                 fcp->Count = min(count, 256);
440                 if (types_get_info(&lvalue->type, TI_FINDCHILDREN, fcp))
441                 {
442                     for (i = 0; i < min(fcp->Count, count); i++)
443                     {
444                         ptr = NULL;
445                         type.module = lvalue->type.module;
446                         type.id = fcp->ChildId[i];
447                         types_get_info(&type, TI_GET_SYMNAME, &ptr);
448                         if (!ptr) continue;
449                         WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
450                         dbg_printf("%s=", tmp);
451                         HeapFree(GetProcessHeap(), 0, ptr);
452                         lvalue_field = *lvalue;
453                         if (types_get_udt_element_lvalue(&lvalue_field, &type, &tmpbuf))
454                         {
455                             print_value(&lvalue_field, format, level + 1);
456                         }
457                         if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
458                     }
459                 }
460                 count -= min(count, 256);
461                 fcp->Start += 256;
462             }
463             dbg_printf("}");
464         }
465         break;
466     case SymTagArrayType:
467         /*
468          * Loop over all of the entries, printing stuff as we go.
469          */
470         count = 1; size = 1;
471         types_get_info(&lvalue->type, TI_GET_COUNT, &count);
472         types_get_info(&lvalue->type, TI_GET_LENGTH, &size);
473
474         if (size == count)
475         {
476             unsigned    len;
477             char        buffer[256];
478             /*
479              * Special handling for character arrays.
480              */
481             /* FIXME should check basic type here (should be a char!!!!)... */
482             len = min(count, sizeof(buffer));
483             memory_get_string(dbg_curr_process,
484                               memory_to_linear_addr(&lvalue->addr),
485                               lvalue->cookie == DLV_TARGET, TRUE, buffer, len);
486             dbg_printf("\"%s%s\"", buffer, (len < count) ? "..." : "");
487             break;
488         }
489         lvalue_field = *lvalue;
490         types_get_info(&lvalue->type, TI_GET_TYPE, &lvalue_field.type.id);
491         dbg_printf("{");
492         for (i = 0; i < count; i++)
493         {
494             print_value(&lvalue_field, format, level + 1);
495             lvalue_field.addr.Offset += size / count;
496             dbg_printf((i == count - 1) ? "}" : ", ");
497         }
498         break;
499     case SymTagFunctionType:
500         dbg_printf("Function ");
501         print_bare_address(&lvalue->addr);
502         dbg_printf(": ");
503         types_print_type(&lvalue->type, FALSE);
504         break;
505     default:
506         WINE_FIXME("Unknown tag (%lu)\n", tag);
507         RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
508         break;
509     }
510
511 leave:
512
513     if (level == 0) dbg_printf("\n");
514 }
515
516 static BOOL CALLBACK print_types_cb(PSYMBOL_INFO sym, ULONG size, void* ctx)
517 {
518     struct dbg_type     type;
519     type.module = sym->ModBase;
520     type.id = sym->TypeIndex;
521     dbg_printf("Mod: %08lx ID: %08lx \n", type.module, type.id);
522     types_print_type(&type, TRUE);
523     dbg_printf("\n");
524     return TRUE;
525 }
526
527 static BOOL CALLBACK print_types_mod_cb(PSTR mod_name, DWORD base, void* ctx)
528 {
529     return SymEnumTypes(dbg_curr_process->handle, base, print_types_cb, ctx);
530 }
531
532 int print_types(void)
533 {
534     SymEnumerateModules(dbg_curr_process->handle, print_types_mod_cb, NULL);
535     return 0;
536 }
537
538 int types_print_type(const struct dbg_type* type, BOOL details)
539 {
540     WCHAR*              ptr;
541     char                tmp[256];
542     const char*         name;
543     DWORD               tag, udt, count;
544     struct dbg_type     subtype;
545
546     if (type->id == dbg_itype_none || !types_get_info(type, TI_GET_SYMTAG, &tag))
547     {
548         dbg_printf("--invalid--<%lxh>--", type->id);
549         return FALSE;
550     }
551
552     if (types_get_info(type, TI_GET_SYMNAME, &ptr) && ptr)
553     {
554         WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
555         name = tmp;
556         HeapFree(GetProcessHeap(), 0, ptr);
557     }
558     else name = "--none--";
559
560     switch (tag)
561     {
562     case SymTagBaseType:
563         if (details) dbg_printf("Basic<%s>", name); else dbg_printf("%s", name);
564         break;
565     case SymTagPointerType:
566         types_get_info(type, TI_GET_TYPE, &subtype.id);
567         subtype.module = type->module;
568         types_print_type(&subtype, FALSE);
569         dbg_printf("*");
570         break;
571     case SymTagUDT:
572         types_get_info(type, TI_GET_UDTKIND, &udt);
573         switch (udt)
574         {
575         case UdtStruct: dbg_printf("struct %s", name); break;
576         case UdtUnion:  dbg_printf("union %s", name); break;
577         case UdtClass:  dbg_printf("class %s", name); break;
578         default:        WINE_ERR("Unsupported UDT type (%ld) for %s", udt, name); break;
579         }
580         if (details &&
581             types_get_info(type, TI_GET_CHILDRENCOUNT, &count))
582         {
583             char                        buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
584             TI_FINDCHILDREN_PARAMS*     fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
585             WCHAR*                      ptr;
586             char                        tmp[256];
587             int                         i;
588             struct dbg_type             type_elt;
589             dbg_printf(" {");
590
591             fcp->Start = 0;
592             while (count)
593             {
594                 fcp->Count = min(count, 256);
595                 if (types_get_info(type, TI_FINDCHILDREN, fcp))
596                 {
597                     for (i = 0; i < min(fcp->Count, count); i++)
598                     {
599                         ptr = NULL;
600                         type_elt.module = type->module;
601                         type_elt.id = fcp->ChildId[i];
602                         types_get_info(&type_elt, TI_GET_SYMNAME, &ptr);
603                         if (!ptr) continue;
604                         WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
605                         HeapFree(GetProcessHeap(), 0, ptr);
606                         dbg_printf("%s", tmp);
607                         if (types_get_info(&type_elt, TI_GET_TYPE, &type_elt.id))
608                         {
609                             dbg_printf(":");
610                             types_print_type(&type_elt, details);
611                         }
612                         if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
613                     }
614                 }
615                 count -= min(count, 256);
616                 fcp->Start += 256;
617             }
618             dbg_printf("}");
619         }
620         break;
621     case SymTagArrayType:
622         types_get_info(type, TI_GET_TYPE, &subtype.id);
623         subtype.module = type->module;
624         types_print_type(&subtype, details);
625         dbg_printf(" %s[]", name);
626         break;
627     case SymTagEnum:
628         dbg_printf("enum %s", name);
629         break;
630     case SymTagFunctionType:
631         types_get_info(type, TI_GET_TYPE, &subtype.id);
632         subtype.module = type->module;
633         types_print_type(&subtype, FALSE);
634         dbg_printf(" (*%s)(", name);
635         if (types_get_info(type, TI_GET_CHILDRENCOUNT, &count))
636         {
637             char                        buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
638             TI_FINDCHILDREN_PARAMS*     fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
639             int                         i;
640
641             fcp->Start = 0;
642             while (count)
643             {
644                 fcp->Count = min(count, 256);
645                 if (types_get_info(type, TI_FINDCHILDREN, fcp))
646                 {
647                     for (i = 0; i < min(fcp->Count, count); i++)
648                     {
649                         subtype.id = fcp->ChildId[i];
650                         types_get_info(&subtype, TI_GET_TYPE, &subtype.id);
651                         types_print_type(&subtype, FALSE);
652                         if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
653                     }
654                 }
655                 count -= min(count, 256);
656                 fcp->Start += 256;
657             }
658         }
659         dbg_printf(")");
660         break;
661     default:
662         WINE_ERR("Unknown type %lu for %s\n", tag, name);
663         break;
664     }
665     
666     return TRUE;
667 }
668
669 /* helper to typecast pInfo to its expected type (_t) */
670 #define X(_t) (*((_t*)pInfo))
671
672 BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, void* pInfo)
673 {
674     if (type->id == dbg_itype_none) return FALSE;
675     if (type->module != 0)
676     {
677         DWORD ret, tag, bt;
678         ret = SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, ti, pInfo);
679         if (!ret &&
680             SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, TI_GET_SYMTAG, &tag) &&
681             tag == SymTagBaseType &&
682             SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, TI_GET_BASETYPE, &bt))
683         {
684             static const WCHAR voidW[] = {'v','o','i','d','\0'};
685             static const WCHAR charW[] = {'c','h','a','r','\0'};
686             static const WCHAR wcharW[] = {'W','C','H','A','R','\0'};
687             static const WCHAR intW[] = {'i','n','t','\0'};
688             static const WCHAR uintW[] = {'u','n','s','i','g','n','e','d',' ','i','n','t','\0'};
689             static const WCHAR floatW[] = {'f','l','o','a','t','\0'};
690             static const WCHAR boolW[] = {'b','o','o','l','\0'};
691             static const WCHAR longW[] = {'l','o','n','g',' ','i','n','t','\0'};
692             static const WCHAR ulongW[] = {'u','n','s','i','g','n','e','d',' ','l','o','n','g',' ','i','n','t','\0'};
693             static const WCHAR complexW[] = {'c','o','m','p','l','e','x','\0'};
694             const WCHAR* name = NULL;
695
696             switch (bt)
697             {
698             case btVoid:        name = voidW; break;
699             case btChar:        name = charW; break;
700             case btWChar:       name = wcharW; break;
701             case btInt:         name = intW; break;
702             case btUInt:        name = uintW; break;
703             case btFloat:       name = floatW; break;
704             case btBool:        name = boolW; break;
705             case btLong:        name = longW; break;
706             case btULong:       name = ulongW; break;
707             case btComplex:     name = complexW; break;
708             default:            WINE_FIXME("Unsupported basic type %ld\n", bt); return FALSE;
709             }
710             X(WCHAR*) = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name) + 1) * sizeof(WCHAR));
711             if (X(WCHAR*))
712             {
713                 lstrcpyW(X(WCHAR*), name);
714                 ret = TRUE;
715             }
716         }
717         return ret;
718     }
719
720     assert(type->id >= dbg_itype_first);
721
722     switch (type->id)
723     {
724     case dbg_itype_unsigned_int:
725         switch (ti)
726         {
727         case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
728         case TI_GET_LENGTH:     X(DWORD64) = 4; break;
729         case TI_GET_BASETYPE:   X(DWORD)   = btUInt; break;
730         default: WINE_FIXME("unsupported %u for u-int\n", ti); return FALSE;
731         }
732         break;
733     case dbg_itype_signed_int:
734         switch (ti)
735         {
736         case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
737         case TI_GET_LENGTH:     X(DWORD64) = 4; break;
738         case TI_GET_BASETYPE:   X(DWORD)   = btInt; break;
739         default: WINE_FIXME("unsupported %u for s-int\n", ti); return FALSE;
740         }
741         break;
742     case dbg_itype_unsigned_short_int:
743         switch (ti)
744         {
745         case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
746         case TI_GET_LENGTH:     X(DWORD64) = 2; break;
747         case TI_GET_BASETYPE:   X(DWORD)   = btUInt; break;
748         default: WINE_FIXME("unsupported %u for u-short int\n", ti); return FALSE;
749         }
750         break;
751     case dbg_itype_signed_short_int:
752         switch (ti)
753         {
754         case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
755         case TI_GET_LENGTH:     X(DWORD64) = 2; break;
756         case TI_GET_BASETYPE:   X(DWORD)   = btInt; break;
757         default: WINE_FIXME("unsupported %u for s-short int\n", ti); return FALSE;
758         }
759         break;
760     case dbg_itype_unsigned_char_int:
761         switch (ti)
762         {
763         case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
764         case TI_GET_LENGTH:     X(DWORD64) = 1; break;
765         case TI_GET_BASETYPE:   X(DWORD)   = btUInt; break;
766         default: WINE_FIXME("unsupported %u for u-char int\n", ti); return FALSE;
767         }
768         break;
769     case dbg_itype_signed_char_int:
770         switch (ti)
771         {
772         case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
773         case TI_GET_LENGTH:     X(DWORD64) = 1; break;
774         case TI_GET_BASETYPE:   X(DWORD)   = btInt; break;
775         default: WINE_FIXME("unsupported %u for s-char int\n", ti); return FALSE;
776         }
777         break;
778     case dbg_itype_char:
779         switch (ti)
780         {
781         case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
782         case TI_GET_LENGTH:     X(DWORD64) = 1; break;
783         case TI_GET_BASETYPE:   X(DWORD)   = btChar; break;
784         default: WINE_FIXME("unsupported %u for char int\n", ti); return FALSE;
785         }
786         break;
787     case dbg_itype_astring:
788         switch (ti)
789         {
790         case TI_GET_SYMTAG:     X(DWORD)   = SymTagPointerType; break;
791         case TI_GET_LENGTH:     X(DWORD64) = 4; break;
792         case TI_GET_TYPE:       X(DWORD)   = dbg_itype_char; break;
793         default: WINE_FIXME("unsupported %u for a string\n", ti); return FALSE;
794         }
795         break;
796     case dbg_itype_segptr:
797         switch (ti)
798         {
799         case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
800         case TI_GET_LENGTH:     X(DWORD64) = 4; break;
801         case TI_GET_BASETYPE:   X(DWORD)   = btInt; break;
802         default: WINE_FIXME("unsupported %u for seg-ptr\n", ti); return FALSE;
803         }
804         break;
805     default: WINE_FIXME("unsupported type id 0x%lx\n", type->id);
806     }
807
808 #undef X
809     return TRUE;
810 }