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