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