How to use DbgHelp to access type information (figures)

Figure 1 - symbol types and tags in the first group

Symbol type Tag
Function SymTagFunction
Data SymTagData
PublicSymbol SymTagPublicSymbol
Block SymTagBlock
FuncDebugStart SymTagFuncDebugStart
FuncDebugEnd SymTagFuncDebugEnd
Label SymTagLabel
Thunk SymTagThunk

Figure 2 - symbol types and tags in the second group

Symbol type Tag
BaseType SymTagBaseType
Typedef SymTagTypedef
PointerType SymTagPointerType
Array SymTagArray
FunctionType SymTagFunctionType
FunctionArgType SymTagFunctionArgType
UDT SymTagUDT
BaseClass SymTagBaseClass
Enum SymTagEnum
Friend SymTagFriend

Figure 3 - how to obtain the name of a symbol

  WCHAR* pName = 0; 

  if( !SymGetTypeInfo( hProcess, ModBase, Index, TI_GET_SYMNAME, &pName ) )
  {
    DWORD ErrCode = GetLastError(); 
    if( ErrCode == 1 ) 
      wprintf( L„Property not supported“ ); 
    else 
      wprintf( L“Error: %u”, ErrCode ); 
  }
  else if( pName == 0 ) 
  {
    wprintf( L”Error” ); 
  }
  else 
  {
    wprintf( L”Name: %s”, pName );
    LocalFree( pName ); 
  }

Figure 4 - DbgHelp symbol property constants and the corresponding DIA property names

SymGetTypeInfo constant Property
TI_GET_BASETYPE BaseType
TI_GET_ARRAYINDEXTYPEID ArrayTypeIndex
TI_GET_BITPOSITION BitPosition
TI_GET_CALLING_CONVENTION CallingConvention
TI_GET_CLASSPARENTID ClassParent
TI_GET_DATAKIND DataKind
TI_GET_LENGTH Length
TI_GET_LEXICALPARENT LexicalParent
TI_GET_NESTED Nested
TI_GET_SYMINDEX SymIndexId
TI_GET_SYMTAG Tag
TI_GET_THISADJUST ThisAdjust
TI_GET_TYPEID Type
TI_GET_UDTKIND UdtKind
TI_GET_VALUE Value
TI_GET_VIRTUALBASECLASS VirtualBaseClass
TI_GET_VIRTUALBASEPOINTEROFFSET VirtualBasePointerOffset

Figure 5 - requesting child symbols of a symbol

  bool GetChildren
  ( 
    HANDLE   hProcess,    // [in]  Process handle 
    DWORD64  ModuleBase,  // [in]  Module base address 
    ULONG    Index,       // [in]  Index of the symbol whose children are needed 
    ULONG*   pChildren,   // [out] Points to the buffer that will receive the child indices 
    DWORD&   NumChildren, // [out] Number of children found 
    DWORD    MaxChildren  // [in]  Maximal number of child indices the buffer can store 
  ) 
  {
    // Check parameters 

    if( pChildren == 0 ) 
    {
      _ASSERTE( !_T("Array pointer is null.") ); 
      return false; 
    }
	
    if( MaxChildren == 0 ) 
    {
      _ASSERTE( !_T("Array size is invalid.") ); 
      return false; 
    }


    // Enumerate children 

    // Get the number of children 

    DWORD ChildCount = 0; 

    if( !SymGetTypeInfo( hProcess, ModuleBase, Index, TI_GET_CHILDRENCOUNT, &ChildCount ) ) 
    {
      DWORD ErrCode = GetLastError(); 
      _ASSERTE( !_T("SymGetTypeInfo(TI_GET_CHIDRENCOUNT) failed.") ); 
      return false; 
    }

    if( ChildCount == 0 ) 
    {
      // No children 
      NumChildren = 0; 
      return true; 
    }

    // Get the children 

    int FindChildrenSize = sizeof(TI_FINDCHILDREN_PARAMS) + ChildCount*sizeof(ULONG); 

    TI_FINDCHILDREN_PARAMS* pFC = (TI_FINDCHILDREN_PARAMS*)_alloca( FindChildrenSize ); 

    memset( pFC, 0, FindChildrenSize ); 

    pFC->Count = ChildCount; 

    if( !SymGetTypeInfo( hProcess, ModuleBase, Index, TI_FINDCHILDREN, pFC ) ) 
    {
      DWORD ErrCode = GetLastError(); 
      _ASSERTE( !_T("SymGetTypeInfo(TI_FINDCHILDREN) failed.") ); 
    return false; 
    }


    // Copy children to the [out] parameter 

    DWORD ChildIndex = 0; 

    for( DWORD i = 0; i < ChildCount; i++ ) 
   {
    // If we are only interested in children with a specific tag 
    // (e.g. if we are looking for members of a class), 
    // we can also check the tag here and decide whether to copy 
    // the child id (index) to the [out] array or not 

    pChildren[ChildIndex] = pFC->ChildId[i];

    ChildIndex++; 

    if( ChildIndex == MaxChildren ) 
      break; 

    }

    NumChildren = ChildIndex; 


    // Complete 

    return true; 
  }

Figure 6 - BasicType enumeration

  enum BasicType
  {
    btNoType = 0,
    btVoid = 1,
    btChar = 2,
    btWChar = 3,
    btInt = 6,
    btUInt = 7,
    btFloat = 8,
    btBCD = 9,
    btBool = 10,
    btLong = 13,
    btULong = 14,
    btCurrency = 25,
    btDate = 26,
    btVariant = 27,
    btComplex = 28,
    btBit = 29,
    btBSTR = 30,
    btHresult = 31
  };