403Webshell
Server IP : 121.121.20.254  /  Your IP : 216.73.216.202
Web Server : Microsoft-IIS/10.0
System : Windows NT WEB-SERVER 10.0 build 20348 (Windows Server 2022) AMD64
User : IUSR ( 0)
PHP Version : 8.3.28
Disable Function : NONE
MySQL : ON  |  cURL : ON  |  WGET : OFF  |  Perl : OFF  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /Program Files (x86)/Microsoft Visual Studio/18/BuildTools/DIA SDK/Samples/DIA2Dump/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /Program Files (x86)/Microsoft Visual Studio/18/BuildTools/DIA SDK/Samples/DIA2Dump/PrintSymbol.cpp
// PrintSymbol.cpp : Defines the printing procedures for the symbols
//
// This is a part of the Debug Interface Access SDK 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// This source code is only intended as a supplement to the
// Debug Interface Access SDK and related electronic documentation 
// provided with the library.
// See these sources for detailed information regarding the
// Debug Interface Access SDK API.
//

#include "stdafx.h"

#include <malloc.h>

#include "dia2.h"
#include "regs.h"
#include "PrintSymbol.h"

// Basic types
const wchar_t * const rgBaseType[] =
{
  L"<NoType>",                         // btNoType = 0,
  L"void",                             // btVoid = 1,
  L"char",                             // btChar = 2,
  L"wchar_t",                          // btWChar = 3,
  L"signed char",
  L"unsigned char",
  L"int",                              // btInt = 6,
  L"unsigned int",                     // btUInt = 7,
  L"float",                            // btFloat = 8,
  L"<BCD>",                            // btBCD = 9,
  L"bool",                             // btBool = 10,
  L"short",
  L"unsigned short",
  L"long",                             // btLong = 13,
  L"unsigned long",                    // btULong = 14,
  L"__int8",
  L"__int16",
  L"__int32",
  L"__int64",
  L"__int128",
  L"unsigned __int8",
  L"unsigned __int16",
  L"unsigned __int32",
  L"unsigned __int64",
  L"unsigned __int128",
  L"<currency>",                       // btCurrency = 25,
  L"<date>",                           // btDate = 26,
  L"VARIANT",                          // btVariant = 27,
  L"<complex>",                        // btComplex = 28,
  L"<bit>",                            // btBit = 29,
  L"BSTR",                             // btBSTR = 30,
  L"HRESULT",                          // btHresult = 31
  L"char16_t",                         // btChar16 = 32
  L"char32_t",                          // btChar32 = 33
  L"char8_t",                          // btChar8  = 34
};

// Tags returned by Dia
const wchar_t * const rgTags[] =
{
  L"(SymTagNull)",                     // SymTagNull
  L"Executable (Global)",              // SymTagExe
  L"Compiland",                        // SymTagCompiland
  L"CompilandDetails",                 // SymTagCompilandDetails
  L"CompilandEnv",                     // SymTagCompilandEnv
  L"Function",                         // SymTagFunction
  L"Block",                            // SymTagBlock
  L"Data",                             // SymTagData
  L"Annotation",                       // SymTagAnnotation
  L"Label",                            // SymTagLabel
  L"PublicSymbol",                     // SymTagPublicSymbol
  L"UserDefinedType",                  // SymTagUDT
  L"Enum",                             // SymTagEnum
  L"FunctionType",                     // SymTagFunctionType
  L"PointerType",                      // SymTagPointerType
  L"ArrayType",                        // SymTagArrayType
  L"BaseType",                         // SymTagBaseType
  L"Typedef",                          // SymTagTypedef
  L"BaseClass",                        // SymTagBaseClass
  L"Friend",                           // SymTagFriend
  L"FunctionArgType",                  // SymTagFunctionArgType
  L"FuncDebugStart",                   // SymTagFuncDebugStart
  L"FuncDebugEnd",                     // SymTagFuncDebugEnd
  L"UsingNamespace",                   // SymTagUsingNamespace
  L"VTableShape",                      // SymTagVTableShape
  L"VTable",                           // SymTagVTable
  L"Custom",                           // SymTagCustom
  L"Thunk",                            // SymTagThunk
  L"CustomType",                       // SymTagCustomType
  L"ManagedType",                      // SymTagManagedType
  L"Dimension",                        // SymTagDimension
  L"CallSite",                         // SymTagCallSite
  L"InlineSite",                       // SymTagInlineSite
  L"BaseInterface",                    // SymTagBaseInterface
  L"VectorType",                       // SymTagVectorType
  L"MatrixType",                       // SymTagMatrixType
  L"HLSLType",                         // SymTagHLSLType
  L"Caller",                           // SymTagCaller,
  L"Callee",                           // SymTagCallee,
  L"Export",                           // SymTagExport,
  L"HeapAllocationSite",               // SymTagHeapAllocationSite
  L"CoffGroup",                        // SymTagCoffGroup
  L"Inlinee",                          // SymTagInlinee
  L"TaggedUnionCase",                  // SymTagTaggedUnionCase
};


// Processors
const wchar_t * const rgFloatPackageStrings[] =
{
  L"hardware processor (80x87 for Intel processors)",    // CV_CFL_NDP
  L"emulator",                                           // CV_CFL_EMU
  L"altmath",                                            // CV_CFL_ALT
  L"???"
};

const wchar_t * const rgProcessorStrings[] =
{
  L"8080",                             //  CV_CFL_8080
  L"8086",                             //  CV_CFL_8086
  L"80286",                            //  CV_CFL_80286
  L"80386",                            //  CV_CFL_80386
  L"80486",                            //  CV_CFL_80486
  L"Pentium",                          //  CV_CFL_PENTIUM
  L"Pentium Pro/Pentium II",           //  CV_CFL_PENTIUMII/CV_CFL_PENTIUMPRO
  L"Pentium III",                      //  CV_CFL_PENTIUMIII
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"MIPS (Generic)",                   //  CV_CFL_MIPSR4000
  L"MIPS16",                           //  CV_CFL_MIPS16
  L"MIPS32",                           //  CV_CFL_MIPS32
  L"MIPS64",                           //  CV_CFL_MIPS64
  L"MIPS I",                           //  CV_CFL_MIPSI
  L"MIPS II",                          //  CV_CFL_MIPSII
  L"MIPS III",                         //  CV_CFL_MIPSIII
  L"MIPS IV",                          //  CV_CFL_MIPSIV
  L"MIPS V",                           //  CV_CFL_MIPSV
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"M68000",                           //  CV_CFL_M68000
  L"M68010",                           //  CV_CFL_M68010
  L"M68020",                           //  CV_CFL_M68020
  L"M68030",                           //  CV_CFL_M68030
  L"M68040",                           //  CV_CFL_M68040
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"Alpha 21064",                      // CV_CFL_ALPHA, CV_CFL_ALPHA_21064
  L"Alpha 21164",                      // CV_CFL_ALPHA_21164
  L"Alpha 21164A",                     // CV_CFL_ALPHA_21164A
  L"Alpha 21264",                      // CV_CFL_ALPHA_21264
  L"Alpha 21364",                      // CV_CFL_ALPHA_21364
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"PPC 601",                          // CV_CFL_PPC601
  L"PPC 603",                          // CV_CFL_PPC603
  L"PPC 604",                          // CV_CFL_PPC604
  L"PPC 620",                          // CV_CFL_PPC620
  L"PPC w/FP",                         // CV_CFL_PPCFP
  L"PPC (Big Endian)",                 // CV_CFL_PPCBE
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"SH3",                              // CV_CFL_SH3
  L"SH3E",                             // CV_CFL_SH3E
  L"SH3DSP",                           // CV_CFL_SH3DSP
  L"SH4",                              // CV_CFL_SH4
  L"SHmedia",                          // CV_CFL_SHMEDIA
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"ARM3",                             // CV_CFL_ARM3
  L"ARM4",                             // CV_CFL_ARM4
  L"ARM4T",                            // CV_CFL_ARM4T
  L"ARM5",                             // CV_CFL_ARM5
  L"ARM5T",                            // CV_CFL_ARM5T
  L"ARM6",                             // CV_CFL_ARM6
  L"ARM (XMAC)",                       // CV_CFL_ARM_XMAC
  L"ARM (WMMX)",                       // CV_CFL_ARM_WMMX
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"Omni",                             // CV_CFL_OMNI
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"Itanium",                          // CV_CFL_IA64, CV_CFL_IA64_1
  L"Itanium (McKinley)",               // CV_CFL_IA64_2
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"CEE",                              // CV_CFL_CEE
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"AM33",                             // CV_CFL_AM33
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"M32R",                             // CV_CFL_M32R
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"TriCore",                          // CV_CFL_TRICORE
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"x64",                              // CV_CFL_X64
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"EBC",                              // CV_CFL_EBC
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"Thumb (CE)",                       // CV_CFL_THUMB
  L"???",
  L"???",
  L"???",
  L"ARM",                              // CV_CFL_ARMNT
  L"???",
  L"ARM64",                            // CV_CFL_ARM64
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"???",
  L"UNKNOWN",                          // CV_CFL_UNKNOWN
  L"D3D11_SHADE",                      // CV_CFL_D3D11_SHADER
};

const wchar_t * const rgDataKind[] =
{
  L"Unknown",
  L"Local",
  L"Static Local",
  L"Param",
  L"Object Ptr",
  L"File Static",
  L"Global",
  L"Member",
  L"Static Member",
  L"Constant",
};

const wchar_t * const rgUdtKind[] =
{
  L"struct",
  L"class",
  L"union",
  L"interface",
  L"tagged union",
};

const wchar_t * const rgAccess[] =
{
  L"",                     // No access specifier
  L"private",
  L"protected",
  L"public"
};

const wchar_t * const rgCallingConvention[] =
{
  L"CV_CALL_NEAR_C      ",
  L"CV_CALL_FAR_C       ",
  L"CV_CALL_NEAR_PASCAL ",
  L"CV_CALL_FAR_PASCAL  ",
  L"CV_CALL_NEAR_FAST   ",
  L"CV_CALL_FAR_FAST    ",
  L"CV_CALL_SKIPPED     ",
  L"CV_CALL_NEAR_STD    ",
  L"CV_CALL_FAR_STD     ",
  L"CV_CALL_NEAR_SYS    ",
  L"CV_CALL_FAR_SYS     ",
  L"CV_CALL_THISCALL    ",
  L"CV_CALL_MIPSCALL    ",
  L"CV_CALL_GENERIC     ",
  L"CV_CALL_ALPHACALL   ",
  L"CV_CALL_PPCCALL     ",
  L"CV_CALL_SHCALL      ",
  L"CV_CALL_ARMCALL     ",
  L"CV_CALL_AM33CALL    ",
  L"CV_CALL_TRICALL     ",
  L"CV_CALL_SH5CALL     ",
  L"CV_CALL_M32RCALL    ",
  L"CV_ALWAYS_INLINED   ",
  L"CV_CALL_NEAR_VECTOR ",
  L"CV_CALL_SWIFT       ",
  L"CV_CALL_RESERVED    "
};

const wchar_t * const rgLanguage[] =
{
  L"C",                                // CV_CFL_C
  L"C++",                              // CV_CFL_CXX
  L"FORTRAN",                          // CV_CFL_FORTRAN
  L"MASM",                             // CV_CFL_MASM
  L"Pascal",                           // CV_CFL_PASCAL
  L"Basic",                            // CV_CFL_BASIC
  L"COBOL",                            // CV_CFL_COBOL
  L"LINK",                             // CV_CFL_LINK
  L"CVTRES",                           // CV_CFL_CVTRES
  L"CVTPGD",                           // CV_CFL_CVTPGD
  L"C#",                               // CV_CFL_CSHARP
  L"Visual Basic",                     // CV_CFL_VB
  L"ILASM",                            // CV_CFL_ILASM
  L"Java",                             // CV_CFL_JAVA
  L"JScript",                          // CV_CFL_JSCRIPT
  L"MSIL",                             // CV_CFL_MSIL
  L"HLSL",                             // CV_CFL_HLSL
  L"Objective-C",                      // CV_CFL_OBJC
  L"Objective-C++",                    // CV_CFL_OBJCXX
  L"Swift",                            // CV_CFL_SWIFT
  L"ALIASOBJ",                         // CV_CFL_ALIASOBJ
  L"Rust",                             // CV_CFL_RUST
  L"Go",                               // CV_CFL_GO
};

const wchar_t * const rgLocationTypeString[] =
{
  L"NULL",
  L"static",
  L"TLS",
  L"RegRel",
  L"ThisRel",
  L"Enregistered",
  L"BitField",
  L"Slot",
  L"IL Relative",
  L"In MetaData",
  L"Constant",
  L"RegRelAliasIndir"
};


////////////////////////////////////////////////////////////
// Print a public symbol info: name, VA, RVA, SEG:OFF
//
void PrintPublicSymbol(IDiaSymbol *pSymbol)
{
  DWORD dwSymTag;
  DWORD dwRVA;
  DWORD dwSeg;
  DWORD dwOff;
  BSTR bstrName;
  
  if (pSymbol->get_symTag(&dwSymTag) != S_OK) {
    return;
  }

  if (pSymbol->get_relativeVirtualAddress(&dwRVA) != S_OK) {
    dwRVA = 0xFFFFFFFF;
  }

  pSymbol->get_addressSection(&dwSeg);
  pSymbol->get_addressOffset(&dwOff);

  wprintf(L"%s: [%08X][%04X:%08X] ", rgTags[dwSymTag], dwRVA, dwSeg, dwOff);
  
  if (dwSymTag == SymTagThunk) {
    if (pSymbol->get_name(&bstrName) == S_OK) {
      wprintf(L"%s\n", bstrName);

      SysFreeString(bstrName);
    }

    else {
      if (pSymbol->get_targetRelativeVirtualAddress(&dwRVA) != S_OK) {
        dwRVA = 0xFFFFFFFF;
      }

      pSymbol->get_targetSection(&dwSeg);
      pSymbol->get_targetOffset(&dwOff);

      wprintf(L"target -> [%08X][%04X:%08X]\n", dwRVA, dwSeg, dwOff);
    }
  }

  else {
    // must be a function or a data symbol

    BSTR bstrUndname;

    if (pSymbol->get_name(&bstrName) == S_OK) {
      if (pSymbol->get_undecoratedName(&bstrUndname) == S_OK) {
        wprintf(L"%s(%s)\n", bstrName, bstrUndname);

        SysFreeString(bstrUndname);
      }

      else {
        wprintf(L"%s\n", bstrName);
      }

      SysFreeString(bstrName);
    }
  }
}

////////////////////////////////////////////////////////////
// Print a global symbol info: name, VA, RVA, SEG:OFF
//
void PrintGlobalSymbol(IDiaSymbol *pSymbol)
{
  DWORD dwSymTag;
  DWORD dwRVA;
  DWORD dwSeg;
  DWORD dwOff;
  
  if (pSymbol->get_symTag(&dwSymTag) != S_OK) {
    return;
  }

  if (pSymbol->get_relativeVirtualAddress(&dwRVA) != S_OK) {
    dwRVA = 0xFFFFFFFF;
  }

  pSymbol->get_addressSection(&dwSeg);
  pSymbol->get_addressOffset(&dwOff);

  wprintf(L"%s: [%08X][%04X:%08X] ", rgTags[dwSymTag], dwRVA, dwSeg, dwOff);
  
  if (dwSymTag == SymTagThunk) {
    BSTR bstrName;

    if (pSymbol->get_name(&bstrName) == S_OK) {
      wprintf(L"%s\n", bstrName);

      SysFreeString(bstrName);
    }

    else {
      if (pSymbol->get_targetRelativeVirtualAddress(&dwRVA) != S_OK) {
        dwRVA = 0xFFFFFFFF;
      }

      pSymbol->get_targetSection(&dwSeg);
      pSymbol->get_targetOffset(&dwOff);
      wprintf(L"target -> [%08X][%04X:%08X]\n", dwRVA, dwSeg, dwOff);
    }
  }

  else {
    BSTR bstrName;
    BSTR bstrUndname;

    if (pSymbol->get_name(&bstrName) == S_OK) {
      if (pSymbol->get_undecoratedName(&bstrUndname) == S_OK) {
        wprintf(L"%s(%s)\n", bstrName, bstrUndname);

        SysFreeString(bstrUndname);
      }

      else {
        wprintf(L"%s\n", bstrName);
      }

      SysFreeString(bstrName);
    }
  }
}

////////////////////////////////////////////////////////////
// Print a callsite symbol info: SEG:OFF, RVA, type
//
void PrintCallSiteInfo(IDiaSymbol *pSymbol)
{
  DWORD dwISect, dwOffset;
  if (pSymbol->get_addressSection(&dwISect) == S_OK &&
    pSymbol->get_addressOffset(&dwOffset) == S_OK) {
    wprintf(L"[0x%04x:0x%08x]  ", dwISect, dwOffset);
  }

  DWORD rva;
  if (pSymbol->get_relativeVirtualAddress(&rva) == S_OK) {
    wprintf(L"0x%08X  ", rva);
  }

  IDiaSymbol *pFuncType;
  if (pSymbol->get_type(&pFuncType) == S_OK) {
    DWORD tag;
    if (pFuncType->get_symTag(&tag) == S_OK) {
      switch(tag)
      {
        case SymTagFunctionType:
          PrintFunctionType(pSymbol);
          break;
        case SymTagPointerType:
          PrintFunctionType(pFuncType);
          break;
        default:
          wprintf(L"???\n");
          break;
      }
    }
    pFuncType->Release();
  }
}

////////////////////////////////////////////////////////////
// Print a callsite symbol info: SEG:OFF, RVA, type
//
void PrintHeapAllocSite(IDiaSymbol *pSymbol)
{
  DWORD dwISect, dwOffset;
  if (pSymbol->get_addressSection(&dwISect) == S_OK &&
    pSymbol->get_addressOffset(&dwOffset) == S_OK) {
    wprintf(L"[0x%04x:0x%08x]  ", dwISect, dwOffset);
  }

  DWORD rva;
  if (pSymbol->get_relativeVirtualAddress(&rva) == S_OK) {
    wprintf(L"0x%08X  ", rva);
  }

  IDiaSymbol *pAllocType;
  if (pSymbol->get_type(&pAllocType) == S_OK) {
    PrintType(pAllocType);
    pAllocType->Release();
  }
}

////////////////////////////////////////////////////////////
// Print a COFF group symbol info: SEG:OFF, RVA, length, name
//
void PrintCoffGroup(IDiaSymbol *pSymbol)
{
  DWORD dwISect, dwOffset;
  if (pSymbol->get_addressSection(&dwISect) == S_OK &&
    pSymbol->get_addressOffset(&dwOffset) == S_OK) {
    wprintf(L"[0x%04x:0x%08x]  ", dwISect, dwOffset);
  }

  DWORD rva;
  if (pSymbol->get_relativeVirtualAddress(&rva) == S_OK) {
    wprintf(L"0x%08X, ", rva);
  }

  ULONGLONG ulLen;
  if (pSymbol->get_length(&ulLen) == S_OK) {
    wprintf(L"len = %08X, ", (ULONG)ulLen);
  }

  DWORD characteristics;
  if (pSymbol->get_characteristics(&characteristics) == S_OK) {
    wprintf(L"characteristics = %08X, ", characteristics);
  }

  PrintName(pSymbol);
}

////////////////////////////////////////////////////////////
// Print a symbol info: name, type etc.
//
void PrintSymbol(IDiaSymbol *pSymbol, DWORD dwIndent)
{
  IDiaSymbol *pType;
  DWORD dwSymTag;
  ULONGLONG ulLen;
  
  if (pSymbol->get_symTag(&dwSymTag) != S_OK) {
    wprintf(L"ERROR - PrintSymbol get_symTag() failed\n");
    return;
  }

  if (dwSymTag == SymTagFunction) {
    putwchar(L'\n');
  }

  PrintSymTag(dwSymTag);

  for (DWORD i = 0; i < dwIndent; i++) {
    putwchar(L' ');
  }

  switch (dwSymTag) {
    case SymTagCompilandDetails:
      PrintCompilandDetails(pSymbol);
      break;

    case SymTagCompilandEnv:
      PrintCompilandEnv(pSymbol);
      break;

    case SymTagData:
      PrintData(pSymbol);
      break;

    case SymTagFunction:
    case SymTagBlock:
      PrintLocation(pSymbol);

      if (pSymbol->get_length(&ulLen) == S_OK) {
        wprintf(L", len = %08X, ", (ULONG)ulLen);
      }

      if (dwSymTag == SymTagFunction) {
        DWORD dwCall;

        if (pSymbol->get_callingConvention(&dwCall) == S_OK) {
          wprintf(L", %s", SafeDRef(rgCallingConvention, dwCall));
        }
      }

      PrintUndName(pSymbol);
      putwchar(L'\n');

      if (dwSymTag == SymTagFunction)
      {
        BOOL f;

        for (DWORD i = 0; i < dwIndent; i++) {
          putwchar(L' ');
        }
        wprintf(L"                 Function attribute:");

        if ((pSymbol->get_isCxxReturnUdt(&f) == S_OK) && f) {
          wprintf(L" return user defined type (C++ style)");
        }
        if ((pSymbol->get_constructor(&f) == S_OK) && f) {
          wprintf(L" instance constructor");
        }
        if ((pSymbol->get_isConstructorVirtualBase(&f) == S_OK) && f) {
          wprintf(L" instance constructor of a class with virtual base");
        }
        putwchar (L'\n');

        for (DWORD i = 0; i < dwIndent; i++) {
          putwchar(L' ');
        }
        wprintf(L"                 Function info:");

        if ((pSymbol->get_hasAlloca(&f) == S_OK) && f) {
          wprintf(L" alloca");
        }

        if ((pSymbol->get_hasSetJump(&f) == S_OK) && f) {
          wprintf(L" setjmp");
        }

        if ((pSymbol->get_hasLongJump(&f) == S_OK) && f) {
          wprintf(L" longjmp");
        }

        if ((pSymbol->get_hasInlAsm(&f) == S_OK) && f) {
          wprintf(L" inlasm");
        }

        if ((pSymbol->get_hasEH(&f) == S_OK) && f) {
          wprintf(L" eh");
        }

        if ((pSymbol->get_inlSpec(&f) == S_OK) && f) {
          wprintf(L" inl_specified");
        }

        if ((pSymbol->get_hasSEH(&f) == S_OK) && f) {
          wprintf(L" seh");
        }

        if ((pSymbol->get_isNaked(&f) == S_OK) && f) {
          wprintf(L" naked");
        }

        if ((pSymbol->get_hasSecurityChecks(&f) == S_OK) && f) {
          wprintf(L" gschecks");
        }

        if ((pSymbol->get_isSafeBuffers(&f) == S_OK) && f) {
          wprintf(L" safebuffers");
        }

        if ((pSymbol->get_hasEHa(&f) == S_OK) && f) {
          wprintf(L" asyncheh");
        }

        if ((pSymbol->get_noStackOrdering(&f) == S_OK) && f) {
          wprintf(L" gsnostackordering");
        }

        if ((pSymbol->get_wasInlined(&f) == S_OK) && f) {
          wprintf(L" wasinlined");
        }

        if ((pSymbol->get_strictGSCheck(&f) == S_OK) && f) {
          wprintf(L" strict_gs_check");
        }

        putwchar(L'\n');

        DWORD regnum;
        if (pSymbol->get_paramBasePointerRegisterId(&regnum) == S_OK) {
          for (DWORD i = 0; i < dwIndent; i++) {
            putwchar(L' ');
          }
          wprintf(L"                 parameter base pointer register: %s\n", SzNameC7Reg((USHORT) regnum));
        }

        if (pSymbol->get_localBasePointerRegisterId(&regnum) == S_OK) {
          for (DWORD i = 0; i < dwIndent; i++) {
            putwchar(L' ');
          }
          wprintf(L"                 local base pointer register: %s\n", SzNameC7Reg((USHORT) regnum));
        }

        if ((pSymbol->get_framePointerPresent(&f) == S_OK) && f) {
          for (DWORD i = 0; i < dwIndent; i++) {
            putwchar(L' ');
          }
          wprintf(L"                 Frame pointer present\n");
        }

        if ((pSymbol->get_optimizedCodeDebugInfo(&f) == S_OK) && f) {
          for (DWORD i = 0; i < dwIndent; i++) {
            putwchar(L' ');
          }
          wprintf(L"                 Contains debug info for optimized code\n");
        }

        BSTR phaseName = NULL;
        if (pSymbol->get_phaseName(&phaseName) == S_OK) {
          for (DWORD i = 0; i < dwIndent; i++) {
            putwchar(L' ');
          }
          wprintf(L"                 Phase Name: %s\n", static_cast<BSTR>(phaseName));

          SysFreeString(phaseName);
        }
      }

      IDiaEnumSymbols *pEnumChildren;

      if (SUCCEEDED(pSymbol->findChildren(SymTagNull, NULL, nsNone, &pEnumChildren))) {
        IDiaSymbol *pChild;
        ULONG celt = 0;

        while (SUCCEEDED(pEnumChildren->Next(1, &pChild, &celt)) && (celt == 1)) {
          PrintSymbol(pChild, dwIndent + 2);
          pChild->Release();
        }

        pEnumChildren->Release();
      }
      return;

    case SymTagAnnotation:
      PrintLocation(pSymbol);
      putwchar(L'\n');
      break;

    case SymTagLabel:
      PrintLocation(pSymbol);
      wprintf(L", ");
      PrintName(pSymbol);
      break;

    case SymTagEnum:
    case SymTagTypedef:
    case SymTagUDT:
    case SymTagBaseClass:
      PrintUDT(pSymbol);
      break;

    case SymTagFuncDebugStart:
    case SymTagFuncDebugEnd:
      PrintLocation(pSymbol);
      break;

    case SymTagFunctionArgType:
    case SymTagFunctionType:
    case SymTagPointerType:
    case SymTagArrayType:
    case SymTagBaseType:
      if (pSymbol->get_type(&pType) == S_OK) {
        PrintType(pType);
        pType->Release();
      }

      putwchar(L'\n');
      break;

    case SymTagThunk:
      PrintThunk(pSymbol);
      break;

    case SymTagCallSite:
      PrintCallSiteInfo(pSymbol);
      break;

    case SymTagHeapAllocationSite:
      PrintHeapAllocSite(pSymbol);
      break;

    case SymTagCoffGroup:
      PrintCoffGroup(pSymbol);
      break;
        
    default:
      PrintName(pSymbol);

      if (pSymbol->get_type(&pType) == S_OK) {
        wprintf(L" has type ");
        PrintType(pType);
        pType->Release();
      }
  }

  if ((dwSymTag == SymTagUDT) || (dwSymTag == SymTagAnnotation)) {
    IDiaEnumSymbols *pEnumChildren;

    putwchar(L'\n');

    if (SUCCEEDED(pSymbol->findChildren(SymTagNull, NULL, nsNone, &pEnumChildren))) {
      IDiaSymbol *pChild;
      ULONG celt = 0;

      while (SUCCEEDED(pEnumChildren->Next(1, &pChild, &celt)) && (celt == 1)) {
        PrintSymbol(pChild, dwIndent + 2);
        pChild->Release();
      }

      pEnumChildren->Release();
    }
  }
  putwchar(L'\n');
}

////////////////////////////////////////////////////////////
// Print the string coresponding to the symbol's tag property
//
void PrintSymTag(DWORD dwSymTag)
{
  wprintf(L"%-15s: ", SafeDRef(rgTags, dwSymTag));
}

////////////////////////////////////////////////////////////
// Print the name of the symbol
//
void PrintName(IDiaSymbol *pSymbol)
{
  BSTR bstrName;
  BSTR bstrUndName;

  if (pSymbol->get_name(&bstrName) != S_OK) {
    wprintf(L"(none)");
    return;
  }

  if (pSymbol->get_undecoratedName(&bstrUndName) == S_OK) {
    if (wcscmp(bstrName, bstrUndName) == 0) {
      wprintf(L"%s", bstrName);
    }

    else {
      wprintf(L"%s(%s)", bstrUndName, bstrName);
    }

    SysFreeString(bstrUndName);
  }

  else {
    wprintf(L"%s", bstrName);
  }

  SysFreeString(bstrName);
}

////////////////////////////////////////////////////////////
// Print the undecorated name of the symbol
//  - only SymTagFunction, SymTagData and SymTagPublicSymbol
//    can have this property set
//
void PrintUndName(IDiaSymbol *pSymbol)
{
  BSTR bstrName;

  if (pSymbol->get_undecoratedName(&bstrName) != S_OK) {
    if (pSymbol->get_name(&bstrName) == S_OK) {
      // Print the name of the symbol instead

      wprintf(L"%s", (bstrName[0] != L'\0') ? bstrName : L"(none)");

      SysFreeString(bstrName);
    }

    else {
      wprintf(L"(none)");
    }

    return;
  }

  if (bstrName[0] != L'\0') {
    wprintf(L"%s", bstrName);
  }

  SysFreeString(bstrName);
}

////////////////////////////////////////////////////////////
// Print a SymTagThunk symbol's info
//
void PrintThunk(IDiaSymbol *pSymbol)
{
  DWORD dwRVA;
  DWORD dwISect;
  DWORD dwOffset;

  if ((pSymbol->get_relativeVirtualAddress(&dwRVA) == S_OK) &&
      (pSymbol->get_addressSection(&dwISect) == S_OK) &&
      (pSymbol->get_addressOffset(&dwOffset) == S_OK)) {
    wprintf(L"[%08X][%04X:%08X]", dwRVA, dwISect, dwOffset);
  }

  if ((pSymbol->get_targetSection(&dwISect) == S_OK) &&
      (pSymbol->get_targetOffset(&dwOffset) == S_OK) &&
      (pSymbol->get_targetRelativeVirtualAddress(&dwRVA) == S_OK)) {
    wprintf(L", target [%08X][%04X:%08X] ", dwRVA, dwISect, dwOffset);
  }

  else {
    wprintf(L", target ");

    PrintName(pSymbol);
  }
}

////////////////////////////////////////////////////////////
// Print the compiland/module details: language, platform...
//
void PrintCompilandDetails(IDiaSymbol *pSymbol)
{
  DWORD dwLanguage;

  if (pSymbol->get_language(&dwLanguage) == S_OK) {
    wprintf(L"\n\tLanguage: %s\n", SafeDRef(rgLanguage, dwLanguage));
  }

  DWORD dwPlatform;

  if (pSymbol->get_platform(&dwPlatform) == S_OK) {
    wprintf(L"\tTarget processor: %s\n", SafeDRef(rgProcessorStrings, dwPlatform));
  }

  BOOL fEC;

  if (pSymbol->get_editAndContinueEnabled(&fEC) == S_OK) {
    if (fEC) {
      wprintf(L"\tCompiled for edit and continue: yes\n");
    }

    else {
      wprintf(L"\tCompiled for edit and continue: no\n");
    }
  }

  BOOL fDbgInfo;

  if (pSymbol->get_hasDebugInfo(&fDbgInfo) == S_OK) {
    if (fDbgInfo) {
      wprintf(L"\tCompiled without debugging info: no\n");
    }

    else {
      wprintf(L"\tCompiled without debugging info: yes\n");
    }
  }

  BOOL fLTCG;

  if (pSymbol->get_isLTCG(&fLTCG) == S_OK) {
    if (fLTCG) {
      wprintf(L"\tCompiled with LTCG: yes\n");
    }

    else {
      wprintf(L"\tCompiled with LTCG: no\n");
    }
  }

  BOOL fDataAlign;

  if (pSymbol->get_isDataAligned(&fDataAlign) == S_OK) {
    if (fDataAlign) {
      wprintf(L"\tCompiled with /bzalign: no\n");
    }

    else {
      wprintf(L"\tCompiled with /bzalign: yes\n");
    }
  }

  BOOL fManagedPresent;

  if (pSymbol->get_hasManagedCode(&fManagedPresent) == S_OK) {
    if (fManagedPresent) {
      wprintf(L"\tManaged code present: yes\n");
    }

    else {
      wprintf(L"\tManaged code present: no\n");
    }
  }

  BOOL fSecurityChecks;

  if (pSymbol->get_hasSecurityChecks(&fSecurityChecks) == S_OK) {
    if (fSecurityChecks) {
      wprintf(L"\tCompiled with /GS: yes\n");
    }

    else {
      wprintf(L"\tCompiled with /GS: no\n");
    }
  }

  BOOL fSdl;

  if (pSymbol->get_isSdl(&fSdl) == S_OK) {
    if (fSdl) {
      wprintf(L"\tCompiled with /sdl: yes\n");
    }

    else {
      wprintf(L"\tCompiled with /sdl: no\n");
    }
  }

  BOOL fHotPatch;

  if (pSymbol->get_isHotpatchable(&fHotPatch) == S_OK) {
    if (fHotPatch) {
      wprintf(L"\tCompiled with /hotpatch: yes\n");
    }

    else {
      wprintf(L"\tCompiled with /hotpatch: no\n");
    }
  }

  BOOL fCVTCIL;

  if (pSymbol->get_isCVTCIL(&fCVTCIL) == S_OK) {
    if (fCVTCIL) {
      wprintf(L"\tConverted by CVTCIL: yes\n");
    }

    else {
      wprintf(L"\tConverted by CVTCIL: no\n");
    }
  }

  BOOL fMSILModule;

  if (pSymbol->get_isMSILNetmodule(&fMSILModule) == S_OK) {
    if (fMSILModule) {
      wprintf(L"\tMSIL module: yes\n");
    }

    else {
      wprintf(L"\tMSIL module: no\n");
    }
  }

  DWORD dwVerMajor;
  DWORD dwVerMinor;
  DWORD dwVerBuild;
  DWORD dwVerQFE;

  if ((pSymbol->get_frontEndMajor(&dwVerMajor) == S_OK) &&
      (pSymbol->get_frontEndMinor(&dwVerMinor) == S_OK) &&
      (pSymbol->get_frontEndBuild(&dwVerBuild) == S_OK)) {
    wprintf(L"\tFrontend Version: Major = %u, Minor = %u, Build = %u",
            dwVerMajor,
            dwVerMinor,
            dwVerBuild);

    if (pSymbol->get_frontEndQFE(&dwVerQFE) == S_OK) {
      wprintf(L", QFE = %u", dwVerQFE);
    }

    putwchar(L'\n');
  }

  if ((pSymbol->get_backEndMajor(&dwVerMajor) == S_OK) &&
      (pSymbol->get_backEndMinor(&dwVerMinor) == S_OK) &&
      (pSymbol->get_backEndBuild(&dwVerBuild) == S_OK)) {
    wprintf(L"\tBackend Version: Major = %u, Minor = %u, Build = %u",
            dwVerMajor,
            dwVerMinor,
            dwVerBuild);

    if (pSymbol->get_backEndQFE(&dwVerQFE) == S_OK) {
      wprintf(L", QFE = %u", dwVerQFE);
    }

    putwchar(L'\n');
  }

  BSTR bstrCompilerName;

  if (pSymbol->get_compilerName(&bstrCompilerName) == S_OK) {
    if (bstrCompilerName != NULL) {
      wprintf(L"\tVersion string: %s", bstrCompilerName);

      SysFreeString(bstrCompilerName);
    }
  }

  putwchar(L'\n');
}

////////////////////////////////////////////////////////////
// Print the compilan/module env
//
void PrintCompilandEnv(IDiaSymbol *pSymbol)
{
  PrintName(pSymbol);
  wprintf(L" =");

  VARIANT vt = { VT_EMPTY };

  if (pSymbol->get_value(&vt) == S_OK) {
    PrintVariant(vt);
    VariantClear((VARIANTARG *) &vt);
  }
}

////////////////////////////////////////////////////////////
// Print a string corespondig to a location type
//
void PrintLocation(IDiaSymbol *pSymbol)
{
  DWORD dwLocType;
  DWORD dwRVA, dwSect, dwOff, dwReg, dwBitPos, dwSlot;
  LONG lOffset;
  ULONGLONG ulLen;
  VARIANT vt = { VT_EMPTY };

  if (pSymbol->get_locationType(&dwLocType) != S_OK) {
    // It must be a symbol in optimized code

    wprintf(L"symbol in optmized code");
    return;
  }

  switch (dwLocType) {
    case LocIsStatic:
      if ((pSymbol->get_relativeVirtualAddress(&dwRVA) == S_OK) &&
          (pSymbol->get_addressSection(&dwSect) == S_OK) &&
          (pSymbol->get_addressOffset(&dwOff) == S_OK)) {
        wprintf(L"%s, [%08X][%04X:%08X]", SafeDRef(rgLocationTypeString, dwLocType), dwRVA, dwSect, dwOff);
      }
      break;

    case LocIsTLS:
    case LocInMetaData:
    case LocIsIlRel:
      if ((pSymbol->get_relativeVirtualAddress(&dwRVA) == S_OK) &&
          (pSymbol->get_addressSection(&dwSect) == S_OK) &&
          (pSymbol->get_addressOffset(&dwOff) == S_OK)) {
        wprintf(L"%s, [%08X][%04X:%08X]", SafeDRef(rgLocationTypeString, dwLocType), dwRVA, dwSect, dwOff);
      }
      break;

    case LocIsRegRel:
      if ((pSymbol->get_registerId(&dwReg) == S_OK) &&
          (pSymbol->get_offset(&lOffset) == S_OK)) {
        wprintf(L"%s Relative, [%08X]", SzNameC7Reg((USHORT) dwReg), lOffset);
      }
      break;

    case LocIsThisRel:
      if (pSymbol->get_offset(&lOffset) == S_OK) {
        wprintf(L"this+0x%X", lOffset);
      }
      break;

    case LocIsBitField:
      if ((pSymbol->get_offset(&lOffset) == S_OK) &&
          (pSymbol->get_bitPosition(&dwBitPos) == S_OK) &&
          (pSymbol->get_length(&ulLen) == S_OK)) {
        wprintf(L"this(bf)+0x%X:0x%X len(0x%X)", lOffset, dwBitPos, (ULONG)ulLen);
      }
      break;

    case LocIsEnregistered:
      if (pSymbol->get_registerId(&dwReg) == S_OK) {
        wprintf(L"enregistered %s", SzNameC7Reg((USHORT) dwReg));
      }
      break;

    case LocIsSlot:
      if (pSymbol->get_slot(&dwSlot) == S_OK) {
        wprintf(L"%s, [%08X]", SafeDRef(rgLocationTypeString, dwLocType), dwSlot);
      }
      break;

    case LocIsConstant:
      wprintf(L"constant");

      if (pSymbol->get_value(&vt) == S_OK) {
        PrintVariant(vt);
        VariantClear((VARIANTARG *) &vt);
      }
      break;

    case LocIsNull:
      break;

    default :
      wprintf(L"Error - invalid location type: 0x%X", dwLocType);
      break;
    }
}

////////////////////////////////////////////////////////////
// Print the type, value and the name of a const symbol
//
void PrintConst(IDiaSymbol *pSymbol)
{
  PrintSymbolType(pSymbol);

  VARIANT vt = { VT_EMPTY };

  if (pSymbol->get_value(&vt) == S_OK) {
    PrintVariant(vt);
    VariantClear((VARIANTARG *) &vt);
  }

  PrintName(pSymbol);
}

////////////////////////////////////////////////////////////
// Print the name and the type of an user defined type
//
void PrintUDT(IDiaSymbol *pSymbol)
{
  PrintName(pSymbol);
  PrintSymbolType(pSymbol);
}

////////////////////////////////////////////////////////////
// Print a string representing the type of a symbol
//
void PrintSymbolType(IDiaSymbol *pSymbol)
{
  IDiaSymbol *pType;

  if (pSymbol->get_type(&pType) == S_OK) {
    wprintf(L", Type: ");
    PrintType(pType);
    pType->Release();
  }
}

////////////////////////////////////////////////////////////
// Print the information details for a type symbol
//
void PrintType(IDiaSymbol *pSymbol)
{
  IDiaSymbol *pBaseType;
  IDiaEnumSymbols *pEnumSym;
  IDiaSymbol *pSym;
  DWORD dwTag;
  BSTR bstrName;
  DWORD dwInfo;
  BOOL bSet;
  DWORD dwRank;
  LONG lCount = 0;
  ULONG celt = 1;

  if (pSymbol->get_symTag(&dwTag) != S_OK) {
    wprintf(L"ERROR - can't retrieve the symbol's SymTag\n");
    return;
  }

  if (pSymbol->get_name(&bstrName) != S_OK) {
    bstrName = NULL;
  }

  if (dwTag != SymTagPointerType) {
    if ((pSymbol->get_constType(&bSet) == S_OK) && bSet) {
      wprintf(L"const ");
    }

    if ((pSymbol->get_volatileType(&bSet) == S_OK) && bSet) {
       wprintf(L"volatile ");
    }

    if ((pSymbol->get_unalignedType(&bSet) == S_OK) && bSet) {
      wprintf(L"__unaligned ");
    }
  }

  ULONGLONG ulLen;

  pSymbol->get_length(&ulLen);

  switch (dwTag) {
    case SymTagUDT:
      PrintUdtKind(pSymbol);
      PrintName(pSymbol);
      break;

    case SymTagEnum:
      wprintf(L"enum ");
      PrintName(pSymbol);
      break;

    case SymTagFunctionType:
      wprintf(L"function ");
      break;

    case SymTagPointerType:
      if (pSymbol->get_type(&pBaseType) != S_OK) {
        wprintf(L"ERROR - SymTagPointerType get_type");
        if (bstrName != NULL) {
          SysFreeString(bstrName);
        }
        return;
      }

      PrintType(pBaseType);
      pBaseType->Release();

      if ((pSymbol->get_reference(&bSet) == S_OK) && bSet) {
        wprintf(L" &");
      }

      else {
        wprintf(L" *");
      }

      if ((pSymbol->get_constType(&bSet) == S_OK) && bSet) {
        wprintf(L" const");
      }

      if ((pSymbol->get_volatileType(&bSet) == S_OK) && bSet) {
        wprintf(L" volatile");
      }

      if ((pSymbol->get_unalignedType(&bSet) == S_OK) && bSet) {
        wprintf(L" __unaligned");
      }
      break;

    case SymTagArrayType:
      if (pSymbol->get_type(&pBaseType) == S_OK) {
        PrintType(pBaseType);

        if (pSymbol->get_rank(&dwRank) == S_OK) {
          if (SUCCEEDED(pSymbol->findChildren(SymTagDimension, NULL, nsNone, &pEnumSym)) && (pEnumSym != NULL)) {
            while (SUCCEEDED(pEnumSym->Next(1, &pSym, &celt)) && (celt == 1)) {
              IDiaSymbol *pBound;

              wprintf(L"[");

              if (pSym->get_lowerBound(&pBound) == S_OK) {
                PrintBound(pBound);

                wprintf(L"..");

                pBound->Release();
              }

              pBound = NULL;

              if (pSym->get_upperBound(&pBound) == S_OK) {
                PrintBound(pBound);

                pBound->Release();
              }

              pSym->Release();
              pSym = NULL;

              wprintf(L"]");
            }

            pEnumSym->Release();
          }
        }

        else if (SUCCEEDED(pSymbol->findChildren(SymTagCustomType, NULL, nsNone, &pEnumSym)) &&
                 (pEnumSym != NULL) &&
                 (pEnumSym->get_Count(&lCount) == S_OK) &&
                 (lCount > 0)) {
          while (SUCCEEDED(pEnumSym->Next(1, &pSym, &celt)) && (celt == 1)) {
            wprintf(L"[");
            PrintType(pSym);
            wprintf(L"]");

            pSym->Release();
          }

          pEnumSym->Release();
        }

        else {
          DWORD dwCountElems;
          ULONGLONG ulLenArray;
          ULONGLONG ulLenElem;

          if (pSymbol->get_count(&dwCountElems) == S_OK) {
            wprintf(L"[0x%X]", dwCountElems);
          }

          else if ((pSymbol->get_length(&ulLenArray) == S_OK) &&
                   (pBaseType->get_length(&ulLenElem) == S_OK)) {
            if (ulLenElem == 0) {
              wprintf(L"[0x%lX]", (ULONG)ulLenArray);
            }

            else {
              wprintf(L"[0x%lX]", (ULONG)ulLenArray/ (ULONG)ulLenElem);
            }
          }
        }

        pBaseType->Release();
      }

      else {
        wprintf(L"ERROR - SymTagArrayType get_type\n");
        if (bstrName != NULL) {
          SysFreeString(bstrName);
        }
        return;
      }
      break;

    case SymTagBaseType:
      if (pSymbol->get_baseType(&dwInfo) != S_OK) {
        wprintf(L"SymTagBaseType get_baseType\n");
        if (bstrName != NULL) {
          SysFreeString(bstrName);
        }
        return;
      }

      switch (dwInfo) {
        case btUInt :
          wprintf(L"unsigned ");

        // Fall through

        case btInt :
          switch (ulLen) {
            case 1:
              if (dwInfo == btInt) {
                wprintf(L"signed ");
              }

              wprintf(L"char");
              break;

            case 2:
              wprintf(L"short");
              break;

            case 4:
              wprintf(L"int");
              break;

            case 8:
              wprintf(L"__int64");
              break;
          }

          dwInfo = 0xFFFFFFFF;
          break;

        case btFloat :
          switch (ulLen) {
            case 4:
              wprintf(L"float");
              break;

            case 8:
              wprintf(L"double");
              break;
          }

          dwInfo = 0xFFFFFFFF;
          break;
      }

      if (dwInfo == 0xFFFFFFFF) {
         break;
      }

      wprintf(L"%s", rgBaseType[dwInfo]);
      break;

    case SymTagTypedef:
      PrintName(pSymbol);
      break;

    case SymTagCustomType:
      {
        DWORD idOEM, idOEMSym;
        DWORD cbData = 0;
        DWORD count;

        if (pSymbol->get_oemId(&idOEM) == S_OK) {
          wprintf(L"OEMId = %X, ", idOEM);
        }

        if (pSymbol->get_oemSymbolId(&idOEMSym) == S_OK) {
          wprintf(L"SymbolId = %X, ", idOEMSym);
        }

        if (pSymbol->get_types(0, &count, NULL) == S_OK) {
          IDiaSymbol** rgpDiaSymbols = (IDiaSymbol**) _alloca(sizeof(IDiaSymbol *) * count);

          if (pSymbol->get_types(count, &count, rgpDiaSymbols) == S_OK) {
            for (ULONG i = 0; i < count; i++) {
              PrintType(rgpDiaSymbols[i]);
              rgpDiaSymbols[i]->Release();
            }
          }
        }

        // print custom data

        if ((pSymbol->get_dataBytes(cbData, &cbData, NULL) == S_OK) && (cbData != 0)) {
          wprintf(L", Data: ");

          BYTE *pbData = new BYTE[cbData];

          pSymbol->get_dataBytes(cbData, &cbData, pbData);

          for (ULONG i = 0; i < cbData; i++) {
            wprintf(L"0x%02X ", pbData[i]);
          }

          delete [] pbData;
        }
      }
      break;

    case SymTagData: // This really is member data, just print its location
      PrintLocation(pSymbol);
      break;
  }

  if (bstrName != NULL) {
    SysFreeString(bstrName);
  }
}

////////////////////////////////////////////////////////////
// Print bound information
//
void PrintBound(IDiaSymbol *pSymbol)
{
  DWORD dwTag = 0;
  DWORD dwKind;

  if (pSymbol->get_symTag(&dwTag) != S_OK) {
    wprintf(L"ERROR - PrintBound() get_symTag");
    return;
  }

  if (pSymbol->get_locationType(&dwKind) != S_OK) {
    wprintf(L"ERROR - PrintBound() get_locationType");
    return;
  }

  if (dwTag == SymTagData && dwKind == LocIsConstant) {
    VARIANT v = { VT_EMPTY };

    if (pSymbol->get_value(&v) == S_OK) {
      PrintVariant(v);
      VariantClear((VARIANTARG *) &v);
    }
  }

  else {
    PrintName(pSymbol);
  }
}

////////////////////////////////////////////////////////////
//
void PrintData(IDiaSymbol *pSymbol)
{
  PrintLocation(pSymbol);

  DWORD dwDataKind;
  if (pSymbol->get_dataKind(&dwDataKind) != S_OK) {
    wprintf(L"ERROR - PrintData() get_dataKind");
    return;
  }

  wprintf(L", %s", SafeDRef(rgDataKind, dwDataKind));
  PrintSymbolType(pSymbol);

  wprintf(L", ");
  PrintName(pSymbol);
}

////////////////////////////////////////////////////////////
// Print a VARIANT
//
void PrintVariant(VARIANT var)
{
  switch (var.vt) {
    case VT_UI1:
    case VT_I1:
      wprintf(L" 0x%X", var.bVal);
      break;

    case VT_I2:
    case VT_UI2:
    case VT_BOOL:
      wprintf(L" 0x%X", var.iVal);
      break;

    case VT_I4:
    case VT_UI4:
    case VT_INT:
    case VT_UINT:
    case VT_ERROR:
      wprintf(L" 0x%X", var.lVal);
      break;

    case VT_R4:
      wprintf(L" %g", var.fltVal);
      break;

    case VT_R8:
      wprintf(L" %g", var.dblVal);
      break;

    case VT_BSTR:
      wprintf(L" \"%s\"", var.bstrVal);
      break;

    default:
      wprintf(L" ??");
    }
}

////////////////////////////////////////////////////////////
// Print a string corresponding to a UDT kind
//
void PrintUdtKind(IDiaSymbol *pSymbol)
{
  DWORD dwKind = 0;

  if (pSymbol->get_udtKind(&dwKind) == S_OK) {
    wprintf(L"%s ", rgUdtKind[dwKind]);
  }
}

void PrintDiaTagValue(DiaTagValue *value) {
  switch (value->valueSizeBytes) {
    case 0:
      wprintf(L"(none)");
      break;
    case 1:
      wprintf(L"0x%X", *((UINT8 *)&value->value));
      break;
    case 2:
      wprintf(L"0x%X", *((UINT16 *)&value->value));
      break;
    case 4:
      wprintf(L"0x%I32X", *((UINT32 *)&value->value));
      break;
    case 8:
      wprintf(L"0x%I64X", *((UINT64 *)&value->value));
      break;
    case 16: {
      UINT64 lo = *((UINT64 *)(&value->value));
      UINT64 hi = *((UINT64 *)(&value->value[8]));

      if (hi == 0) {
          wprintf(L"0x%llX\n", lo);
      } else {
          wprintf(L"0x%llX%016llX\n", hi, lo);
      }

      break;
    }
    default:
      wprintf(L"??");
      break;
  }
}

void PrintIndent(DWORD dwIndent) {
  for (DWORD i = 0; i < dwIndent; i++) {
    putwchar(L' ');
  }
}

////////////////////////////////////////////////////////////
// Print type informations is details
//
void PrintTypeInDetail(IDiaSymbol *pSymbol, DWORD dwIndent)
{
  IDiaEnumSymbols *pEnumChildren;
  IDiaSymbol *pType;
  IDiaSymbol *pChild;
  DWORD dwSymTag;
  DWORD dwSymTagType;
  ULONG celt = 0;
  BOOL bFlag;

  if (dwIndent > MAX_TYPE_IN_DETAIL) {
    return;
  }

  if (pSymbol->get_symTag(&dwSymTag) != S_OK) {
    wprintf(L"ERROR - PrintTypeInDetail() get_symTag\n");
    return;
  }

  PrintSymTag(dwSymTag);

  PrintIndent(dwIndent);

  switch (dwSymTag) {
    case SymTagData:
      PrintData(pSymbol);

      if (pSymbol->get_type(&pType) == S_OK) {
        if (pType->get_symTag(&dwSymTagType) == S_OK) {
          if (dwSymTagType == SymTagUDT) {
            putwchar(L'\n');
            PrintTypeInDetail(pType, dwIndent + 2);
          }
        }
        pType->Release();
      }
      break;

    case SymTagTypedef:
    case SymTagVTable:
      PrintSymbolType(pSymbol);
      break;

    case SymTagEnum:
    case SymTagUDT:
      PrintUDT(pSymbol);
      putwchar(L'\n');

      if (SUCCEEDED(pSymbol->findChildren(SymTagNull, NULL, nsNone, &pEnumChildren))) {
        while (SUCCEEDED(pEnumChildren->Next(1, &pChild, &celt)) && (celt == 1)) {
          PrintTypeInDetail(pChild, dwIndent + 2);

          pChild->Release();
        }

        pEnumChildren->Release();
      }
      return;
      break;

    case SymTagFunction:
      PrintFunctionType(pSymbol);
      return;
      break;

    case SymTagPointerType:
      PrintName(pSymbol);
      wprintf(L" has type ");
      PrintType(pSymbol);
      break;

    case SymTagArrayType:
    case SymTagBaseType:
    case SymTagFunctionArgType:
    case SymTagUsingNamespace:
    case SymTagCustom:
    case SymTagFriend:
      PrintName(pSymbol);
      PrintSymbolType(pSymbol);
      break;

    case SymTagVTableShape:
    case SymTagBaseClass:
      PrintName(pSymbol);

      if ((pSymbol->get_virtualBaseClass(&bFlag) == S_OK) && bFlag) {
        IDiaSymbol *pVBTableType;
        LONG ptrOffset;
        DWORD dispIndex;

        if ((pSymbol->get_virtualBaseDispIndex(&dispIndex) == S_OK) &&
            (pSymbol->get_virtualBasePointerOffset(&ptrOffset) == S_OK)) {
          wprintf(L" virtual, offset = 0x%X, pointer offset = %ld, virtual base pointer type = ", dispIndex, ptrOffset);

          if (pSymbol->get_virtualBaseTableType(&pVBTableType) == S_OK) {
            PrintType(pVBTableType);
            pVBTableType->Release();
          }

          else {
            wprintf(L"(unknown)");
          }
        }
      }

      else {
        LONG offset;

        if (pSymbol->get_offset(&offset) == S_OK) {
          wprintf(L", offset = 0x%X", offset);
        }
      }

      putwchar(L'\n');

      if (SUCCEEDED(pSymbol->findChildren(SymTagNull, NULL, nsNone, &pEnumChildren))) {
        while (SUCCEEDED(pEnumChildren->Next(1, &pChild, &celt)) && (celt == 1)) {
          PrintTypeInDetail(pChild, dwIndent + 2);
          pChild->Release();
        }

        pEnumChildren->Release();
      }
      break;

    case SymTagFunctionType:
      if (pSymbol->get_type(&pType) == S_OK) {
        PrintType(pType);
      }
      break;

    case SymTagThunk:
      // Happens for functions which only have S_PROCREF
      PrintThunk(pSymbol);
      break;

    case SymTagTaggedUnionCase: {
      PrintName(pSymbol);

      IDiaSymbol11* pSymbol11 = NULL;
      IDiaSymbol* pTagType = NULL;
      DWORD tagOffset = 0;
      DiaTagValue mask;

      if (SUCCEEDED(pSymbol->QueryInterface(&pSymbol11)) && pSymbol11->get_discriminatedUnionTag(&pTagType, &tagOffset, &mask) == S_OK) {
        wprintf(L"\nTag            :   ");
        PrintIndent(dwIndent);
        wprintf(L"this+0x%X, Type: ", tagOffset);
        PrintType(pTagType);

        wprintf(L"\nTagMask        :   ");
        PrintIndent(dwIndent);
        PrintDiaTagValue(&mask);
      }

      putwchar(L'\n');

      DWORD rangeSize = 0;
      if (pSymbol11 && pSymbol11->get_tagRanges(0, &rangeSize, NULL) == S_OK) {
        DiaTagValue *pTagValues = new DiaTagValue[rangeSize];
        if (pSymbol11->get_tagRanges(rangeSize, &rangeSize, pTagValues) == S_OK) {
          for (DWORD i = 0; i < rangeSize; i++) {
            if (i % 2 == 0) {
              wprintf(L"TagRange       :   ");
              PrintIndent(dwIndent);
              wprintf(L"low = ");
            } else {
              wprintf(L", high = ");
            }

            PrintDiaTagValue(&pTagValues[i]);

            if (i % 2 == 1) {
              putwchar(L'\n');
            }
          }
        }
      }

      if (SUCCEEDED(pSymbol->findChildren(SymTagNull, NULL, nsNone, &pEnumChildren))) {
        while (SUCCEEDED(pEnumChildren->Next(1, &pChild, &celt)) && (celt == 1)) {
          PrintTypeInDetail(pChild, dwIndent + 2);

          pChild->Release();
        }

        pEnumChildren->Release();
      }
      break;
    }

    default:
      wprintf(L"ERROR - PrintTypeInDetail() invalid SymTag\n");
    }

    putwchar(L'\n');
}

////////////////////////////////////////////////////////////
// Print a function type
//
void PrintFunctionType(IDiaSymbol *pSymbol)
{
  DWORD dwAccess = 0;

  if (pSymbol->get_access(&dwAccess) == S_OK) {
    wprintf(L"%s ", SafeDRef(rgAccess, dwAccess));
  }

  BOOL bIsStatic = FALSE;

  if ((pSymbol->get_isStatic(&bIsStatic) == S_OK) && bIsStatic) {
    wprintf(L"static ");
  }

  IDiaSymbol *pFuncType;

  if (pSymbol->get_type(&pFuncType) == S_OK) {
    IDiaSymbol *pReturnType;

    if (pFuncType->get_type(&pReturnType) == S_OK) {
      PrintType(pReturnType);
      putwchar(L' ');

      BSTR bstrName;

      if (pSymbol->get_name(&bstrName) == S_OK) {
        wprintf(L"%s", bstrName);

        SysFreeString(bstrName);
      }

      IDiaEnumSymbols *pEnumChildren;

      if (SUCCEEDED(pFuncType->findChildren(SymTagNull, NULL, nsNone, &pEnumChildren))) {
        IDiaSymbol *pChild;
        ULONG celt = 0;
        ULONG nParam = 0;

        wprintf(L"(");

        while (SUCCEEDED(pEnumChildren->Next(1, &pChild, &celt)) && (celt == 1)) {
          IDiaSymbol *pType;

          if (pChild->get_type(&pType) == S_OK) {
            if (nParam++) {
              wprintf(L", ");
            }

            PrintType(pType);
            pType->Release();
          }

          pChild->Release();
        }

        pEnumChildren->Release();

        wprintf(L")\n");
      }

      pReturnType->Release();
    }

    pFuncType->Release();
  }
}

////////////////////////////////////////////////////////////
//
void PrintSourceFile(IDiaSourceFile *pSource)
{
  BSTR bstrSourceName;

  if (pSource->get_fileName(&bstrSourceName) == S_OK) {
    wprintf(L"\t%s", bstrSourceName);

    SysFreeString(bstrSourceName);
  }

  else {
    wprintf(L"ERROR - PrintSourceFile() get_fileName");
    return;
  }

  BYTE checksum[256];
  DWORD cbChecksum = sizeof(checksum);

  if (pSource->get_checksum(cbChecksum, &cbChecksum, checksum) == S_OK) {
    wprintf(L" (");

    DWORD checksumType;

    if (pSource->get_checksumType(&checksumType) == S_OK) {
      switch (checksumType) {
        case CHKSUM_TYPE_NONE :
          wprintf(L"None");
          break;

        case CHKSUM_TYPE_MD5 :
          wprintf(L"MD5");
          break;

        case CHKSUM_TYPE_SHA1 :
          wprintf(L"SHA1");
          break;

        default :
          wprintf(L"0x%X", checksumType);
          break;
      }

      if (cbChecksum != 0) {
        wprintf(L": ");
      }
    }

    for (DWORD ib = 0; ib < cbChecksum; ib++) {
      wprintf(L"%02X", checksum[ib]);
    }

    wprintf(L")");
  }
}

////////////////////////////////////////////////////////////
//
void PrintLines(IDiaSession *pSession, IDiaSymbol *pFunction)
{
  DWORD dwSymTag;

  if ((pFunction->get_symTag(&dwSymTag) != S_OK) || (dwSymTag != SymTagFunction)) {
    wprintf(L"ERROR - PrintLines() dwSymTag != SymTagFunction");
    return;
  }

  BSTR bstrName;

  if (pFunction->get_name(&bstrName) == S_OK) {
    wprintf(L"\n** %s\n\n", bstrName);

    SysFreeString(bstrName);
  }

  ULONGLONG ulLength;

  if (pFunction->get_length(&ulLength) != S_OK) {
    wprintf(L"ERROR - PrintLines() get_length");
    return;
  }

  DWORD dwRVA;
  IDiaEnumLineNumbers *pLines;

  if (pFunction->get_relativeVirtualAddress(&dwRVA) == S_OK) {
    if (SUCCEEDED(pSession->findLinesByRVA(dwRVA, static_cast<DWORD>(ulLength), &pLines))) {
      PrintLines(pLines);
      pLines->Release();
    }
  }

  else {
    DWORD dwSect;
    DWORD dwOffset;

    if ((pFunction->get_addressSection(&dwSect) == S_OK) &&
        (pFunction->get_addressOffset(&dwOffset) == S_OK)) {
      if (SUCCEEDED(pSession->findLinesByAddr(dwSect, dwOffset, static_cast<DWORD>(ulLength), &pLines))) {
        PrintLines(pLines);
        pLines->Release();
      }
    }
  }
}

////////////////////////////////////////////////////////////
//
void PrintLines(IDiaEnumLineNumbers *pLines)
{
  IDiaLineNumber *pLine;
  DWORD celt;
  DWORD dwRVA;
  DWORD dwSeg;
  DWORD dwOffset;
  DWORD dwLinenum;
  DWORD dwSrcId;
  DWORD dwLength;

  DWORD dwSrcIdLast = (DWORD)(-1);

  while (SUCCEEDED(pLines->Next(1, &pLine, &celt)) && (celt == 1)) {
    if ((pLine->get_relativeVirtualAddress(&dwRVA) == S_OK) &&
        (pLine->get_addressSection(&dwSeg) == S_OK) &&
        (pLine->get_addressOffset(&dwOffset) == S_OK) &&
        (pLine->get_lineNumber(&dwLinenum) == S_OK) &&
        (pLine->get_sourceFileId(&dwSrcId) == S_OK) &&
        (pLine->get_length(&dwLength) == S_OK)) {
      wprintf(L"\tline %u at [%08X][%04X:%08X], len = 0x%X", dwLinenum, dwRVA, dwSeg, dwOffset, dwLength);

      if (dwSrcId != dwSrcIdLast) {
        IDiaSourceFile *pSource;

        if (pLine->get_sourceFile(&pSource) == S_OK) {
          PrintSourceFile(pSource);

          dwSrcIdLast = dwSrcId;

          pSource->Release();
        }
      }

      pLine->Release();

      putwchar(L'\n');
    }
  }
}

////////////////////////////////////////////////////////////
// Print the section contribution data: name, Sec::Off, length
void PrintSecContribs(IDiaSectionContrib *pSegment)
{
  DWORD dwRVA;
  DWORD dwSect;
  DWORD dwOffset;
  DWORD dwLen;
  IDiaSymbol *pCompiland;
  BSTR bstrName;

  if ((pSegment->get_relativeVirtualAddress(&dwRVA) == S_OK) &&
      (pSegment->get_addressSection(&dwSect) == S_OK) &&
      (pSegment->get_addressOffset(&dwOffset) == S_OK) &&
      (pSegment->get_length(&dwLen) == S_OK) &&
      (pSegment->get_compiland(&pCompiland) == S_OK) &&
      (pCompiland->get_name(&bstrName) == S_OK)) {
    wprintf(L"  %08X  %04X:%08X  %08X  %s\n", dwRVA, dwSect, dwOffset, dwLen, bstrName);

    pCompiland->Release();

    SysFreeString(bstrName);
  }
}

////////////////////////////////////////////////////////////
// Print a debug stream data
//
void PrintStreamData(IDiaEnumDebugStreamData *pStream)
{
  BSTR bstrName;

  if (pStream->get_name(&bstrName) != S_OK) {
    wprintf(L"ERROR - PrintStreamData() get_name\n");
  }

  else {
    wprintf(L"Stream: %s", bstrName);

    SysFreeString(bstrName);
  }

  LONG dwElem;

  if (pStream->get_Count(&dwElem) != S_OK) {
      wprintf(L"ERROR - PrintStreamData() get_Count\n");
  }

  else {
    wprintf(L"(%u)\n", dwElem);
  }

  DWORD cbTotal = 0;

  BYTE data[1024];
  DWORD cbData;
  ULONG celt = 0;

  while (SUCCEEDED(pStream->Next(1, sizeof(data), &cbData, (BYTE *) &data, &celt)) && (celt == 1)) {
    DWORD i;

    for (i = 0; i < cbData; i++) {
      wprintf(L"%02X ", data[i]);

      if (i && (i % 8 == 7) && (i+1 < cbData)) {
        wprintf(L"- ");
      }
    }

    wprintf(L"| ");

    for (i = 0; i < cbData; i++) {
      wprintf(L"%c", iswprint(data[i]) ? data[i] : '.');
    }

    putwchar(L'\n');

    cbTotal += cbData;
  }

  wprintf(L"Summary :\n\tNo of Elems = %u\n", dwElem);
  if (dwElem != 0) {
    wprintf(L"\tSizeof(Elem) = %u\n", cbTotal / dwElem);
  }
  putwchar(L'\n');
}

////////////////////////////////////////////////////////////
// Print the FPO info for a given symbol;
//
void PrintFrameData(IDiaFrameData *pFrameData)
{
  DWORD dwSect;
  DWORD dwOffset;
  DWORD cbBlock;
  DWORD cbLocals;                      // Number of bytes reserved for the function locals
  DWORD cbParams;                      // Number of bytes reserved for the function arguments
  DWORD cbMaxStack;
  DWORD cbProlog;
  DWORD cbSavedRegs;
  BOOL bSEH;
  BOOL bEH;
  BOOL bStart;

  if ((pFrameData->get_addressSection(&dwSect) == S_OK) &&
      (pFrameData->get_addressOffset(&dwOffset) == S_OK) &&
      (pFrameData->get_lengthBlock(&cbBlock) == S_OK) &&
      (pFrameData->get_lengthLocals(&cbLocals) == S_OK) &&
      (pFrameData->get_lengthParams(&cbParams) == S_OK) &&
      (pFrameData->get_maxStack(&cbMaxStack) == S_OK) &&
      (pFrameData->get_lengthProlog(&cbProlog) == S_OK) &&
      (pFrameData->get_lengthSavedRegisters(&cbSavedRegs) == S_OK) &&
      (pFrameData->get_systemExceptionHandling(&bSEH) == S_OK) &&
      (pFrameData->get_cplusplusExceptionHandling(&bEH) == S_OK) &&
      (pFrameData->get_functionStart(&bStart) == S_OK)) {
    wprintf(L"%04X:%08X   %8X %8X %8X %8X %8X %8X %c   %c   %c",
            dwSect, dwOffset, cbBlock, cbLocals, cbParams, cbMaxStack, cbProlog, cbSavedRegs,
            bSEH ? L'Y' : L'N',
            bEH ? L'Y' : L'N',
            bStart ? L'Y' : L'N');

    BSTR bstrProgram;

    if (pFrameData->get_program(&bstrProgram) == S_OK) {
      wprintf(L" %s", bstrProgram);

      SysFreeString(bstrProgram);
    }

    putwchar(L'\n');
  }
}

////////////////////////////////////////////////////////////
// Print all the valid properties associated to a symbol
//
void PrintPropertyStorage(IDiaPropertyStorage *pPropertyStorage)
{
  IEnumSTATPROPSTG *pEnumProps;

  if (SUCCEEDED(pPropertyStorage->Enum(&pEnumProps))) {
    STATPROPSTG prop;
    DWORD celt = 1;

    while (SUCCEEDED(pEnumProps->Next(celt, &prop, &celt)) && (celt == 1)) {
      PROPSPEC pspec = { PRSPEC_PROPID, prop.propid };
      PROPVARIANT vt = { VT_EMPTY };

      if (SUCCEEDED(pPropertyStorage->ReadMultiple(1, &pspec, &vt))) {
        switch (vt.vt) {
          case VT_BOOL:
            wprintf(L"%32s:\t %s\n", prop.lpwstrName, vt.bVal ? L"true" : L"false");
            break;

          case VT_I2:
            wprintf(L"%32s:\t %d\n", prop.lpwstrName, vt.iVal);
            break;

          case VT_UI2:
            wprintf(L"%32s:\t %u\n", prop.lpwstrName, vt.uiVal);
            break;

          case VT_I4:
            wprintf(L"%32s:\t %d\n", prop.lpwstrName, vt.intVal);
            break;

          case VT_UI4:
            wprintf(L"%32s:\t 0x%0X\n", prop.lpwstrName, vt.uintVal);
            break;

          case VT_UI8:
            wprintf(L"%32s:\t 0x%llX\n", prop.lpwstrName, vt.uhVal.QuadPart);
            break;

          case VT_BSTR:
            wprintf(L"%32s:\t %s\n", prop.lpwstrName, vt.bstrVal);
            break;

          case VT_UNKNOWN:
            wprintf(L"%32s:\t %p\n", prop.lpwstrName, vt.punkVal);
            break;

          case VT_SAFEARRAY:
            break;
        }

        VariantClear((VARIANTARG *) &vt);
      }

      SysFreeString( prop.lpwstrName );
    }

    pEnumProps->Release();
  }
}

Youez - 2016 - github.com/yon3zu
LinuXploit