Started implementing support for the SubSystemTib field in the TEB of
[wine] / dlls / dbghelp / type.c
1 /*
2  * File types.c - management of types (hierarchical tree)
3  *
4  * Copyright (C) 1997, Eric Youngdale.
5  *               2004, Eric Pouech.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  * Note: This really doesn't do much at the moment, but it forms the framework
22  * upon which full support for datatype handling will eventually be built.
23  */
24 #include "config.h"
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <assert.h>
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winreg.h"
32 #include "winnls.h"
33 #include "wine/debug.h"
34 #include "dbghelp_private.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
37 WINE_DECLARE_DEBUG_CHANNEL(dbghelp_symtype);
38
39 static const char* symt_get_tag_str(DWORD tag)
40 {
41     switch (tag)
42     {
43     case SymTagNull:                    return "SymTagNull";
44     case SymTagExe:                     return "SymTagExe";
45     case SymTagCompiland:               return "SymTagCompiland";
46     case SymTagCompilandDetails:        return "SymTagCompilandDetails";
47     case SymTagCompilandEnv:            return "SymTagCompilandEnv";
48     case SymTagFunction:                return "SymTagFunction";
49     case SymTagBlock:                   return "SymTagBlock";
50     case SymTagData:                    return "SymTagData";
51     case SymTagAnnotation:              return "SymTagAnnotation";
52     case SymTagLabel:                   return "SymTagLabel";
53     case SymTagPublicSymbol:            return "SymTagPublicSymbol";
54     case SymTagUDT:                     return "SymTagUDT";
55     case SymTagEnum:                    return "SymTagEnum";
56     case SymTagFunctionType:            return "SymTagFunctionType";
57     case SymTagPointerType:             return "SymTagPointerType";
58     case SymTagArrayType:               return "SymTagArrayType";
59     case SymTagBaseType:                return "SymTagBaseType";
60     case SymTagTypedef:                 return "SymTagTypedef,";
61     case SymTagBaseClass:               return "SymTagBaseClass";
62     case SymTagFriend:                  return "SymTagFriend";
63     case SymTagFunctionArgType:         return "SymTagFunctionArgType,";
64     case SymTagFuncDebugStart:          return "SymTagFuncDebugStart,";
65     case SymTagFuncDebugEnd:            return "SymTagFuncDebugEnd";
66     case SymTagUsingNamespace:          return "SymTagUsingNamespace,";
67     case SymTagVTableShape:             return "SymTagVTableShape";
68     case SymTagVTable:                  return "SymTagVTable";
69     case SymTagCustom:                  return "SymTagCustom";
70     case SymTagThunk:                   return "SymTagThunk";
71     case SymTagCustomType:              return "SymTagCustomType";
72     case SymTagManagedType:             return "SymTagManagedType";
73     case SymTagDimension:               return "SymTagDimension";
74     default:                            return "---";
75     }
76 }
77
78 const char* symt_get_name(const struct symt* sym)
79 {
80     switch (sym->tag)
81     {
82     /* lexical tree */
83     case SymTagData:            return ((struct symt_data*)sym)->hash_elt.name;
84     case SymTagFunction:        return ((struct symt_function*)sym)->hash_elt.name;
85     case SymTagPublicSymbol:    return ((struct symt_public*)sym)->hash_elt.name;
86     case SymTagBaseType:        return ((struct symt_basic*)sym)->hash_elt.name;
87     /* hierarchy tree */
88     case SymTagEnum:            return ((struct symt_enum*)sym)->name;
89     case SymTagTypedef:         return ((struct symt_typedef*)sym)->hash_elt.name;
90     case SymTagUDT:             return ((struct symt_udt*)sym)->hash_elt.name;
91     default:
92         FIXME("Unsupported sym-tag %s\n", symt_get_tag_str(sym->tag));
93         /* fall through */
94     case SymTagArrayType:
95     case SymTagPointerType:
96     case SymTagFunctionType:
97         return NULL;
98     }
99 }
100
101 static struct symt* symt_find_type_by_name(struct module* module, 
102                                            enum SymTagEnum sym_tag, 
103                                            const char* typename)
104 {
105     void*                       ptr;
106     struct symt_ht*             type;
107     struct hash_table_iter      hti;
108
109     assert(typename);
110     assert(module);
111
112     hash_table_iter_init(&module->ht_types, &hti, typename);
113     while ((ptr = hash_table_iter_up(&hti)))
114     {
115         type = GET_ENTRY(ptr, struct symt_ht, hash_elt);
116
117         if ((sym_tag == SymTagNull || type->symt.tag == sym_tag) &&
118             type->hash_elt.name && !strcmp(type->hash_elt.name, typename))
119             return &type->symt;
120     }
121     SetLastError(ERROR_INVALID_NAME); /* FIXME ?? */
122     return NULL;
123 }
124
125 struct symt_basic* symt_new_basic(struct module* module, enum BasicType bt, 
126                                   const char* typename, unsigned size)
127 {
128     struct symt_basic*          sym;
129
130     if (typename)
131     {
132         sym = (struct symt_basic*)symt_find_type_by_name(module, SymTagBaseType,
133                                                          typename);
134         if (sym && sym->bt == bt && sym->size == size)
135             return sym;
136     }
137     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
138     {
139         sym->symt.tag = SymTagBaseType;
140         if (typename)
141         {
142             sym->hash_elt.name = pool_strdup(&module->pool, typename);
143             hash_table_add(&module->ht_types, &sym->hash_elt);
144         } else sym->hash_elt.name = NULL;
145         sym->bt = bt;
146         sym->size = size;
147     }
148     return sym;
149 }
150
151 struct symt_udt* symt_new_udt(struct module* module, const char* typename, 
152                               unsigned size, enum UdtKind kind)
153 {
154     struct symt_udt*            sym;
155
156     TRACE_(dbghelp_symtype)("Adding udt %s:%s\n", module->module.ModuleName, typename);
157     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
158     {
159         sym->symt.tag = SymTagUDT;
160         sym->kind     = kind;
161         sym->size     = size;
162         if (typename)
163         {
164             sym->hash_elt.name = pool_strdup(&module->pool, typename);
165             hash_table_add(&module->ht_types, &sym->hash_elt);
166         } else sym->hash_elt.name = NULL;
167         vector_init(&sym->vchildren, sizeof(struct symt*), 8);
168     }
169     return sym;
170 }
171
172 BOOL symt_set_udt_size(struct module* module, struct symt_udt* udt, unsigned size)
173 {
174     assert(udt->symt.tag == SymTagUDT);
175     if (vector_length(&udt->vchildren) != 0)
176     {
177         if (udt->size != size)
178             FIXME_(dbghelp_symtype)("Changing size for %s from %u to %u\n", 
179                                     udt->hash_elt.name, udt->size, size);
180         return TRUE;
181     }
182     udt->size = size;
183     return TRUE;
184 }
185
186 /******************************************************************
187  *              symt_add_udt_element
188  *
189  * add an element to a udt (struct, class, union)
190  * the size & offset parameters are expressed in bits (not bytes) so that
191  * we can mix in the single call bytes aligned elements (regular fields) and
192  * the others (bit fields)
193  */
194 BOOL symt_add_udt_element(struct module* module, struct symt_udt* udt_type,
195                           const char* name, struct symt* elt_type,
196                           unsigned offset, unsigned size)
197 {
198     struct symt_data*   m;
199     struct symt**       p;
200
201     assert(udt_type->symt.tag == SymTagUDT);
202
203     TRACE_(dbghelp_symtype)("Adding %s to UDT %s\n", name, udt_type->hash_elt.name);
204     p = NULL;
205     while ((p = vector_iter_up(&udt_type->vchildren, p)))
206     {
207         m = (struct symt_data*)*p;
208         assert(m);
209         assert(m->symt.tag == SymTagData);
210         if (m->hash_elt.name[0] == name[0] && strcmp(m->hash_elt.name, name) == 0)
211             return TRUE;
212     }
213
214     if ((m = pool_alloc(&module->pool, sizeof(*m))) == NULL) return FALSE;
215     memset(m, 0, sizeof(*m));
216     m->symt.tag      = SymTagData;
217     m->hash_elt.name = pool_strdup(&module->pool, name);
218     m->hash_elt.next = NULL;
219
220     m->kind          = DataIsMember;
221     m->container     = &udt_type->symt;
222     m->type          = elt_type;
223     if (!(offset & 7) && !(size & 7))
224     {
225         m->location      = LocIsThisRel;
226         m->u.offset      = offset >> 3;
227         /* we could check that elt_type's size is actually size */
228     }
229     else
230     {
231         m->location            = LocIsBitField;
232         m->u.bitfield.position = offset;
233         m->u.bitfield.length   = size;
234     }
235     p = vector_add(&udt_type->vchildren, &module->pool);
236     *p = &m->symt;
237
238     return TRUE;
239 }
240
241 struct symt_enum* symt_new_enum(struct module* module, const char* typename)
242 {
243     struct symt_enum*   sym;
244
245     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
246     {
247         sym->symt.tag            = SymTagEnum;
248         sym->name = pool_strdup(&module->pool, typename);
249         vector_init(&sym->vchildren, sizeof(struct symt*), 8);
250     }
251     return sym;
252 }
253
254 BOOL symt_add_enum_element(struct module* module, struct symt_enum* enum_type,
255                            const char* name, unsigned value)
256 {
257     struct symt_data*   e;
258     struct symt**       p;
259
260     assert(enum_type->symt.tag == SymTagEnum);
261     e = pool_alloc(&module->pool, sizeof(*e));
262     if (e == NULL) return FALSE;
263
264     e->symt.tag = SymTagData;
265     e->hash_elt.name = pool_strdup(&module->pool, name);
266     e->hash_elt.next = NULL;
267     e->kind = DataIsConstant;
268     e->container = &enum_type->symt;
269     /* CV defines the underlying type for the enumeration */
270     e->type = &symt_new_basic(module, btInt, "int", 4)->symt;
271     e->location = LocIsConstant;
272     e->u.value = value; /* FIXME: use variant */
273
274     p = vector_add(&enum_type->vchildren, &module->pool);
275     if (!p) return FALSE; /* FIXME we leak e */
276     *p = &e->symt;
277
278     return TRUE;
279 }
280
281 struct symt_array* symt_new_array(struct module* module, int min, int max, 
282                                   struct symt* base)
283 {
284     struct symt_array*  sym;
285
286     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
287     {
288         sym->symt.tag  = SymTagArrayType;
289         sym->start     = min;
290         sym->end       = max;
291         sym->basetype  = base;
292     }
293     return sym;
294 }
295
296 struct symt_function_signature* symt_new_function_signature(struct module* module, 
297                                                             struct symt* ret_type)
298 {
299     struct symt_function_signature* sym;
300
301     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
302     {
303         sym->symt.tag = SymTagFunctionType;
304         sym->rettype  = ret_type;
305     }
306     return sym;
307 }
308
309 struct symt_pointer* symt_new_pointer(struct module* module, struct symt* ref_type)
310 {
311     struct symt_pointer*        sym;
312
313     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
314     {
315         sym->symt.tag = SymTagPointerType;
316         sym->pointsto = ref_type;
317     }
318     return sym;
319 }
320
321 /******************************************************************
322  *              SymEnumTypes (DBGHELP.@)
323  *
324  */
325 BOOL WINAPI SymEnumTypes(HANDLE hProcess, unsigned long BaseOfDll,
326                          PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
327                          void* UserContext)
328 {
329     struct process*             pcs;
330     struct module*              module;
331     struct symt_ht*             type;
332     void*                       ptr;
333     char                        buffer[sizeof(SYMBOL_INFO) + 256];
334     SYMBOL_INFO*                sym_info = (SYMBOL_INFO*)buffer;
335     struct hash_table_iter      hti;
336     const char*                 tmp;
337
338     TRACE("(%p %08lx %p %p)\n",
339           hProcess, BaseOfDll, EnumSymbolsCallback, UserContext);
340
341     pcs = process_find_by_handle(hProcess);
342     if (!pcs) return FALSE;
343     module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
344     if (!(module = module_get_debug(pcs, module))) return FALSE;
345
346     sym_info->SizeOfStruct = sizeof(SYMBOL_INFO);
347     sym_info->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO);
348
349     hash_table_iter_init(&module->ht_types, &hti, NULL);
350     while ((ptr = hash_table_iter_up(&hti)))
351     {
352         type = GET_ENTRY(ptr, struct symt_ht, hash_elt);
353         sym_info->TypeIndex = (DWORD)type;
354         sym_info->info = 0; /* FIXME */
355         symt_get_info(&type->symt, TI_GET_LENGTH, &sym_info->Size);
356         sym_info->ModBase = module->module.BaseOfImage;
357         sym_info->Flags = 0; /* FIXME */
358         sym_info->Value = 0; /* FIXME */
359         sym_info->Address = 0; /* FIXME */
360         sym_info->Register = 0; /* FIXME */
361         sym_info->Scope = 0; /* FIXME */
362         sym_info->Tag = type->symt.tag;
363         tmp = symt_get_name(&type->symt);
364         sym_info->NameLen = strlen(tmp) + 1;
365         strncpy(sym_info->Name, tmp, min(sym_info->NameLen, sym_info->MaxNameLen));
366         sym_info->Name[sym_info->MaxNameLen - 1] = '\0';
367         if (!EnumSymbolsCallback(sym_info, sym_info->Size, UserContext)) break;
368     }
369     return TRUE;
370 }
371
372 /******************************************************************
373  *              symt_get_info
374  *
375  * Retrieves inforamtion about a symt (either symbol or type)
376  */
377 BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req, 
378                    void* pInfo)
379 {
380     unsigned            len;
381
382     if (!type) return FALSE;
383
384 /* helper to typecast pInfo to its expected type (_t) */
385 #define X(_t) (*((_t*)pInfo))
386
387     switch (req)
388     {
389     case TI_FINDCHILDREN:
390         {
391             const struct vector*        v;
392             struct symt**               pt;
393             unsigned                    i;
394             TI_FINDCHILDREN_PARAMS*     tifp = pInfo;
395
396             switch (type->tag)
397             {
398             case SymTagUDT:  v = &((struct symt_udt*)type)->vchildren; break;
399             case SymTagEnum: v = &((struct symt_enum*)type)->vchildren; break;
400             default:
401                 FIXME("Unsupported sym-tag %s for find-children\n", symt_get_tag_str(type->tag));
402                 return FALSE;
403             }
404             for (i = 0; i < tifp->Count; i++)
405             {
406                 if (!(pt = vector_at(v, tifp->Start + i))) return FALSE;
407                 tifp->ChildId[i] = (DWORD)*pt;
408             }
409         }
410         break;
411
412     case TI_GET_ADDRESS:
413         switch (type->tag)
414         {
415         case SymTagData:
416             switch (((struct symt_data*)type)->kind)
417             {
418             case DataIsGlobal:
419             case DataIsFileStatic:
420                 X(DWORD) = ((struct symt_data*)type)->u.address;
421                 break;
422             default: return FALSE;
423             }
424             break;
425         case SymTagFunction:
426             X(DWORD) = ((struct symt_function*)type)->addr;
427             break;
428         case SymTagPublicSymbol:
429             X(DWORD) = ((struct symt_public*)type)->address;
430             break;
431         default:
432             FIXME("Unsupported sym-tag %s for get-address\n", symt_get_tag_str(type->tag));
433             return FALSE;
434         }
435         break;
436
437 #if 0
438         /* this is wrong, we should return the type of the index, not the
439          * type of the array[0]
440          */
441     case TI_GET_ARRAYINDEXTYPEID:
442         if (type->tag != SymTagArrayType) return FALSE;
443         X(DWORD) = (DWORD)((struct symt_array*)type)->basetype;
444         break;
445 #endif
446
447     case TI_GET_BASETYPE:
448         if (type->tag != SymTagBaseType) return FALSE;
449         X(DWORD) = ((struct symt_basic*)type)->bt;
450         break;
451
452     case TI_GET_BITPOSITION:
453         if (type->tag != SymTagData || ((struct symt_data*)type)->location != LocIsBitField)
454             return FALSE;
455         X(DWORD) = ((struct symt_data*)type)->u.bitfield.position;
456         break;
457
458     case TI_GET_CHILDRENCOUNT:
459         switch (type->tag)
460         {
461         case SymTagUDT:
462             X(DWORD) = vector_length(&((struct symt_udt*)type)->vchildren);
463             break;
464         case SymTagEnum:
465             X(DWORD) = vector_length(&((struct symt_enum*)type)->vchildren);
466             break;
467         default:
468             FIXME("Unsupported sym-tag %s for get-children-count\n", symt_get_tag_str(type->tag));
469             /* fall through */
470         case SymTagPublicSymbol:
471         case SymTagPointerType:
472         case SymTagBaseType:
473             return FALSE;
474         }
475         break;
476
477     case TI_GET_COUNT:
478         if (type->tag != SymTagArrayType) return FALSE;
479         X(DWORD) = ((struct symt_array*)type)->end - 
480             ((struct symt_array*)type)->start;
481         break;
482
483     case TI_GET_DATAKIND:
484         if (type->tag != SymTagData) return FALSE;
485         X(DWORD) = ((struct symt_data*)type)->kind;
486         break;
487
488     case TI_GET_LENGTH:
489         switch (type->tag)
490         {
491         case SymTagBaseType:
492             X(DWORD) = ((struct symt_basic*)type)->size;
493             break;
494         case SymTagFunction:
495             X(DWORD) = ((struct symt_function*)type)->size;
496             break;
497         case SymTagPointerType:
498             X(DWORD) = sizeof(void*);
499             break;
500         case SymTagUDT:
501             X(DWORD) = ((struct symt_udt*)type)->size;
502             break;
503         case SymTagEnum:
504             X(DWORD) = sizeof(int);
505             break;
506         case SymTagData:
507             if (((struct symt_data*)type)->location == LocIsBitField)
508                 X(DWORD) = ((struct symt_data*)type)->u.bitfield.length;
509             else
510                 return symt_get_info(((struct symt_data*)type)->type, 
511                                      TI_GET_LENGTH, pInfo);
512             break;
513         case SymTagArrayType:   
514             if (!symt_get_info(((struct symt_array*)type)->basetype, 
515                                TI_GET_LENGTH, pInfo))
516                 return FALSE;
517             X(DWORD) *= ((struct symt_array*)type)->end - 
518                 ((struct symt_array*)type)->start;
519             break;
520         case SymTagPublicSymbol:
521             X(DWORD) = ((struct symt_public*)type)->size;
522             break;
523         default:
524             FIXME("Unsupported sym-tag %s for get-size\n", symt_get_tag_str(type->tag));
525             return 0;
526         }
527         break;
528
529     case TI_GET_LEXICALPARENT:
530         switch (type->tag)
531         {
532         case SymTagBlock:
533             X(DWORD) = (DWORD)((struct symt_block*)type)->container;
534             break;
535         case SymTagData:
536             X(DWORD) = (DWORD)((struct symt_data*)type)->container;
537             break;
538         default:
539             FIXME("Unsupported sym-tag %s for get-lexical-parent\n", symt_get_tag_str(type->tag));
540             return FALSE;
541         }
542         break;
543
544     case TI_GET_OFFSET:
545         switch (type->tag)
546         {
547         case SymTagData:
548             switch (((struct symt_data*)type)->location)
549             {
550             case LocIsRegRel:
551             case LocIsThisRel:  
552                 X(ULONG) = ((struct symt_data*)type)->u.offset; 
553                 break;
554             case LocIsConstant: 
555                 X(ULONG) = 0; /* FIXME ???? */
556                 break;
557             default:
558                 FIXME("Unknown location (%u) for get-offset\n", 
559                       ((struct symt_data*)type)->location);
560                 break;
561             }
562             break;
563         default:
564             FIXME("Unsupported sym-tag %s for get-offset\n", symt_get_tag_str(type->tag));
565             return FALSE;
566         }
567         break;
568
569     case TI_GET_SYMNAME:
570         {
571             const char* name = symt_get_name(type);
572             if (!name) return FALSE;
573             len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
574             X(WCHAR*) = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
575             if (!X(WCHAR*)) return FALSE;
576             MultiByteToWideChar(CP_ACP, 0, name, -1, X(WCHAR*), len);
577         }
578         break;
579
580     case TI_GET_SYMTAG:
581         X(DWORD) = type->tag;
582         break;
583
584     case TI_GET_TYPE:
585         switch (type->tag)
586         {
587         case SymTagArrayType:
588             X(DWORD) = (DWORD)((struct symt_array*)type)->basetype;
589             break;
590         case SymTagPointerType:
591             X(DWORD) = (DWORD)((struct symt_pointer*)type)->pointsto;
592             break;
593         case SymTagFunctionType:
594             X(DWORD) = (DWORD)((struct symt_function_signature*)type)->rettype;
595             break;
596         case SymTagData:
597             X(DWORD) = (DWORD)((struct symt_data*)type)->type; 
598             break;
599         default:
600             FIXME("Unsupported sym-tag %s for get-type\n", symt_get_tag_str(type->tag));
601             return FALSE;
602         }
603         break;
604
605     case TI_GET_TYPEID:
606         X(DWORD) = (DWORD)type; 
607         break;
608
609     case TI_GET_UDTKIND:
610         if (type->tag != SymTagUDT) return FALSE;
611         X(DWORD) = ((struct symt_udt*)type)->kind;
612         break;
613
614 #undef X
615
616     case TI_GET_ADDRESSOFFSET:
617     case TI_GET_ARRAYINDEXTYPEID:
618     case TI_GET_CALLING_CONVENTION:
619     case TI_GET_CLASSPARENTID:
620     case TI_GET_NESTED:
621     case TI_GET_SYMINDEX:
622     case TI_GET_THISADJUST:
623     case TI_GET_VALUE:
624     case TI_GET_VIRTUALBASECLASS:
625     case TI_GET_VIRTUALBASEPOINTEROFFSET:
626     case TI_GET_VIRTUALTABLESHAPEID:
627     case TI_IS_EQUIV_TO:
628         FIXME("Unsupported GetInfo request (%u)\n", req);
629         return FALSE;
630     }
631
632     return TRUE;
633 }
634
635 /******************************************************************
636  *              SymGetTypeInfo (DBGHELP.@)
637  *
638  */
639 BOOL WINAPI SymGetTypeInfo(HANDLE hProcess, unsigned long ModBase,
640                            ULONG TypeId, IMAGEHLP_SYMBOL_TYPE_INFO GetType,
641                            PVOID pInfo)
642 {
643     struct process*     pcs = process_find_by_handle(hProcess);
644
645     if (!pcs) return FALSE;
646 #if 0
647     struct module*      module;
648     module = module_find_by_addr(pcs, ModBase, DMT_UNKNOWN);
649     if (!(module = module_get_debug(pcs, module))) return FALSE;
650 #endif
651
652     return symt_get_info((struct symt*)TypeId, GetType, pInfo);
653 }
654
655 /******************************************************************
656  *              SymGetTypeFromName (DBGHELP.@)
657  *
658  */
659 BOOL WINAPI SymGetTypeFromName(HANDLE hProcess, unsigned long BaseOfDll,
660                                LPSTR Name, PSYMBOL_INFO Symbol)
661 {
662     struct process*     pcs = process_find_by_handle(hProcess);
663     struct module*      module;
664     struct symt*        type;
665
666     if (!pcs) return FALSE;
667     module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
668     if (!module) return FALSE;
669     type = symt_find_type_by_name(module, SymTagNull, Name);
670     if (!type) return FALSE;
671     Symbol->TypeIndex = (DWORD)type;
672
673     return TRUE;
674 }