Rename X11 Driver tab of winecfg to Graphics.
[wine/multimedia.git] / programs / winedbg / types.c
blob0b3e6300d8bc604054785cbb2fc73964d2806e62
1 /*
2 * File types.c - datatype handling stuff for internal debugger.
4 * Copyright (C) 1997, Eric Youngdale.
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.
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.
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
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.
24 #include "config.h"
25 #include <stdlib.h>
27 #include "debugger.h"
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
32 /******************************************************************
33 * types_extract_as_integer
35 * Given a lvalue, try to get an integral (or pointer/address) value
36 * out of it
38 long int types_extract_as_integer(const struct dbg_lvalue* lvalue)
40 long int rtn = 0;
41 DWORD tag, size, bt;
42 DWORD linear = (DWORD)memory_to_linear_addr(&lvalue->addr);
44 assert(lvalue->cookie == DLV_TARGET || lvalue->cookie == DLV_HOST);
46 if (lvalue->typeid == dbg_itype_none ||
47 !types_get_info(linear, lvalue->typeid, TI_GET_SYMTAG, &tag))
48 return 0;
50 switch (tag)
52 case SymTagBaseType:
53 if (!types_get_info(linear, lvalue->typeid, TI_GET_LENGTH, &size) ||
54 !types_get_info(linear, lvalue->typeid, TI_GET_BASETYPE, &bt))
56 WINE_ERR("Couldn't get information\n");
57 RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
59 if (size > sizeof(rtn))
61 WINE_ERR("Size too large (%lu)\n", size);
62 return 0;
64 /* FIXME: we have an ugly & non portable thing here !!! */
65 if (!memory_read_value(lvalue, size, &rtn)) return 0;
67 /* now let's do some promotions !! */
68 switch (bt)
70 case btInt:
71 /* propagate sign information */
72 if (((size & 3) != 0) && (rtn >> (size * 8 - 1)) != 0)
73 rtn |= (-1) << (size * 8);
74 break;
75 case btUInt:
76 case btChar:
77 break;
78 case btFloat:
79 RaiseException(DEBUG_STATUS_NOT_AN_INTEGER, 0, 0, NULL);
81 break;
82 case SymTagPointerType:
83 if (!memory_read_value(lvalue, sizeof(void*), &rtn)) return 0;
84 break;
85 case SymTagArrayType:
86 case SymTagUDT:
87 assert(lvalue->cookie == DLV_TARGET);
88 if (!memory_read_value(lvalue, sizeof(rtn), &rtn)) return 0;
89 break;
90 case SymTagEnum:
91 assert(lvalue->cookie == DLV_TARGET);
92 if (!memory_read_value(lvalue, sizeof(rtn), &rtn)) return 0;
93 break;
94 default:
95 WINE_FIXME("Unsupported tag %lu\n", tag);
96 rtn = 0;
97 break;
100 return rtn;
103 /******************************************************************
104 * types_deref
107 BOOL types_deref(const struct dbg_lvalue* lvalue, struct dbg_lvalue* result)
109 DWORD tag;
110 DWORD linear = (DWORD)memory_to_linear_addr(&lvalue->addr);
112 assert(lvalue->cookie == DLV_TARGET || lvalue->cookie == DLV_HOST);
114 memset(result, 0, sizeof(*result));
115 result->typeid = dbg_itype_none;
118 * Make sure that this really makes sense.
120 if (!types_get_info(linear, lvalue->typeid, TI_GET_SYMTAG, &tag) ||
121 tag != SymTagPointerType ||
122 memory_read_value(lvalue, sizeof(result->addr.Offset), &result->addr.Offset) ||
123 !types_get_info(linear, lvalue->typeid, TI_GET_TYPE, &result->typeid))
124 return FALSE;
126 result->cookie = DLV_TARGET; /* see comment on DEREF below */
127 result->addr.Mode = AddrModeFlat;
128 return TRUE;
131 /******************************************************************
132 * types_get_udt_element_lvalue
134 * Implement a structure derefencement
136 static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue, DWORD linear,
137 DWORD typeid, long int* tmpbuf)
139 DWORD offset, length, bitoffset;
140 DWORD bt;
141 unsigned mask;
143 types_get_info(linear, typeid, TI_GET_TYPE, &lvalue->typeid);
144 types_get_info(linear, typeid, TI_GET_OFFSET, &offset);
146 if (types_get_info(linear, typeid, TI_GET_BITPOSITION, &bitoffset))
148 types_get_info(linear, typeid, TI_GET_LENGTH, &length);
149 if (length > sizeof(*tmpbuf)) return FALSE;
151 * Bitfield operation. We have to extract the field and store
152 * it in a temporary buffer so that we get it all right.
154 lvalue->addr.Offset += offset;
155 if (!memory_read_value(lvalue, sizeof(*tmpbuf), tmpbuf)) return FALSE;
156 mask = 0xffffffff << length;
157 *tmpbuf >>= bitoffset & 7;
158 *tmpbuf &= ~mask;
160 lvalue->cookie = DLV_HOST;
161 lvalue->addr.Mode = AddrModeFlat;
162 lvalue->addr.Offset = (DWORD)tmpbuf;
165 * OK, now we have the correct part of the number.
166 * Check to see whether the basic type is signed or not, and if so,
167 * we need to sign extend the number.
169 if (types_get_info(linear, lvalue->typeid, TI_GET_BASETYPE, &bt) &&
170 bt == btInt && (*tmpbuf & (1 << (length - 1))))
172 *tmpbuf |= mask;
174 return TRUE;
176 if (types_get_info(linear, typeid, TI_GET_OFFSET, &offset))
178 lvalue->addr.Offset += offset;
179 return TRUE;
181 return FALSE;
184 /******************************************************************
185 * types_udt_find_element
188 BOOL types_udt_find_element(struct dbg_lvalue* lvalue, const char* name, long int* tmpbuf)
190 DWORD linear = (DWORD)memory_to_linear_addr(&lvalue->addr);
191 DWORD tag, count;
192 char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
193 TI_FINDCHILDREN_PARAMS* fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
194 WCHAR* ptr;
195 char tmp[256];
196 int i;
198 assert(lvalue->cookie == DLV_TARGET || lvalue->cookie == DLV_HOST);
200 if (!types_get_info(linear, lvalue->typeid, TI_GET_SYMTAG, &tag) ||
201 tag != SymTagUDT)
202 return FALSE;
204 if (types_get_info(linear, lvalue->typeid, TI_GET_CHILDRENCOUNT, &count))
206 fcp->Start = 0;
207 while (count)
209 fcp->Count = min(count, 256);
210 if (types_get_info(linear, lvalue->typeid, TI_FINDCHILDREN, fcp))
212 for (i = 0; i < min(fcp->Count, count); i++)
214 ptr = NULL;
215 types_get_info(linear, fcp->ChildId[i], TI_GET_SYMNAME, &ptr);
216 if (!ptr) continue;
217 WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
218 HeapFree(GetProcessHeap(), 0, ptr);
219 if (strcmp(tmp, name)) continue;
221 return types_get_udt_element_lvalue(lvalue, linear,
222 fcp->ChildId[i], tmpbuf);
225 count -= min(count, 256);
226 fcp->Start += 256;
229 return FALSE;
232 /******************************************************************
233 * types_array_index
235 * Grab an element from an array
237 BOOL types_array_index(const struct dbg_lvalue* lvalue, int index,
238 struct dbg_lvalue* result)
240 DWORD tag, length, count;
241 DWORD linear = (DWORD)memory_to_linear_addr(&lvalue->addr);
243 assert(lvalue->cookie == DLV_TARGET || lvalue->cookie == DLV_HOST);
245 if (!types_get_info(0, lvalue->typeid, TI_GET_SYMTAG, &tag))
246 return FALSE;
247 switch (tag)
249 case SymTagArrayType:
250 types_get_info(linear, lvalue->typeid, TI_GET_COUNT, &count);
251 if (index < 0 || index >= count) return FALSE;
252 /* fall through */
253 case SymTagPointerType:
255 * Get the base type, so we know how much to index by.
257 types_get_info(linear, lvalue->typeid, TI_GET_TYPE, &result->typeid);
258 types_get_info(linear, result->typeid, TI_GET_LENGTH, &length);
259 /* Contents of array must be on same target */
260 result->cookie = lvalue->cookie;
261 result->addr.Mode = lvalue->addr.Mode;
262 memory_read_value(lvalue, sizeof(result->addr.Offset), &result->addr.Offset);
263 result->addr.Offset += index * length;
264 break;
265 default:
266 assert(FALSE);
268 return TRUE;
271 struct type_find_t
273 unsigned long result; /* out: the found type */
274 enum SymTagEnum tag; /* in: the tag to look for */
275 union
277 unsigned long typeid;
278 const char* name;
279 } u;
282 static BOOL CALLBACK types_cb(PSYMBOL_INFO sym, ULONG size, void* _user)
284 struct type_find_t* user = (struct type_find_t*)_user;
285 BOOL ret = TRUE;
286 DWORD typeid;
288 if (sym->Tag == user->tag)
290 switch (user->tag)
292 case SymTagUDT:
293 if (!strcmp(user->u.name, sym->Name))
295 user->result = sym->TypeIndex;
296 ret = FALSE;
298 break;
299 case SymTagPointerType:
300 types_get_info(sym->ModBase, sym->TypeIndex, TI_GET_TYPE, &typeid);
301 if (types_get_info(sym->ModBase, sym->TypeIndex, TI_GET_TYPE, &typeid) &&
302 typeid == user->u.typeid)
304 user->result = sym->TypeIndex;
305 ret = FALSE;
307 default: break;
310 return ret;
313 /******************************************************************
314 * types_find_pointer
316 * Should look up in module based at linear whether (typeid*) exists
317 * Otherwise, we could create it locally
319 unsigned long types_find_pointer(unsigned long linear, unsigned long typeid)
321 struct type_find_t f;
322 f.result = dbg_itype_none;
323 f.tag = SymTagPointerType;
324 f.u.typeid = typeid;
325 SymEnumTypes(dbg_curr_process->handle, linear, types_cb, &f);
326 return f.result;
329 /******************************************************************
330 * types_find_type
332 * Should look up in the module based at linear address whether a type
333 * named 'name' and with the correct tag exists
335 unsigned long types_find_type(unsigned long linear, const char* name, enum SymTagEnum tag)
338 struct type_find_t f;
339 f.result = dbg_itype_none;
340 f.tag = tag;
341 f.u.name = name;
342 SymEnumTypes(dbg_curr_process->handle, linear, types_cb, &f);
343 return f.result;
346 /***********************************************************************
347 * print_value
349 * Implementation of the 'print' command.
351 void print_value(const struct dbg_lvalue* lvalue, char format, int level)
353 struct dbg_lvalue lvalue_field;
354 int i;
355 unsigned long linear;
356 DWORD tag;
357 DWORD count;
358 DWORD size;
360 assert(lvalue->cookie == DLV_TARGET || lvalue->cookie == DLV_HOST);
361 linear = (unsigned long)memory_to_linear_addr(&lvalue->addr);
363 if (lvalue->typeid == dbg_itype_none)
365 /* No type, just print the addr value */
366 print_bare_address(&lvalue->addr);
367 goto leave;
370 if (format == 'i' || format == 's' || format == 'w' || format == 'b' || format == 'g')
372 dbg_printf("Format specifier '%c' is meaningless in 'print' command\n", format);
373 format = '\0';
376 if (!types_get_info(linear, lvalue->typeid, TI_GET_SYMTAG, &tag))
378 WINE_FIXME("---error\n");
379 return;
381 switch (tag)
383 case SymTagBaseType:
384 case SymTagEnum:
385 case SymTagPointerType:
386 print_basic(lvalue, 1, format);
387 break;
388 case SymTagUDT:
389 if (types_get_info(linear, lvalue->typeid, TI_GET_CHILDRENCOUNT, &count))
391 char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
392 TI_FINDCHILDREN_PARAMS* fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
393 WCHAR* ptr;
394 char tmp[256];
395 long int tmpbuf;
397 dbg_printf("{");
398 fcp->Start = 0;
399 while (count)
401 fcp->Count = min(count, 256);
402 if (types_get_info(linear, lvalue->typeid, TI_FINDCHILDREN, fcp))
404 for (i = 0; i < min(fcp->Count, count); i++)
406 ptr = NULL;
407 types_get_info(linear, fcp->ChildId[i], TI_GET_SYMNAME, &ptr);
408 if (!ptr) continue;
409 WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
410 dbg_printf("%s=", tmp);
411 HeapFree(GetProcessHeap(), 0, ptr);
412 lvalue_field = *lvalue;
413 if (types_get_udt_element_lvalue(&lvalue_field, linear,
414 fcp->ChildId[i], &tmpbuf))
416 print_value(&lvalue_field, format, level + 1);
418 if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
421 count -= min(count, 256);
422 fcp->Start += 256;
424 dbg_printf("}");
426 break;
427 case SymTagArrayType:
429 * Loop over all of the entries, printing stuff as we go.
431 count = 1; size = 1;
432 types_get_info(linear, lvalue->typeid, TI_GET_COUNT, &count);
433 types_get_info(linear, lvalue->typeid, TI_GET_LENGTH, &size);
435 if (size == count)
437 unsigned len;
438 char buffer[256];
440 * Special handling for character arrays.
442 /* FIXME should check basic type here (should be a char!!!!)... */
443 len = min(count, sizeof(buffer));
444 memory_get_string(dbg_curr_thread->handle,
445 memory_to_linear_addr(&lvalue->addr),
446 lvalue->cookie, TRUE, buffer, len);
447 dbg_printf("\"%s%s\"", buffer, (len < count) ? "..." : "");
448 break;
450 lvalue_field = *lvalue;
451 types_get_info(linear, lvalue->typeid, TI_GET_TYPE, &lvalue_field.typeid);
452 dbg_printf("{");
453 for (i = 0; i < count; i++)
455 print_value(&lvalue_field, format, level + 1);
456 lvalue_field.addr.Offset += size / count;
457 dbg_printf((i == count - 1) ? "}" : ", ");
459 break;
460 case SymTagFunctionType:
461 dbg_printf("Function ");
462 print_bare_address(&lvalue->addr);
463 dbg_printf(": ");
464 types_print_type(linear, lvalue->typeid, FALSE);
465 break;
466 default:
467 WINE_FIXME("Unknown tag (%lu)\n", tag);
468 RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
469 break;
472 leave:
474 if (level == 0) dbg_printf("\n");
477 static BOOL CALLBACK print_types_cb(PSYMBOL_INFO sym, ULONG size, void* ctx)
479 types_print_type(sym->ModBase, sym->TypeIndex, TRUE);
480 dbg_printf("\n");
481 return TRUE;
484 static BOOL CALLBACK print_types_mod_cb(PSTR mod_name, DWORD base, void* ctx)
486 return SymEnumTypes(dbg_curr_process->handle, base, print_types_cb, ctx);
489 int print_types(void)
491 SymEnumerateModules(dbg_curr_process->handle, print_types_mod_cb, NULL);
492 return 0;
495 int types_print_type(DWORD linear, DWORD typeid, BOOL details)
497 WCHAR* ptr;
498 char tmp[256];
499 const char* name;
500 DWORD tag, subtype, count;
502 if (typeid == dbg_itype_none || !types_get_info(linear, typeid, TI_GET_SYMTAG, &tag))
504 dbg_printf("--invalid--<%lxh>--", typeid);
505 return FALSE;
508 if (types_get_info(linear, typeid, TI_GET_SYMNAME, &ptr) && ptr)
510 WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
511 name = tmp;
512 HeapFree(GetProcessHeap(), 0, ptr);
514 else name = "--none--";
516 switch (tag)
518 case SymTagBaseType:
519 if (details) dbg_printf("Basic<%s>", name); else dbg_printf("%s", name);
520 break;
521 case SymTagPointerType:
522 types_get_info(linear, typeid, TI_GET_TYPE, &subtype);
523 types_print_type(linear, subtype, details);
524 dbg_printf("*");
525 break;
526 case SymTagUDT:
527 types_get_info(linear, typeid, TI_GET_UDTKIND, &subtype);
528 switch (subtype)
530 case UdtStruct: dbg_printf("struct %s", name); break;
531 case UdtUnion: dbg_printf("union %s", name); break;
532 case UdtClass: dbg_printf("class %s", name); break;
534 if (details &&
535 types_get_info(linear, typeid, TI_GET_CHILDRENCOUNT, &count))
537 char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
538 TI_FINDCHILDREN_PARAMS* fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
539 WCHAR* ptr;
540 char tmp[256];
541 int i;
543 dbg_printf(" {");
545 fcp->Start = 0;
546 while (count)
548 fcp->Count = min(count, 256);
549 if (types_get_info(linear, typeid, TI_FINDCHILDREN, fcp))
551 for (i = 0; i < min(fcp->Count, count); i++)
553 ptr = NULL;
554 types_get_info(linear, fcp->ChildId[i], TI_GET_SYMNAME, &ptr);
555 if (!ptr) continue;
556 WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
557 HeapFree(GetProcessHeap(), 0, ptr);
558 dbg_printf("%s", tmp);
559 if (types_get_info(linear, fcp->ChildId[i], TI_GET_TYPE, &subtype))
561 dbg_printf(":");
562 types_print_type(linear, subtype, details);
564 if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
567 count -= min(count, 256);
568 fcp->Start += 256;
570 dbg_printf("}");
572 break;
573 case SymTagArrayType:
574 types_get_info(linear, typeid, TI_GET_TYPE, &subtype);
575 types_print_type(linear, subtype, details);
576 dbg_printf(" %s[]", name);
577 break;
578 case SymTagEnum:
579 dbg_printf("enum %s", name);
580 break;
581 case SymTagFunctionType:
582 types_get_info(linear, typeid, TI_GET_TYPE, &subtype);
583 types_print_type(linear, subtype, FALSE);
584 dbg_printf(" (*%s)(", name);
585 if (types_get_info(linear, typeid, TI_GET_CHILDRENCOUNT, &count))
587 char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
588 TI_FINDCHILDREN_PARAMS* fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
589 int i;
591 fcp->Start = 0;
592 while (count)
594 fcp->Count = min(count, 256);
595 if (types_get_info(linear, typeid, TI_FINDCHILDREN, fcp))
597 for (i = 0; i < min(fcp->Count, count); i++)
599 types_print_type(linear, fcp->ChildId[i], FALSE);
600 if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
603 count -= min(count, 256);
604 fcp->Start += 256;
607 dbg_printf(")");
608 break;
609 default:
610 WINE_ERR("Unknown type %lu for %s\n", tag, name);
611 break;
614 return TRUE;
617 BOOL types_get_info(unsigned long modbase, unsigned long typeid,
618 IMAGEHLP_SYMBOL_TYPE_INFO ti, void* pInfo)
620 if (typeid == dbg_itype_none) return FALSE;
621 if (typeid < dbg_itype_first)
623 BOOL ret;
624 DWORD tag;
626 ret = SymGetTypeInfo(dbg_curr_process->handle, modbase, typeid, ti, pInfo);
627 if (!ret && ti == TI_GET_LENGTH &&
628 (!SymGetTypeInfo(dbg_curr_process->handle, modbase, typeid,
629 TI_GET_SYMTAG, &tag) || tag == SymTagData))
631 WINE_FIXME("get length on symtag data is no longer supported\n");
632 assert(0);
634 return ret;
636 assert(modbase);
638 /* helper to typecast pInfo to its expected type (_t) */
639 #define X(_t) (*((_t*)pInfo))
641 switch (typeid)
643 case dbg_itype_unsigned_int:
644 switch (ti)
646 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
647 case TI_GET_LENGTH: X(DWORD) = 4; break;
648 case TI_GET_BASETYPE: X(DWORD) = btUInt; break;
649 default: WINE_FIXME("unsupported %u for u-int\n", ti); return FALSE;
651 break;
652 case dbg_itype_signed_int:
653 switch (ti)
655 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
656 case TI_GET_LENGTH: X(DWORD) = 4; break;
657 case TI_GET_BASETYPE: X(DWORD) = btInt; break;
658 default: WINE_FIXME("unsupported %u for s-int\n", ti); return FALSE;
660 break;
661 case dbg_itype_unsigned_short_int:
662 switch (ti)
664 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
665 case TI_GET_LENGTH: X(DWORD) = 2; break;
666 case TI_GET_BASETYPE: X(DWORD) = btUInt; break;
667 default: WINE_FIXME("unsupported %u for u-short int\n", ti); return FALSE;
669 break;
670 case dbg_itype_signed_short_int:
671 switch (ti)
673 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
674 case TI_GET_LENGTH: X(DWORD) = 2; break;
675 case TI_GET_BASETYPE: X(DWORD) = btInt; break;
676 default: WINE_FIXME("unsupported %u for s-short int\n", ti); return FALSE;
678 break;
679 case dbg_itype_unsigned_char_int:
680 switch (ti)
682 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
683 case TI_GET_LENGTH: X(DWORD) = 1; break;
684 case TI_GET_BASETYPE: X(DWORD) = btUInt; break;
685 default: WINE_FIXME("unsupported %u for u-char int\n", ti); return FALSE;
687 break;
688 case dbg_itype_signed_char_int:
689 switch (ti)
691 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
692 case TI_GET_LENGTH: X(DWORD) = 1; break;
693 case TI_GET_BASETYPE: X(DWORD) = btInt; break;
694 default: WINE_FIXME("unsupported %u for s-char int\n", ti); return FALSE;
696 break;
697 case dbg_itype_char:
698 switch (ti)
700 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
701 case TI_GET_LENGTH: X(DWORD) = 1; break;
702 case TI_GET_BASETYPE: X(DWORD) = btChar; break;
703 default: WINE_FIXME("unsupported %u for char int\n", ti); return FALSE;
705 break;
706 case dbg_itype_astring:
707 switch (ti)
709 case TI_GET_SYMTAG: X(DWORD) = SymTagPointerType; break;
710 case TI_GET_LENGTH: X(DWORD) = 4; break;
711 case TI_GET_TYPE: X(DWORD) = dbg_itype_char; break;
712 default: WINE_FIXME("unsupported %u for a string\n", ti); return FALSE;
714 break;
715 default: WINE_FIXME("unsupported typeid 0x%lx\n", typeid);
718 #undef X
719 return TRUE;