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