home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 40 / IOPROG_40.ISO / SOFT / NETFrameworkSDK.exe / comsdk.cab / samples1.exe / MetaInfo / mdinfo.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  139.4 KB  |  4,134 lines

  1. //*****************************************************************************
  2. // File: mdinfo.cpp
  3. //
  4. // Copyright (c) 1997-1998 Microsoft Corporation.  All Rights Reserved.
  5. // Microsoft Confidential.
  6. //*****************************************************************************
  7. #include <stdio.h>
  8. #include <windows.h>
  9. #include <objbase.h>
  10. #include <crtdbg.h>
  11. #include <assert.h>
  12.  
  13. #define INIT_GUID
  14. #include <initguid.h>
  15.  
  16. //#include <corpriv.h>
  17. #include <cor.h>
  18. #include "assert.h"
  19. #include "CorError.h"
  20. #include <WinWrap.h>
  21.  
  22. typedef LPCSTR LPCUTF8;
  23. typedef LPSTR  LPUTF8;
  24.  
  25. #include "cahlpr.h"
  26.  
  27. #include "malloc.h"
  28. #include "mdinfo.h"
  29.                     
  30. template<class T> class CQuickArray : CQuickBytes
  31. {
  32. public:
  33.     T* Alloc(int iItems) 
  34.         { return (T*)CQuickBytes::Alloc(iItems * sizeof(T)); }
  35.     HRESULT ReSize(int iItems) 
  36.         { return CQuickBytes::ReSize(iItems * sizeof(T)); }
  37.     T* Ptr() 
  38.         { return (T*) CQuickBytes::Ptr(); }
  39.     size_t Size()
  40.         { return CQuickBytes::Size() / sizeof(T); }
  41.     size_t MaxSize()
  42.         { return CQuickBytes::cbTotal / sizeof(T); }
  43.     T& operator[] (size_t ix)
  44.     { _ASSERTE(ix < static_cast<unsigned int>(Size()));
  45.         return *(Ptr() + ix);
  46.     }
  47. };
  48.  
  49. #ifndef IfFailRet
  50. #define IfFailRet(EXPR) \
  51. do { hr = (EXPR); if(FAILED(hr)) { return (hr); } } while (0)
  52. #endif
  53.  
  54. LPCWSTR PrettyPrintSig(PCCOR_SIGNATURE typePtr,    unsigned typeLen, const WCHAR *name, CQuickBytes *out, IMetaDataImport *pIMDI);
  55.  
  56. #define ENUM_BUFFER_SIZE 10
  57. #define TAB_SIZE 8
  58.  
  59. #define NumItems(s) (sizeof(s) / sizeof(s[0]))
  60.  
  61. #define ISFLAG(p,x) if (Is##p##x(flags)) strcat(sFlags, "["#x "] ");
  62.  
  63. extern HRESULT  _FillVariant(
  64.     BYTE        bCPlusTypeFlag, 
  65.     void const  *pValue,
  66.     VARIANT     *pvar); 
  67.  
  68. // Validator declarations.
  69. extern DWORD g_ValModuleType;
  70.  
  71. // Tables for mapping element type to text
  72. char *g_szMapElementType[] = 
  73. {
  74.     "End",          // 0x0
  75.     "Void",         // 0x1
  76.     "Boolean",
  77.     "Char", 
  78.     "I1",
  79.     "UI1",
  80.     "I2",           // 0x6
  81.     "UI2",
  82.     "I4",
  83.     "UI4",
  84.     "I8",
  85.     "UI8",
  86.     "R4",
  87.     "R8",
  88.     "String",
  89.     "Ptr",          // 0xf
  90.     "ByRef",        // 0x10
  91.     "ValueClass",
  92.     "Class",
  93.     "CopyCtor",
  94.     "MDArray",      // 0x14
  95.     "GENArray",
  96.     "TypedByRef",
  97.     "VALUEARRAY",
  98.     "I",
  99.     "U",
  100.     "R",            // 0x1a
  101.     "FNPTR",
  102.     "Object",
  103.     "SZArray",
  104.     "GENERICArray",
  105.     "CMOD_REQD",
  106.     "CMOD_OPT",
  107. };
  108.  
  109. char *g_szMapUndecorateType[] = 
  110. {
  111.     "",                 // 0x0
  112.     "void",
  113.     "boolean",
  114.     "Char", 
  115.     "byte",
  116.     "unsigned byte",
  117.     "short",
  118.     "unsigned short",
  119.     "int",
  120.     "unsigned int",
  121.     "long",
  122.     "unsigned long",
  123.     "float",
  124.     "double",
  125.     "String",
  126.     "*",                // 0xf
  127.     "ByRef",
  128.     "",
  129.     "",
  130.     "",
  131.     "",
  132.     "",
  133.     "",
  134.     "",
  135.     "",
  136.     "",
  137.     "",
  138.     "Function Pointer",
  139.     "Object",
  140.     "",
  141.     "",
  142.     "CMOD_REQD",
  143.     "CMOD_OPT",
  144. };
  145.  
  146. char *g_strCalling[] = 
  147. {   
  148.     "[DEFAULT]",
  149.     "[C]",
  150.     "[STDCALL]",
  151.     "[THISCALL]",
  152.     "[FASTCALL]",
  153.     "[VARARG]",
  154.     "[FIELD]",
  155.     "[LOCALSIG]",
  156.     "[PROPERTY]",
  157.     "[UNMANAGED]",
  158. };
  159.  
  160. char *g_szNativeType[] =
  161. {
  162.     "NATIVE_TYPE_END(DEPRECATED!)",  //         = 0x0,    //DEPRECATED
  163.     "NATIVE_TYPE_VOID(DEPRECATED!)",  //        = 0x1,    //DEPRECATED
  164.     "NATIVE_TYPE_BOOLEAN",  //     = 0x2,    // (4 byte boolean value: TRUE = non-zero, FALSE = 0)
  165.     "NATIVE_TYPE_I1",  //          = 0x3,  
  166.     "NATIVE_TYPE_U1",  //          = 0x4,  
  167.     "NATIVE_TYPE_I2",  //          = 0x5,  
  168.     "NATIVE_TYPE_U2",  //          = 0x6,  
  169.     "NATIVE_TYPE_I4",  //          = 0x7,  
  170.     "NATIVE_TYPE_U4",  //          = 0x8,  
  171.     "NATIVE_TYPE_I8",  //          = 0x9,  
  172.     "NATIVE_TYPE_U8",  //          = 0xa,  
  173.     "NATIVE_TYPE_R4",  //          = 0xb,  
  174.     "NATIVE_TYPE_R8",  //          = 0xc,  
  175.     "NATIVE_TYPE_SYSCHAR(DEPRECATED!)",  //     = 0xd,    //DEPRECATED 
  176.     "NATIVE_TYPE_VARIANT(DEPRECATED!)",  //     = 0xe,    //DEPRECATED
  177.     "NATIVE_TYPE_CURRENCY(DEPRECATED!)",  //    = 0xf,    //DEPRECATED
  178.     "NATIVE_TYPE_PTR(DEPRECATED!)",  //         = 0x10,   //DEPRECATED  
  179.  
  180.     "NATIVE_TYPE_DECIMAL(DEPRECATED!)",  //     = 0x11,   //DEPRECATED
  181.     "NATIVE_TYPE_DATE(DEPRECATED!)",  //        = 0x12,   //DEPRECATED
  182.     "NATIVE_TYPE_BSTR",  //        = 0x13, 
  183.     "NATIVE_TYPE_LPSTR",  //       = 0x14, 
  184.     "NATIVE_TYPE_LPWSTR",  //      = 0x15, 
  185.     "NATIVE_TYPE_LPTSTR",  //      = 0x16, 
  186.     "NATIVE_TYPE_FIXEDSYSSTRING",  //  = 0x17, 
  187.     "NATIVE_TYPE_OBJECTREF(DEPRECATED!)",  //   = 0x18,   //DEPRECATED
  188.     "NATIVE_TYPE_IUNKNOWN(DEPRECATED!)",  //    = 0x19,   //DEPRECATED
  189.     "NATIVE_TYPE_IDISPATCH(DEPRECATED!)",  //   = 0x1a,   //DEPRECATED
  190.     "NATIVE_TYPE_STRUCT",  //      = 0x1b, 
  191.     "NATIVE_TYPE_INTF",  //        = 0x1c, 
  192.     "NATIVE_TYPE_SAFEARRAY",  //   = 0x1d, 
  193.     "NATIVE_TYPE_FIXEDARRAY",  //  = 0x1e, 
  194.     "NATIVE_TYPE_INT",  //         = 0x1f, 
  195.     "NATIVE_TYPE_UINT",  //        = 0x20, 
  196.  
  197.     //@todo: sync up the spec   
  198.     "NATIVE_TYPE_NESTEDSTRUCT(DEPRECATED!)",  //  = 0x21, //DEPRECATED (use "NATIVE_TYPE_STRUCT)   
  199.  
  200.     "NATIVE_TYPE_BYVALSTR",  //    = 0x22,
  201.                               
  202.     "NATIVE_TYPE_ANSIBSTR",  //    = 0x23,
  203.  
  204.     "NATIVE_TYPE_TBSTR",  //       = 0x24, // select BSTR or ANSIBSTR depending on platform
  205.  
  206.  
  207.     "NATIVE_TYPE_VARIANTBOOL",  // = 0x25, // (2-byte boolean value: TRUE = -1, FALSE = 0)
  208.     "NATIVE_TYPE_FUNC",  //        = 0x26,
  209.     "NATIVE_TYPE_LPVOID",  //      = 0x27, // blind pointer (no deep marshaling)
  210.  
  211.     "NATIVE_TYPE_ASANY",  //       = 0x28,
  212.     "NATIVE_TYPE_R",  //           = 0x29, // agnostic floating point
  213.  
  214.     "NATIVE_TYPE_ARRAY",  //       = 0x2a,
  215.     "NATIVE_TYPE_LPSTRUCT",  //    = 0x2b,
  216.     "NATIVE_TYPE_CUSTOMMARSHALER", //           = 0x2c, // Custom marshaler.
  217.     "NATIVE_TYPE_ERROR", //        = 0x2d, // VT_HRESULT when exporting to a typelib.
  218. };
  219.  
  220.  
  221. size_t g_cbCoffNames = 0;
  222.  
  223. mdMethodDef g_tkEntryPoint = 0; // integration with ILDASM
  224.  
  225.  
  226.  
  227. // helper to init signature buffer
  228. void MDInfo::InitSigBuffer()
  229. {
  230.     strcpy((LPSTR)m_sigBuf.Ptr(), "");
  231. }
  232.  
  233. // helper to append a string into the signature buffer. If size of signature buffer is not big enough,
  234. // we will grow it.
  235. HRESULT MDInfo::AddToSigBuffer(char *string)
  236. {
  237.     HRESULT     hr;
  238.     IfFailRet( m_sigBuf.ReSize(strlen((LPSTR)m_sigBuf.Ptr()) + strlen(string) + 1) );
  239.     strcat((LPSTR)m_sigBuf.Ptr(), string);
  240.     return NOERROR;
  241. }
  242.  
  243. MDInfo::MDInfo(IMetaDataImport* pImport, IMetaDataAssemblyImport* pAssemblyImport, LPCWSTR szScope, strPassBackFn inPBFn, ULONG DumpFilter)
  244.  :  m_pTables(0)
  245. {   // This constructor is specific to ILDASM/MetaInfo integration
  246.  
  247.     _ASSERTE(pImport != NULL);
  248.     _ASSERTE(NumItems(g_szMapElementType) == NumItems(g_szMapUndecorateType));
  249.     _ASSERTE(NumItems(g_szMapElementType) == ELEMENT_TYPE_MAX);
  250.  
  251.     m_pImport = pImport;
  252.     m_pImport->AddRef();
  253.     if(m_pAssemblyImport = pAssemblyImport) 
  254.         m_pAssemblyImport->AddRef();
  255.     else
  256.     {
  257.         HRESULT hr = m_pImport->QueryInterface(IID_IMetaDataAssemblyImport, (void**) &m_pAssemblyImport);
  258.         if (FAILED(hr))
  259.             Error("QueryInterface failed for IID_IMetaDataAssemblyImport.", hr);
  260.     }
  261.  
  262.     m_pbFn = inPBFn;
  263.     m_DumpFilter = (DUMP_FILTER) DumpFilter;
  264. } // MDInfo::MDInfo()
  265.  
  266. MDInfo::MDInfo(IMetaDataDispenserEx* inDisp, LPCWSTR szScope, strPassBackFn inPBFn, ULONG DumpFilter)
  267.  :  m_pTables(0)
  268. {
  269.     HRESULT     hr = S_OK;
  270.     VARIANT     value;
  271.  
  272.     _ASSERTE(inDisp != NULL && inPBFn != NULL);
  273.     _ASSERTE(NumItems(g_szMapElementType) == NumItems(g_szMapUndecorateType));
  274.     _ASSERTE(NumItems(g_szMapElementType) == ELEMENT_TYPE_MAX);
  275.  
  276.     m_pDisp=inDisp;
  277.     m_pImport = NULL;
  278.     m_pAssemblyImport = NULL;
  279.     m_pbFn = inPBFn;
  280.     m_DumpFilter = (DUMP_FILTER) DumpFilter;
  281.  
  282.     // Attempt to open scope on given file
  283.     hr = m_pDisp->OpenScope(szScope, 0, IID_IMetaDataImport, (IUnknown**)&m_pImport);
  284.     if (hr == CLDB_E_BADUPDATEMODE)
  285.     {
  286.         V_VT(&value) = VT_UI4;
  287.         V_UI4(&value) = MDUpdateIncremental;
  288.         if (FAILED(hr = m_pDisp->SetOption(MetaDataSetUpdate, &value)))
  289.             Error("SetOption failed.", hr);
  290.         hr = m_pDisp->OpenScope(szScope, 0, IID_IMetaDataImport, (IUnknown**)&m_pImport);
  291.     }
  292.     if (FAILED(hr))
  293.         Error("OpenScope failed", hr);
  294.  
  295.     // Query for the IMetaDataAssemblyImport interface.
  296.     hr = m_pImport->QueryInterface(IID_IMetaDataAssemblyImport, (void**) &m_pAssemblyImport);
  297.     if (FAILED(hr))
  298.         Error("QueryInterface failed for IID_IMetaDataAssemblyImport.", hr);
  299.  
  300. } // MDInfo::MDInfo()
  301.  
  302.  
  303. MDInfo::MDInfo(IMetaDataDispenserEx* inDisp, PBYTE pbMetaData, DWORD dwSize, strPassBackFn inPBFn, ULONG DumpFilter)
  304.  :  m_pTables(0)
  305. {
  306.     _ASSERTE(inDisp != NULL && inPBFn != NULL);
  307.     _ASSERTE(NumItems(g_szMapElementType) == NumItems(g_szMapUndecorateType));
  308.     _ASSERTE(NumItems(g_szMapElementType) == ELEMENT_TYPE_MAX);
  309.  
  310.     m_pDisp=inDisp;
  311.     m_pImport = NULL;
  312.     m_pAssemblyImport = NULL;
  313.     m_pbFn = inPBFn;
  314.     m_DumpFilter = (DUMP_FILTER) DumpFilter;
  315.  
  316.     m_pImport = NULL;
  317.     m_pAssemblyImport = NULL;
  318.  
  319.     // Attempt to open scope on manifest. It's valid for this to fail, because
  320.     // the blob we open may just be the assembly resources (the space is
  321.     // overloaded until we remove LM -a assemblies, at which point this
  322.     // constructor should probably be removed too).
  323.     HRESULT hr;
  324.     if (SUCCEEDED(hr = m_pDisp->OpenScopeOnMemory(pbMetaData, dwSize, 0,
  325.                             IID_IMetaDataImport, (IUnknown**)&m_pImport)))
  326.     {
  327.         // Query for the IMetaDataAssemblyImport interface.
  328.         hr = m_pImport->QueryInterface(IID_IMetaDataAssemblyImport, (void**) &m_pAssemblyImport);
  329.         if (FAILED(hr))
  330.             Error("QueryInterace failed for IID_IMetaDataAssemblyImport.", hr);
  331.     }
  332. } // MDInfo::MDInfo()
  333.  
  334.  
  335. // Destructor
  336. MDInfo::~MDInfo()
  337. {
  338.     if (m_pImport)
  339.         m_pImport->Release();
  340.     if (m_pAssemblyImport)
  341.         m_pAssemblyImport->Release();
  342.     if (m_pTables)
  343.         m_pTables->Release();
  344. } // MDInfo::~MDInfo()
  345.  
  346. //=====================================================================================================================
  347. //=====================================================================================================================
  348. // DisplayMD() function
  349. //
  350. // Displays the meta data content of a file
  351.  
  352. void MDInfo::DisplayMD(void)
  353. {
  354.     if (m_DumpFilter & (dumpSchema | dumpHeader | dumpCSV | dumpRaw | dumpStats))
  355.         DisplayRaw();
  356.     else
  357.     {
  358.         DisplayVersionInfo();
  359.         DisplayScopeInfo();
  360.         WriteLine("===========================================================");
  361.         DisplayGlobalFunctions();
  362.         DisplayGlobalFields();
  363.         DisplayGlobalMemberRefs();
  364.         DisplayTypeDefs();
  365.         DisplayTypeRefs();
  366.         DisplayTypeSpecs();
  367.         DisplayModuleRefs();
  368.         DisplaySignatures();
  369.         DisplayAssembly();
  370.         DisplayUserStrings();
  371.  
  372.         // WriteLine("============================================================");
  373.         // WriteLine("Unresolved MemberRefs");
  374.         // DisplayMemberRefs(0x00000001, "\t");
  375.  
  376.         if (m_DumpFilter & dumpUnsat)
  377.             DisplayUnsatInfo();
  378.     
  379.     
  380.         VWrite("\n\nCoff symbol name overhead:  %d\n", g_cbCoffNames);
  381.     }
  382. } // void MDInfo::DisplayMD()
  383.  
  384. int MDInfo::WriteLine(char *str)
  385. {
  386.     int count = strlen(str);
  387.  
  388.     m_pbFn(str);
  389.     m_pbFn("\n");
  390.     return count;
  391. } // int MDInfo::WriteLine()
  392.  
  393. int MDInfo::Write(char *str)
  394. {
  395.     int count = strlen(str);
  396.  
  397.     m_pbFn(str);
  398.     return count;
  399. } // int MDInfo::Write()
  400.  
  401. int MDInfo::VWriteLine(char *str, ...)
  402. {
  403.     va_list marker;
  404.     int count;
  405.  
  406.     va_start(marker, str);
  407.     count = vsprintf(m_output, str, marker);
  408.     m_pbFn(m_output);
  409.     m_pbFn("\n");
  410.     va_end(marker);
  411.     return count;
  412. } // int MDInfo::WriteLine()
  413.  
  414. int MDInfo::VWrite(char *str, ...)
  415. {
  416.     va_list marker;
  417.     int count;
  418.  
  419.     va_start(marker, str);
  420.     count = vsprintf(m_output, str, marker);
  421.     m_pbFn(m_output);
  422.     va_end(marker);
  423.     return count;
  424. } // int MDInfo::Write()
  425.  
  426. // Error() function -- prints an error and returns
  427. void MDInfo::Error(const char* szError, HRESULT hr)
  428. {
  429.     printf("\n%s\n",szError);
  430.     if (hr != S_OK)
  431.     {
  432.         IErrorInfo  *pIErr = NULL;          // Error interface.
  433.         BSTR        bstrDesc = NULL;        // Description text.
  434.  
  435.         printf("Failed return code: 0x%08x\n", hr);
  436.  
  437.         // Try to get an error info object and display the message.
  438.         if (GetErrorInfo(0, &pIErr) == S_OK &&
  439.             pIErr->GetDescription(&bstrDesc) == S_OK)
  440.         {
  441.             printf("%ls ", bstrDesc);
  442.             SysFreeString(bstrDesc);
  443.         }
  444.  
  445.         // Free the error interface.
  446.         if (pIErr)
  447.             pIErr->Release();
  448.     }
  449.     CoUninitialize();
  450.     exit(hr);
  451. } // void MDInfo::Error()
  452.  
  453. // Print out the optional version info included in the MetaData.
  454.  
  455. void MDInfo::DisplayVersionInfo(void)
  456. {
  457.     if (!(m_DumpFilter & MDInfo::dumpNoLogo))
  458.     {
  459.         LPCUTF8 pVersionStr;
  460.         HRESULT hr = S_OK;
  461.  
  462.         if (m_pTables == 0)
  463.         {
  464.             if (m_pImport)
  465.                 hr = m_pImport->QueryInterface(IID_IMetaDataTables, (void**)&m_pTables);
  466.             else if (m_pAssemblyImport)
  467.                 hr = m_pAssemblyImport->QueryInterface(IID_IMetaDataTables, (void**)&m_pTables);
  468.             else
  469.                 return;
  470.             if (FAILED(hr))
  471.                 Error("QueryInterace failed for IID_IMetaDataTables.", hr);
  472.         }
  473.  
  474.         hr = m_pTables->GetString(1, &pVersionStr);
  475.         if (FAILED(hr))
  476.             Error("GetString() failed.", hr);
  477.         if (strstr(pVersionStr, "Version of runtime against which the binary is built : ")
  478.                     == pVersionStr)
  479.         {
  480.             WriteLine(const_cast<char *>(pVersionStr));
  481.         }
  482.     }
  483. } // void MDInfo::DisplayVersionInfo()
  484.  
  485. // Prints out information about the scope
  486.  
  487. void MDInfo::DisplayScopeInfo(void)
  488. {
  489.     HRESULT hr;
  490.     mdModule mdm;
  491.     GUID mvid;
  492.     WCHAR scopeName[STRING_BUFFER_LEN];
  493.     WCHAR guidString[STRING_BUFFER_LEN];
  494.  
  495.     hr = m_pImport->GetScopeProps( scopeName, STRING_BUFFER_LEN, 0, &mvid);
  496.     if (FAILED(hr)) Error("GetScopeProps failed.", hr);
  497.  
  498.     VWriteLine("ScopeName : %ls",scopeName);
  499.  
  500.     if (!(m_DumpFilter & MDInfo::dumpNoLogo))
  501.         VWriteLine("MVID      : %ls",GUIDAsString(mvid, guidString, STRING_BUFFER_LEN));
  502.  
  503.     hr = m_pImport->GetModuleFromScope(&mdm);
  504.     if (FAILED(hr)) Error("GetModuleFromScope failed.", hr);
  505.     DisplayPermissions(mdm, "");
  506.     DisplayCustomAttributes(mdm, "\t");
  507. } // void MDInfo::DisplayScopeInfo()
  508.  
  509. void MDInfo::DisplayRaw()
  510. {
  511.     int         iDump;                  // Level of info to dump.
  512.  
  513.     if (m_pTables == 0)
  514.         m_pImport->QueryInterface(IID_IMetaDataTables, (void**)&m_pTables);
  515.     if (m_pTables == 0)
  516.         Error("Can't get table info.");
  517.  
  518.     if (m_DumpFilter & dumpCSV)
  519.         DumpRawCSV();
  520.     else
  521.     {
  522.         if (m_DumpFilter & dumpRaw)
  523.             iDump = 3;
  524.         else
  525.         if (m_DumpFilter & dumpSchema)
  526.             iDump = 2;
  527.         else
  528.             iDump = 1;
  529.         
  530.         DumpRaw(iDump, (m_DumpFilter & dumpStats) != 0);
  531.     }
  532. } // void MDInfo::DisplayRaw()
  533.  
  534. // return the name of the type of token passed in
  535.  
  536. char *MDInfo::TokenTypeName(mdToken inToken)
  537. {
  538.     switch(TypeFromToken(inToken))
  539.     {
  540.     case mdtTypeDef:        return "TypeDef";
  541.     case mdtInterfaceImpl:  return "InterfaceImpl";
  542.     case mdtMethodDef:      return "MethodDef";
  543.     case mdtFieldDef:       return "FieldDef";
  544.     case mdtTypeRef:        return "TypeRef";
  545.     case mdtMemberRef:      return "MemberRef";
  546.     case mdtCustomAttribute:return "CustomAttribute";
  547.     case mdtParamDef:       return "ParamDef";
  548.     case mdtSourceFile:     return "SourceFile";
  549.     case mdtLocalVarScope:  return "LocalVarScope";
  550.     case mdtLocalVar:       return "LocalVar";
  551.     case mdtProperty:       return "Property";
  552.     case mdtEvent:          return "Event";
  553.     default:                return "[UnknownTokenType]";
  554.     }
  555. } // char *MDInfo::TokenTypeName()
  556.  
  557. // Prints out name of the given memberref
  558. //
  559. // com 99 only
  560.  
  561. LPCWSTR MDInfo::MemberRefName(mdMemberRef inMemRef, LPWSTR buffer, ULONG bufLen)
  562. {
  563.     HRESULT hr;
  564.     
  565.     if (!m_pImport) // if com99 not available
  566.         return L"";
  567.  
  568.     hr = m_pImport->GetMemberRefProps( inMemRef, NULL, buffer, bufLen,
  569.                                     NULL, NULL, NULL);
  570.     if (FAILED(hr)) Error("GetMemberRefProps failed.", hr);
  571.     
  572.     return buffer;
  573. } // LPCWSTR MDInfo::MemberRefName()
  574.  
  575.  
  576. // Prints out information about the given memberref
  577. //
  578. // com 99 only
  579.  
  580. void MDInfo::DisplayMemberRefInfo(mdMemberRef inMemRef, const char *preFix)
  581. {
  582.     HRESULT hr;
  583.     WCHAR memRefName[STRING_BUFFER_LEN];
  584.     ULONG nameLen;
  585.     mdToken token;
  586.     PCCOR_SIGNATURE pbSigBlob;
  587.     ULONG ulSigBlob;
  588.     char newPreFix[STRING_BUFFER_LEN];
  589.  
  590.     if (!m_pImport) // if com99 not available
  591.         return;
  592.  
  593.     hr = m_pImport->GetMemberRefProps( inMemRef, &token, memRefName, STRING_BUFFER_LEN,
  594.                                     &nameLen, &pbSigBlob, &ulSigBlob);
  595.     if (FAILED(hr)) Error("GetMemberRefProps failed.", hr);
  596.     
  597.     VWriteLine("%s\t\tMember: (%8.8x) %ls: ", preFix, inMemRef, memRefName);
  598.  
  599.     if (ulSigBlob)
  600.         DisplaySignature(pbSigBlob, ulSigBlob, preFix);
  601.  
  602.     sprintf (newPreFix, "\t\t%s", preFix);
  603.     DisplayCustomAttributes(inMemRef, newPreFix);
  604. } // void MDInfo::DisplayMemberRefInfo()
  605.  
  606. // Prints out information about all memberrefs of the given typeref
  607. //
  608. // com 99 only
  609.  
  610. void MDInfo::DisplayMemberRefs(mdToken tkParent, const char *preFix)
  611. {
  612.     HCORENUM memRefEnum = NULL;
  613.     HRESULT hr;
  614.     mdMemberRef memRefs[ENUM_BUFFER_SIZE];
  615.     ULONG count, totalCount = 1;
  616.  
  617.     if (!m_pImport) // if com99 not available
  618.         return;
  619.  
  620.     while (SUCCEEDED(hr = m_pImport->EnumMemberRefs( &memRefEnum, tkParent,
  621.                              memRefs, NumItems(memRefs), &count)) && 
  622.             count > 0)
  623.     {
  624.         for (ULONG i = 0; i < count; i++, totalCount++)
  625.         {
  626.             VWriteLine("%s\tMemberRef #%d", preFix, totalCount);
  627.             VWriteLine("%s\t-------------------------------------------------------", preFix);
  628.             DisplayMemberRefInfo(memRefs[i], preFix);
  629.         }
  630.     }
  631.     m_pImport->CloseEnum( memRefEnum);
  632. } // void MDInfo::DisplayMemberRefs()
  633.  
  634. // Prints out information about all resources in the com object
  635. //
  636. // avaiable: 98 and 99
  637.  
  638. // Iterates through each typeref and prints out the information of each
  639. //
  640. // available: 98 and 99
  641.  
  642. void MDInfo::DisplayTypeRefs()
  643. {
  644.     HCORENUM typeRefEnum = NULL;
  645.     mdTypeRef typeRefs[ENUM_BUFFER_SIZE];
  646.     ULONG count, totalCount=1;
  647.     HRESULT hr;
  648.     
  649.     while (SUCCEEDED(hr = m_pImport->EnumTypeRefs( &typeRefEnum,
  650.                              typeRefs, NumItems(typeRefs), &count)) &&
  651.             count > 0)
  652.     {
  653.         for (ULONG i = 0; i < count; i++, totalCount++)
  654.         {
  655.             VWriteLine("TypeRef #%d (%08x)", totalCount, typeRefs[i]);
  656.             WriteLine("-------------------------------------------------------");
  657.             DisplayTypeRefInfo(typeRefs[i]);
  658.             // Yes, MemberRefs only available under com99, but it will figure it out
  659.             DisplayMemberRefs(typeRefs[i], "");
  660.             WriteLine("");
  661.         }
  662.     }
  663.     m_pImport->CloseEnum( typeRefEnum);
  664. } // void MDInfo::DisplayTypeRefs()
  665.  
  666. void MDInfo::DisplayTypeSpecs()
  667. {
  668.     HCORENUM typespecEnum = NULL;
  669.     mdTypeSpec typespecs[ENUM_BUFFER_SIZE];
  670.     ULONG count, totalCount=1;
  671.     HRESULT hr;
  672.     
  673.     while (SUCCEEDED(hr = m_pImport->EnumTypeSpecs( &typespecEnum,
  674.                              typespecs, NumItems(typespecs), &count)) &&
  675.             count > 0)
  676.     {
  677.         for (ULONG i = 0; i < count; i++, totalCount++)
  678.         {
  679.             VWriteLine("TypeSpec #%d", totalCount);
  680.             WriteLine("-------------------------------------------------------");
  681.             DisplayTypeSpecInfo(typespecs[i], "");
  682.             // Yes, MemberRefs only available under com99, but it will figure it out
  683.             DisplayMemberRefs(typespecs[i], "");
  684.             WriteLine("");
  685.         }
  686.     }
  687.     m_pImport->CloseEnum( typespecEnum);
  688. } // void MDInfo::DisplayTypeSpecs()
  689.  
  690.  
  691.  
  692. // Called to display the information about all typedefs in the object.
  693. //
  694. // available: 98 and 99
  695.  
  696. void MDInfo::DisplayTypeDefs()
  697. {
  698.     HCORENUM typeDefEnum = NULL;
  699.     mdTypeDef typeDefs[ENUM_BUFFER_SIZE];
  700.     ULONG count, totalCount = 1;
  701.     HRESULT hr;
  702.     
  703.     while (SUCCEEDED(hr = m_pImport->EnumTypeDefs( &typeDefEnum,
  704.                              typeDefs, NumItems(typeDefs), &count)) &&
  705.             count > 0)
  706.     {
  707.         for (ULONG i = 0; i < count; i++, totalCount++)
  708.         {
  709.             VWriteLine("TypeDef #%d", totalCount);
  710.             WriteLine("-------------------------------------------------------");
  711.             DisplayTypeDefInfo(typeDefs[i]);
  712.             WriteLine("");
  713.         }
  714.     }
  715.     m_pImport->CloseEnum( typeDefEnum);
  716. } // void MDInfo::DisplayTypeDefs()
  717.  
  718. // Called to display the information about all modulerefs in the object.
  719. //
  720. // available: 99 only
  721.  
  722. void MDInfo::DisplayModuleRefs()
  723. {
  724.     HCORENUM moduleRefEnum = NULL;
  725.     mdModuleRef moduleRefs[ENUM_BUFFER_SIZE];
  726.     ULONG count, totalCount = 1;
  727.     HRESULT hr;
  728.     
  729.     while (SUCCEEDED(hr = m_pImport->EnumModuleRefs( &moduleRefEnum,
  730.                              moduleRefs, NumItems(moduleRefs), &count)) &&
  731.             count > 0)
  732.     {
  733.         for (ULONG i = 0; i < count; i++, totalCount++)
  734.         {
  735.             VWriteLine("ModuleRef #%d", totalCount);
  736.             WriteLine("-------------------------------------------------------");
  737.             DisplayModuleRefInfo(moduleRefs[i]);
  738.             DisplayMemberRefs(moduleRefs[i], "");
  739.             WriteLine("");
  740.         }
  741.     }
  742.     m_pImport->CloseEnum( moduleRefEnum);
  743. } // void MDInfo::DisplayModuleRefs()
  744.  
  745. // Prints out information about the given moduleref
  746. //
  747. // com 99 only
  748.  
  749. void MDInfo::DisplayModuleRefInfo(mdModuleRef inModuleRef)
  750. {
  751.     HRESULT hr;
  752.     WCHAR moduleRefName[STRING_BUFFER_LEN];
  753.     ULONG nameLen;
  754.  
  755.     if (!m_pImport) // if com99 not available
  756.         return;
  757.  
  758.     hr = m_pImport->GetModuleRefProps( inModuleRef, moduleRefName, STRING_BUFFER_LEN,
  759.                                     &nameLen);
  760.     if (FAILED(hr)) Error("GetModuleRefProps failed.", hr);
  761.     
  762.     VWriteLine("\t\tModuleRef: (%8.8x) %ls: ", inModuleRef, moduleRefName);
  763.     DisplayCustomAttributes(inModuleRef, "\t\t");
  764. } // void MDInfo::DisplayModuleRefInfo()
  765.  
  766.  
  767. // Called to display the information about all signatures in the object.
  768. //
  769. // available: 99 only
  770.  
  771. void MDInfo::DisplaySignatures()
  772. {
  773.     HCORENUM signatureEnum = NULL;
  774.     mdSignature signatures[ENUM_BUFFER_SIZE];
  775.     ULONG count, totalCount = 1;
  776.     HRESULT hr;
  777.     
  778.     while (SUCCEEDED(hr = m_pImport->EnumSignatures( &signatureEnum,
  779.                              signatures, NumItems(signatures), &count)) &&
  780.             count > 0)
  781.     {
  782.         for (ULONG i = 0; i < count; i++, totalCount++)
  783.         {
  784.             VWriteLine("Signature #%d", totalCount);
  785.             WriteLine("-------------------------------------------------------");
  786.             DisplaySignatureInfo(signatures[i]);
  787.             WriteLine("");
  788.         }
  789.     }
  790.     m_pImport->CloseEnum( signatureEnum);
  791. } // void MDInfo::DisplaySignatures()
  792.  
  793.  
  794. // Prints out information about the given signature
  795. //
  796. // com 99 only
  797.  
  798. void MDInfo::DisplaySignatureInfo(mdSignature inSignature)
  799. {
  800.     HRESULT hr;
  801.     PCCOR_SIGNATURE pbSigBlob;
  802.     ULONG   ulSigBlob;
  803.  
  804.     if (!m_pImport) // if com99 not available
  805.         return;
  806.  
  807.     hr = m_pImport->GetSigFromToken( inSignature, &pbSigBlob, &ulSigBlob );
  808.     if (FAILED(hr)) Error("GetSigFromToken failed.", hr);
  809.     
  810.     DisplaySignature(pbSigBlob, ulSigBlob, "");
  811. } // void MDInfo::DisplaySignatureInfo()
  812.  
  813.  
  814. // returns the passed-in buffer which is filled with the name of the given 
  815. // member in wide characters
  816. //
  817. // available: 99 only
  818.  
  819. LPCWSTR MDInfo::MemberName(mdToken inToken, LPWSTR buffer, ULONG bufLen)
  820. {
  821.     HRESULT hr;
  822.     
  823.     if (!m_pImport) // if com99 not available
  824.         return L"";
  825.  
  826.     hr = m_pImport->GetMemberProps( inToken, NULL, buffer, bufLen,
  827.                             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  828.     if (FAILED(hr)) Error("GetMemberProps failed.", hr);
  829.  
  830.     return (buffer);
  831. } // LPCWSTR MDInfo::MemberName()
  832.  
  833.  
  834. // displays information for the given method
  835. //
  836. // available: 99 only
  837.  
  838. void MDInfo::DisplayMethodInfo(mdMethodDef inMethod, DWORD *pflags)
  839. {
  840.     HRESULT hr;
  841.     mdTypeDef memTypeDef;
  842.     WCHAR memberName[STRING_BUFFER_LEN];
  843.     ULONG nameLen;
  844.     DWORD flags;
  845.     PCCOR_SIGNATURE pbSigBlob;
  846.     ULONG ulSigBlob;
  847.     ULONG ulCodeRVA;
  848.     ULONG ulImplFlags;
  849.  
  850.     if (!m_pImport) // if com99 not available
  851.         return;
  852.  
  853.     hr = m_pImport->GetMethodProps( inMethod, &memTypeDef, memberName, STRING_BUFFER_LEN,
  854.                             &nameLen, &flags, &pbSigBlob, &ulSigBlob, &ulCodeRVA, &ulImplFlags);
  855.     if (FAILED(hr)) Error("GetMethodProps failed.", hr);
  856.     if (pflags)
  857.         *pflags = flags;
  858.  
  859.     VWriteLine("\t\tMethodName: %ls (%8.8X)", memberName, inMethod);
  860.  
  861.     char sFlags[STRING_BUFFER_LEN];
  862.  
  863.     strcpy(sFlags, "");
  864.     ISFLAG(Md, Public);     
  865.     ISFLAG(Md, Private);        
  866.     ISFLAG(Md, Family);     
  867.     ISFLAG(Md, Assem);      
  868.     ISFLAG(Md, FamANDAssem);    
  869.     ISFLAG(Md, FamORAssem); 
  870.     ISFLAG(Md, PrivateScope);   
  871.     ISFLAG(Md, Static);     
  872.     ISFLAG(Md, Final);      
  873.     ISFLAG(Md, Virtual);        
  874.     ISFLAG(Md, HideBySig);  
  875.     ISFLAG(Md, ReuseSlot);  
  876.     ISFLAG(Md, NewSlot);        
  877.     ISFLAG(Md, Abstract);       
  878.     ISFLAG(Md, SpecialName);    
  879.     ISFLAG(Md, RTSpecialName);
  880.     ISFLAG(Md, PinvokeImpl);
  881.     ISFLAG(Md, UnmanagedExport);
  882.     if (!*sFlags)
  883.         strcpy(sFlags, "[none]");
  884.  
  885.     if (IsMdInstanceInitializerW(flags, memberName)) strcat(sFlags, "[.ctor] ");
  886.     if (IsMdClassConstructorW(flags, memberName)) strcat(sFlags, "[.cctor] ");
  887.     // "Reserved" flags
  888.     ISFLAG(Md, HasSecurity);
  889.     ISFLAG(Md, RequireSecObject);
  890.  
  891.     VWriteLine("\t\tFlags     : %s (%08x)", sFlags, flags);
  892.     VWriteLine("\t\tRVA       : 0x%08x", ulCodeRVA);
  893.  
  894.     flags = ulImplFlags;
  895.     strcpy(sFlags, "");
  896.     ISFLAG(Mi, Native);     
  897.     ISFLAG(Mi, IL);         
  898.     ISFLAG(Mi, OPTIL);      
  899.     ISFLAG(Mi, Runtime);        
  900.     ISFLAG(Mi, Unmanaged);  
  901.     ISFLAG(Mi, Managed);        
  902.     ISFLAG(Mi, ForwardRef);
  903.     ISFLAG(Mi, OLE);            
  904.     ISFLAG(Mi, InternalCall);
  905.     ISFLAG(Mi, Synchronized);
  906.     ISFLAG(Mi, NoInlining);    
  907.     if (!*sFlags)
  908.         strcpy(sFlags, "[none]");
  909.  
  910.     VWriteLine("\t\tImplFlags : %s (%08x)", sFlags, flags);
  911.  
  912.     if (ulSigBlob)
  913.         DisplaySignature(pbSigBlob, ulSigBlob, "");
  914. } // void MDInfo::DisplayMethodInfo()
  915.  
  916. // displays the member information for the given field
  917. //
  918. // available: 99 only
  919.  
  920. void MDInfo::DisplayFieldInfo(mdFieldDef inField, DWORD *pdwFlags)
  921. {
  922.     HRESULT hr;
  923.     mdTypeDef memTypeDef;
  924.     WCHAR memberName[STRING_BUFFER_LEN];
  925.     ULONG nameLen;
  926.     DWORD flags;
  927.     PCCOR_SIGNATURE pbSigBlob;
  928.     ULONG ulSigBlob;
  929.     DWORD dwCPlusTypeFlag;
  930.     void const *pValue;
  931.     ULONG cbValue;
  932.     VARIANT defaultValue;
  933.  
  934.     if (!m_pImport) // if com99 not available
  935.         return;
  936.  
  937.     ::VariantInit(&defaultValue);
  938.     hr = m_pImport->GetFieldProps( inField, &memTypeDef, memberName, STRING_BUFFER_LEN,
  939.                             &nameLen, &flags, &pbSigBlob, &ulSigBlob, &dwCPlusTypeFlag,
  940.                             &pValue, &cbValue);
  941.     if (FAILED(hr)) Error("GetFieldProps failed.", hr);
  942.  
  943.     if (pdwFlags)
  944.         *pdwFlags = flags;
  945.  
  946.     _FillVariant((BYTE)dwCPlusTypeFlag, pValue, &defaultValue);
  947.  
  948.     char sFlags[STRING_BUFFER_LEN];
  949.  
  950.     strcpy(sFlags, "");
  951.     ISFLAG(Fd, Public);     
  952.     ISFLAG(Fd, Private);        
  953.     ISFLAG(Fd, Family);     
  954.     ISFLAG(Fd, Assembly);       
  955.     ISFLAG(Fd, FamANDAssem);    
  956.     ISFLAG(Fd, FamORAssem); 
  957.     ISFLAG(Fd, PrivateScope);   
  958.     ISFLAG(Fd, Static);     
  959.     ISFLAG(Fd, InitOnly);       
  960.     ISFLAG(Fd, Literal);        
  961.     ISFLAG(Fd, NotSerialized);
  962.     ISFLAG(Fd, SpecialName);
  963.     ISFLAG(Fd, RTSpecialName);
  964.     ISFLAG(Fd, PinvokeImpl);    
  965.     // "Reserved" flags
  966.     ISFLAG(Fd, HasSecurity);
  967.     ISFLAG(Fd, HasDefault);
  968.     if (!*sFlags)
  969.         strcpy(sFlags, "[none]");
  970.  
  971.     VWriteLine("\t\tField Name: %ls (%8.8X)", memberName, inField);
  972.     VWriteLine("\t\tFlags     : %s (%08x)", sFlags, flags);
  973.     VWriteLine("\t\tDefltValue: %ls",VariantAsString(&defaultValue));
  974.     if (!ulSigBlob) // Signature size should be non-zero for fields
  975.         Error ("Signature size should be non-zero for fields");
  976.     DisplaySignature(pbSigBlob, ulSigBlob, "");
  977. } // void MDInfo::DisplayFieldInfo()
  978.  
  979. // displays the RVA for the given global field.
  980. void MDInfo::DisplayFieldRVA(mdFieldDef inFieldDef)
  981. {
  982.     HRESULT hr;
  983.     ULONG   ulRVA;
  984.  
  985.     hr = m_pImport->GetRVA(inFieldDef, &ulRVA, 0);
  986.     if (FAILED(hr) && hr != CLDB_E_RECORD_NOTFOUND) Error("GetRVA failed.", hr);
  987.  
  988.     VWriteLine("\t\tRVA       : 0x%08x", ulRVA);
  989. } // void MDInfo::DisplayFieldRVA()
  990.  
  991. // displays information about every global function.
  992. void MDInfo::DisplayGlobalFunctions()
  993. {
  994.     WriteLine("Global functions");
  995.     WriteLine("-------------------------------------------------------");
  996.     DisplayMethods(mdTokenNil);
  997.     WriteLine("");
  998. } // void MDInfo::DisplayGlobalFunctions()
  999.  
  1000. // displays information about every global field.
  1001. void MDInfo::DisplayGlobalFields()
  1002. {
  1003.     WriteLine("Global fields");
  1004.     WriteLine("-------------------------------------------------------");
  1005.     DisplayFields(mdTokenNil, NULL, 0);
  1006.     WriteLine("");
  1007. } // void MDInfo::DisplayGlobalFields()
  1008.  
  1009. // displays information about every global memberref.
  1010. void MDInfo::DisplayGlobalMemberRefs()
  1011. {
  1012.     WriteLine("Global MemberRefs");
  1013.     WriteLine("-------------------------------------------------------");
  1014.     DisplayMemberRefs(mdTokenNil, "");
  1015.     WriteLine("");
  1016. } // void MDInfo::DisplayGlobalMemberRefs()
  1017.  
  1018. // displays information about every method in a given typedef
  1019. //
  1020. // available only under com99
  1021.  
  1022. void MDInfo::DisplayMethods(mdTypeDef inTypeDef)
  1023. {
  1024.     HCORENUM methodEnum = NULL;
  1025.     mdToken methods[ENUM_BUFFER_SIZE];
  1026.     DWORD flags;
  1027.     ULONG count, totalCount = 1;
  1028.     HRESULT hr;
  1029.     
  1030.     if (!m_pImport)
  1031.         return;
  1032.  
  1033.     while (SUCCEEDED(hr = m_pImport->EnumMethods( &methodEnum, inTypeDef,
  1034.                              methods, NumItems(methods), &count)) &&
  1035.             count > 0)
  1036.     {
  1037.         for (ULONG i = 0; i < count; i++, totalCount++)
  1038.         {
  1039.             VWriteLine("\tMethod #%d %s", totalCount,(methods[i] == g_tkEntryPoint) ? "[ENTRYPOINT]" : "");
  1040.             WriteLine("\t-------------------------------------------------------");
  1041.             DisplayMethodInfo(methods[i], &flags);
  1042.             DisplayParams(methods[i]);
  1043.             DisplayCustomAttributes(methods[i], "\t\t");
  1044.             DisplayPermissions(methods[i], "\t");
  1045.             DisplayMemberRefs(methods[i], "\t");
  1046.  
  1047.             // P-invoke data if present.
  1048.             if (IsMdPinvokeImpl(flags))
  1049.                 DisplayPinvokeInfo(methods[i]);
  1050.  
  1051.             WriteLine("");
  1052.         }
  1053.     }
  1054.     m_pImport->CloseEnum( methodEnum);
  1055. } // void MDInfo::DisplayMethods()
  1056.  
  1057.  
  1058. // displays information about every field in a given typedef
  1059. //
  1060. // available only under com99
  1061.  
  1062. void MDInfo::DisplayFields(mdTypeDef inTypeDef, COR_FIELD_OFFSET *rFieldOffset, ULONG cFieldOffset)
  1063. {
  1064.     HCORENUM fieldEnum = NULL;
  1065.     mdToken fields[ENUM_BUFFER_SIZE];
  1066.     ULONG count, totalCount = 1;
  1067.     DWORD flags;
  1068.     HRESULT hr;
  1069.     
  1070.     if (!m_pImport)
  1071.         return;
  1072.  
  1073.     while (SUCCEEDED(hr = m_pImport->EnumFields( &fieldEnum, inTypeDef,
  1074.                              fields, NumItems(fields), &count)) &&
  1075.             count > 0)
  1076.     {
  1077.         for (ULONG i = 0; i < count; i++, totalCount++)
  1078.         {
  1079.             VWriteLine("\tField #%d",totalCount);
  1080.             WriteLine("\t-------------------------------------------------------");
  1081.             DisplayFieldInfo(fields[i], &flags);
  1082.             DisplayCustomAttributes(fields[i], "\t\t");
  1083.             DisplayPermissions(fields[i], "\t");
  1084.             DisplayFieldMarshal(fields[i]);
  1085.  
  1086.             // RVA if its a global field.
  1087.             if (inTypeDef == mdTokenNil)
  1088.                 DisplayFieldRVA(fields[i]);
  1089.  
  1090.             // P-invoke data if present.
  1091.             if (IsFdPinvokeImpl(flags))
  1092.                 DisplayPinvokeInfo(fields[i]);
  1093.  
  1094.             // Display offset if present.
  1095.             if (cFieldOffset)
  1096.             {
  1097.                 bool found = false;
  1098.                 for (ULONG iLayout = 0; i < cFieldOffset; ++iLayout)
  1099.                 {
  1100.                     if (RidFromToken(rFieldOffset[iLayout].ridOfField) == RidFromToken(fields[i]))
  1101.                     {
  1102.                         found = true;
  1103.                         VWriteLine("\t\tOffset : 0x%08x", rFieldOffset[iLayout].ulOffset);
  1104.                         break;
  1105.                     }
  1106.                 }
  1107.                 _ASSERTE(found);
  1108.             }
  1109.             WriteLine("");
  1110.         }
  1111.     }
  1112.     m_pImport->CloseEnum( fieldEnum);
  1113. } // void MDInfo::DisplayFields()
  1114.  
  1115.  
  1116. // displays information about every methodImpl in a given typedef
  1117. //
  1118. // available only under com99
  1119.  
  1120. void MDInfo::DisplayMethodImpls(mdTypeDef inTypeDef)
  1121. {
  1122.     HCORENUM methodImplEnum = NULL;
  1123.     mdMethodDef rtkMethodBody[ENUM_BUFFER_SIZE];
  1124.     mdMethodDef rtkMethodDecl[ENUM_BUFFER_SIZE];
  1125.  
  1126.     ULONG count, totalCount=1;
  1127.     HRESULT hr;
  1128.  
  1129.     if (!m_pImport) // com99 only
  1130.         return;
  1131.  
  1132.     while (SUCCEEDED(hr = m_pImport->EnumMethodImpls( &methodImplEnum, inTypeDef,
  1133.                              rtkMethodBody, rtkMethodDecl, NumItems(rtkMethodBody), &count)) &&
  1134.             count > 0)
  1135.     {
  1136.         for (ULONG i = 0; i < count; i++, totalCount++)
  1137.         {
  1138.             VWriteLine("\n\tMethodImpl #%d", totalCount);
  1139.             WriteLine("\t-------------------------------------------------------");
  1140.             VWriteLine("\t\tMethod Body Token : 0x%08x", rtkMethodBody[i]);
  1141.             VWriteLine("\t\tMethod Declaration Token : 0x%08x", rtkMethodDecl[i]);
  1142.             WriteLine("");
  1143.         }
  1144.     }
  1145.     m_pImport->CloseEnum( methodImplEnum);
  1146. } // void MDInfo::DisplayMethodImpls()
  1147.  
  1148. // displays information about the given parameter
  1149. //
  1150. // available only under com99
  1151.  
  1152. void MDInfo::DisplayParamInfo(mdParamDef inParamDef)
  1153. {
  1154.     mdMethodDef md;
  1155.     ULONG num;
  1156.     WCHAR paramName[STRING_BUFFER_LEN];
  1157.     ULONG nameLen;
  1158.     DWORD flags;
  1159.     VARIANT defValue;
  1160.     DWORD dwCPlusFlags;
  1161.     void const *pValue;
  1162.     ULONG cbValue;
  1163.  
  1164.     if (!m_pImport) // if com99 not available
  1165.         return;
  1166.  
  1167.     ::VariantInit(&defValue);
  1168.     HRESULT hr = m_pImport->GetParamProps( inParamDef, &md, &num, paramName, NumItems(paramName),
  1169.                             &nameLen, &flags, &dwCPlusFlags, &pValue, &cbValue);
  1170.     if (FAILED(hr)) Error("GetParamProps failed.", hr);
  1171.     
  1172.     _FillVariant((BYTE)dwCPlusFlags, pValue, &defValue);
  1173.     
  1174.     char sFlags[STRING_BUFFER_LEN];
  1175.     strcpy(sFlags, "");
  1176.     ISFLAG(Pd, In);     
  1177.     ISFLAG(Pd, Out);        
  1178.     ISFLAG(Pd, Lcid);       
  1179.     ISFLAG(Pd, Retval); 
  1180.     ISFLAG(Pd, Optional);
  1181.     // "Reserved" flags.
  1182.     ISFLAG(Pd, HasDefault); 
  1183.     ISFLAG(Pd, HasFieldMarshal);    
  1184.     if (!*sFlags)
  1185.         strcpy(sFlags, "[none]");
  1186.  
  1187.     VWriteLine("\t\t\t(%ld) MethodToken : (%08x) Name : %ls flags: %s (%08x) default: %ls", num, md, paramName, sFlags, flags, VariantAsString(&defValue));
  1188.     DisplayCustomAttributes(inParamDef, "\t\t\t");
  1189. } // void MDInfo::DisplayParamInfo()
  1190.  
  1191.  
  1192. // displays all parameters for a given memberdef
  1193. //
  1194. // available only under com99
  1195.  
  1196. void MDInfo::DisplayParams(mdMethodDef inMethodDef)
  1197. {
  1198.     HCORENUM paramEnum = NULL;
  1199.     mdParamDef params[ENUM_BUFFER_SIZE];
  1200.     ULONG count, paramCount;
  1201.     bool first = true;
  1202.     HRESULT hr;
  1203.  
  1204.   if (!m_pImport) // if com99 not available
  1205.         return;
  1206.   
  1207.     while (SUCCEEDED(hr = m_pImport->EnumParams( ¶mEnum, inMethodDef,
  1208.                              params, NumItems(params), &count)) &&
  1209.             count > 0)
  1210.     {
  1211.         if (first)
  1212.         {
  1213.             m_pImport->CountEnum( paramEnum, ¶mCount);
  1214.             VWriteLine("\t\t%d Parameters", paramCount);
  1215.         }
  1216.         for (ULONG i = 0; i < count; i++)
  1217.         {
  1218.             DisplayParamInfo(params[i]);
  1219.             DisplayFieldMarshal(params[i]);
  1220.         }
  1221.         first = false;
  1222.     }
  1223.     m_pImport->CloseEnum( paramEnum);
  1224. } // void MDInfo::DisplayParams()
  1225.  
  1226.  
  1227. LPCWSTR MDInfo::TokenName(mdToken inToken, LPWSTR buffer, ULONG bufLen)
  1228. {
  1229.     LPCUTF8     pName;                  // Token name in UTF8.
  1230.  
  1231.     if (IsNilToken(inToken))
  1232.         return L"";
  1233.  
  1234.     m_pImport->GetNameFromToken(inToken, &pName);
  1235.  
  1236.     ::MultiByteToWideChar(CP_UTF8,0, pName,-1, buffer,bufLen);
  1237.  
  1238.     return buffer;
  1239. } // LPCWSTR MDInfo::TokenName()
  1240.  
  1241. // prints out name of typeref or typedef
  1242. //
  1243. // available: 98 and 99
  1244.  
  1245. LPCWSTR MDInfo::TypeDeforRefName(mdToken inToken, LPWSTR buffer, ULONG bufLen)
  1246. {
  1247.     if (RidFromToken(inToken))
  1248.     {
  1249.         if (TypeFromToken(inToken) == mdtTypeDef)
  1250.             return (TypeDefName((mdTypeDef) inToken, buffer, bufLen));
  1251.         else if (TypeFromToken(inToken) == mdtTypeRef)
  1252.             return (TypeRefName((mdTypeRef) inToken, buffer, bufLen));
  1253.         else
  1254.             return (L"[InvalidReference]");
  1255.     }
  1256.     else
  1257.         return (L"");
  1258. } // LPCWSTR MDInfo::TypeDeforRefName()
  1259.  
  1260. LPCWSTR MDInfo::MemberDeforRefName(mdToken inToken, LPWSTR buffer, ULONG bufLen)
  1261. {
  1262.     if (RidFromToken(inToken))
  1263.     {
  1264.         if (TypeFromToken(inToken) == mdtMethodDef || TypeFromToken(inToken) == mdtFieldDef)
  1265.             return (MemberName(inToken, buffer, bufLen));
  1266.         else if (TypeFromToken(inToken) == mdtMemberRef)
  1267.             return (MemberRefName((mdMemberRef) inToken, buffer, bufLen));
  1268.         else
  1269.             return (L"[InvalidReference]");
  1270.     }
  1271.     else
  1272.         return (L"");
  1273. } // LPCWSTR MDInfo::MemberDeforRefName()
  1274.  
  1275. // prints out only the name of the given typedef
  1276. //
  1277. // available 98 and 99
  1278.  
  1279. LPCWSTR MDInfo::TypeDefName(mdTypeDef inTypeDef, LPWSTR buffer, ULONG bufLen)
  1280. {
  1281.     HRESULT hr;
  1282.  
  1283.     hr = m_pImport->GetTypeDefProps(
  1284.                             // [IN] The import scope.
  1285.         inTypeDef,              // [IN] TypeDef token for inquiry.
  1286.         buffer,                 // [OUT] Put name here.
  1287.         bufLen,                 // [IN] size of name buffer in wide chars.
  1288.         NULL,                   // [OUT] put size of name (wide chars) here.
  1289.         NULL,                   // [OUT] Put version here.
  1290.         NULL,                   // [OUT] Put flags here.
  1291.         NULL);                  // [OUT] Put base class TypeDef/TypeRef here.
  1292.     if (FAILED(hr)) Error("GetTypeDefProps failed.", hr);
  1293.  
  1294.     return buffer;
  1295. } // LPCWSTR MDInfo::TypeDefName()
  1296.  
  1297. // prints out all the properties of a given typedef
  1298. //
  1299. // available: 98 and 99
  1300.  
  1301. void MDInfo::DisplayTypeDefProps(mdTypeDef inTypeDef)
  1302. {
  1303.     HRESULT hr;
  1304.     WCHAR typeDefName[STRING_BUFFER_LEN];
  1305.     ULONG nameLen;
  1306.     CLASSVERSION ver;
  1307.     DWORD flags;
  1308.     mdToken extends;
  1309.     ULONG       dwPacking;              // Packing size of class, if specified.
  1310.     ULONG       dwSize;                 // Total size of class, if specified.
  1311.  
  1312.     hr = m_pImport->GetTypeDefProps(
  1313.         inTypeDef,              // [IN] TypeDef token for inquiry.
  1314.         typeDefName,            // [OUT] Put name here.
  1315.         STRING_BUFFER_LEN,      // [IN] size of name buffer in wide chars.
  1316.         &nameLen,               // [OUT] put size of name (wide chars) here.
  1317.         &ver,                   // [OUT] Put version here.
  1318.         &flags,                 // [OUT] Put flags here.
  1319.         &extends);              // [OUT] Put base class TypeDef/TypeRef here.
  1320.     if (FAILED(hr)) Error("GetTypeDefProps failed.", hr);
  1321.  
  1322.     char sFlags[STRING_BUFFER_LEN];
  1323.     WCHAR szTempBuf[STRING_BUFFER_LEN];
  1324.  
  1325.     VWriteLine("\tTypDefName: %ls  (%8.8X)",typeDefName,inTypeDef);
  1326.     VWriteLine("\tFlags     : %s (%08x)",ClassFlags(flags, sFlags), flags);
  1327.     VWriteLine("\tVersion   : %d:%d:%d:%d", ((WORD *) &ver)[0], ((WORD *) &ver)[1],
  1328.                                          ((WORD *) &ver)[2], ((WORD *) &ver)[3]);
  1329.     VWriteLine("\tExtends   : %8.8X [%s] %ls",extends,TokenTypeName(extends),
  1330.                                  TypeDeforRefName(extends, szTempBuf, NumItems(szTempBuf)));
  1331.  
  1332.     hr = m_pImport->GetClassLayout(inTypeDef, &dwPacking, 0,0,0, &dwSize);
  1333.     if (hr == S_OK)
  1334.         VWriteLine("\tLayout    : Packing:%d, Size:%d", dwPacking, dwSize);
  1335.  
  1336.     if (IsTdNested(flags))
  1337.     {
  1338.         mdTypeDef   tkEnclosingClass;
  1339.  
  1340.         hr = m_pImport->GetNestedClassProps(inTypeDef, &tkEnclosingClass);
  1341.         if (hr == S_OK)
  1342.         {
  1343.             VWriteLine("\tEnclosingClass : %ls (%8.8X)", TypeDeforRefName(tkEnclosingClass,
  1344.                                             szTempBuf, NumItems(szTempBuf)), tkEnclosingClass);
  1345.         }
  1346.         else if (hr == CLDB_E_RECORD_NOTFOUND)
  1347.             WriteLine("ERROR: EnclosingClass not found for NestedClass");
  1348.         else
  1349.             Error("GetNestedClassProps failed.", hr);
  1350.     }
  1351. } // void MDInfo::DisplayTypeDefProps()
  1352.  
  1353. //  Prints out the name of the given TypeRef
  1354. //
  1355. // available: 98 and 99
  1356.  
  1357. LPCWSTR MDInfo::TypeRefName(mdTypeRef tr, LPWSTR buffer, ULONG bufLen)
  1358. {
  1359.     HRESULT hr;
  1360.     
  1361.     hr = m_pImport->GetTypeRefProps(           
  1362.         tr,                 // The class ref token.
  1363.         NULL,               // Resolution scope.
  1364.         buffer,             // Put the name here.
  1365.         bufLen,             // Size of the name buffer, wide chars.
  1366.         NULL);              // Put actual size of name here.
  1367.     if (FAILED(hr)) Error("GetTypeRefProps failed.", hr);
  1368.  
  1369.     return (buffer);
  1370. } // LPCWSTR MDInfo::TypeRefName()
  1371.  
  1372. // Prints out all the info of the given TypeRef
  1373. //
  1374. // available: 98 and 99
  1375.  
  1376. void MDInfo::DisplayTypeRefInfo(mdTypeRef tr)
  1377. {
  1378.     HRESULT hr;
  1379.     mdToken tkResolutionScope;
  1380.     WCHAR typeRefName[STRING_BUFFER_LEN];
  1381.     ULONG nameLen;
  1382.  
  1383.     hr = m_pImport->GetTypeRefProps(           
  1384.         tr,                 // The class ref token.
  1385.         &tkResolutionScope, // ResolutionScope.
  1386.         typeRefName,        // Put the name here.
  1387.         STRING_BUFFER_LEN,  // Size of the name buffer, wide chars.
  1388.         &nameLen);          // Put actual size of name here.
  1389.  
  1390.     if (FAILED(hr)) Error("GetTypeRefProps failed.", hr);
  1391.  
  1392.     if(!(m_DumpFilter & 0x10000000) && !lstrcmpW(typeRefName,L"Copyrighted.Material.Disassembly.Disabled"))
  1393.     {
  1394.         WriteLine("Information Unavailable");
  1395.         return;
  1396.     }
  1397.  
  1398.     VWriteLine("Token:             0x%08x", tr);
  1399.     VWriteLine("ResolutionScope:   0x%08x", tkResolutionScope);
  1400.     VWriteLine("TypeRefName:       %ls",typeRefName);
  1401.  
  1402.     DisplayCustomAttributes(tr, "\t");
  1403. } // void MDInfo::DisplayTypeRefInfo()
  1404.  
  1405.  
  1406. void MDInfo::DisplayTypeSpecInfo(mdTypeSpec ts, const char *preFix)
  1407. {
  1408.     HRESULT hr;
  1409.     PCCOR_SIGNATURE pvSig;
  1410.     ULONG           cbSig;
  1411.     ULONG           cb;
  1412.  
  1413.     InitSigBuffer();
  1414.  
  1415.     hr = m_pImport->GetTypeSpecFromToken(           
  1416.         ts,             // The class ref token.
  1417.         &pvSig,
  1418.         &cbSig);
  1419.  
  1420.     if (FAILED(hr)) Error("GetTypeSpecFromToken failed.", hr);
  1421.  
  1422.     if (FAILED(hr = GetOneElementType(pvSig, cbSig, &cb)))
  1423.         goto ErrExit;
  1424.  
  1425.     VWriteLine("%s\t\tTypeSpec : %s", preFix, (LPSTR)m_sigBuf.Ptr());
  1426. ErrExit:
  1427.     return;
  1428. } // void MDInfo::DisplayTypeSpecInfo()
  1429.  
  1430. // Return the passed-in buffer filled with a string detailing the class flags 
  1431. // associated with the class.
  1432. //
  1433. // available: only 99
  1434.  
  1435. char *MDInfo::ClassFlags(DWORD flags, char *sFlags)
  1436. {
  1437.     strcpy(sFlags, "");
  1438.     ISFLAG(Td, NotPublic);
  1439.     ISFLAG(Td, Public);
  1440.     ISFLAG(Td, NestedPublic);
  1441.     ISFLAG(Td, NestedPrivate);
  1442.     ISFLAG(Td, NestedFamily);
  1443.     ISFLAG(Td, NestedAssembly);
  1444.     ISFLAG(Td, NestedFamANDAssem);
  1445.     ISFLAG(Td, NestedFamORAssem);
  1446.     ISFLAG(Td, AutoLayout);     
  1447.     ISFLAG(Td, LayoutSequential);   
  1448.     ISFLAG(Td, ExplicitLayout); 
  1449.     ISFLAG(Td, Class);          
  1450.     ISFLAG(Td, Interface);      
  1451.     ISFLAG(Td, ValueType);      
  1452.     ISFLAG(Td, UnmanagedValueType);
  1453.     ISFLAG(Td, Abstract);           
  1454.     ISFLAG(Td, Sealed);         
  1455.     ISFLAG(Td, Enum);               
  1456.     ISFLAG(Td, SpecialName);
  1457.     ISFLAG(Td, RTSpecialName);
  1458.     ISFLAG(Td, Import);         
  1459.     ISFLAG(Td, Serializable);                  
  1460.     ISFLAG(Td, AnsiClass);      
  1461.     ISFLAG(Td, UnicodeClass);       
  1462.     ISFLAG(Td, AutoClass);      
  1463.     ISFLAG(Td, LateInit);
  1464.     // "Reserved" flags
  1465.     ISFLAG(Td, HasSecurity);        
  1466.     if (!*sFlags)
  1467.         strcpy(sFlags, "[none]");
  1468.  
  1469.     return sFlags;
  1470. } // char *MDInfo::ClassFlags()
  1471.  
  1472. // prints out all info on the given typeDef, including all information that
  1473. // is specific to a given typedef
  1474. //
  1475. // available: 98 and 99
  1476.  
  1477. void MDInfo::DisplayTypeDefInfo(mdTypeDef inTypeDef)
  1478. {
  1479.     // available under 98 and 99
  1480.     DisplayTypeDefProps(inTypeDef);
  1481.  
  1482.     // only available under 99, but they'll figure it out
  1483.  
  1484.     // Get field layout information.
  1485.     HRESULT             hr = NOERROR;
  1486.     COR_FIELD_OFFSET    *rFieldOffset = NULL;
  1487.     ULONG               cFieldOffset = 0;
  1488.     hr = m_pImport->GetClassLayout(inTypeDef, NULL, rFieldOffset, 0, &cFieldOffset, NULL);
  1489.     if (SUCCEEDED(hr) && cFieldOffset)
  1490.     {
  1491.         if (!(rFieldOffset = (COR_FIELD_OFFSET *)_alloca(sizeof(COR_FIELD_OFFSET) * cFieldOffset)))
  1492.             Error("_calloc failed.", E_OUTOFMEMORY);
  1493.         hr = m_pImport->GetClassLayout(inTypeDef, NULL, rFieldOffset, cFieldOffset, &cFieldOffset, NULL);
  1494.         if (FAILED(hr)) Error("GetClassLayout() failed.", hr);
  1495.     }
  1496.  
  1497.     //No reason to display members if we're displaying fields and methods separately
  1498.     DisplayFields(inTypeDef, rFieldOffset, cFieldOffset);
  1499.     DisplayMethods(inTypeDef);
  1500.     DisplayProperties(inTypeDef);
  1501.     DisplayEvents(inTypeDef);
  1502.     DisplayMethodImpls(inTypeDef);
  1503.     DisplayPermissions(inTypeDef, "");
  1504.     
  1505.     // available under 98 and 99
  1506.     DisplayInterfaceImpls(inTypeDef);
  1507.     DisplayCustomAttributes(inTypeDef, "\t");
  1508. } // void MDInfo::DisplayTypeDefInfo()
  1509.  
  1510. // print out information about every the given typeDef's interaceImpls
  1511. //
  1512. // available: 98 and 99
  1513.  
  1514. void MDInfo::DisplayInterfaceImpls(mdTypeDef inTypeDef)
  1515. {
  1516.     HCORENUM interfaceImplEnum = NULL;
  1517.     mdTypeRef interfaceImpls[ENUM_BUFFER_SIZE];
  1518.     ULONG count, totalCount = 1;
  1519.     HRESULT hr;
  1520.     
  1521.     while(SUCCEEDED(hr = m_pImport->EnumInterfaceImpls( &interfaceImplEnum,
  1522.                              inTypeDef,interfaceImpls,NumItems(interfaceImpls), &count)) &&
  1523.             count > 0)
  1524.     {
  1525.         for (ULONG i = 0; i < count; i++, totalCount++)
  1526.         {
  1527.             VWriteLine("\tInterfaceImpl #%d", totalCount);
  1528.             WriteLine("\t-------------------------------------------------------");
  1529.             DisplayInterfaceImplInfo(interfaceImpls[i]);
  1530.             DisplayPermissions(interfaceImpls[i], "\t");
  1531.             WriteLine("");
  1532.         }
  1533.     }
  1534.     m_pImport->CloseEnum( interfaceImplEnum);
  1535. } // void MDInfo::DisplayInterfaceImpls()
  1536.  
  1537. // print the information for the given interface implementation
  1538. //
  1539. // available: 98 and 99
  1540.  
  1541. void MDInfo::DisplayInterfaceImplInfo(mdInterfaceImpl inImpl)
  1542. {
  1543.     mdTypeDef typeDef;
  1544.     mdToken token;
  1545.     HRESULT hr;
  1546.  
  1547.     WCHAR szTempBuf[STRING_BUFFER_LEN];
  1548.  
  1549.     hr = m_pImport->GetInterfaceImplProps( inImpl, &typeDef, &token);
  1550.     if (FAILED(hr)) Error("GetInterfaceImplProps failed.", hr);
  1551.  
  1552.     VWriteLine("\t\tClass     : %ls",TypeDeforRefName(typeDef, szTempBuf, NumItems(szTempBuf)));
  1553.     VWriteLine("\t\tToken     : %8.8X [%s] %ls",token,TokenTypeName(token), TypeDeforRefName(token, szTempBuf, NumItems(szTempBuf)));
  1554.  
  1555.     DisplayCustomAttributes(inImpl, "\t\t");
  1556. } // void MDInfo::DisplayInterfaceImplInfo()
  1557.  
  1558. // displays the information for a particular property
  1559. //
  1560. // available: com99 only
  1561.  
  1562. void MDInfo::DisplayPropertyInfo(
  1563.     mdProperty  inProp)                 // Property token.
  1564. {
  1565.     HRESULT     hr;
  1566.     mdTypeDef   typeDef;
  1567.     WCHAR       propName[STRING_BUFFER_LEN];
  1568.     DWORD       flags;
  1569.     VARIANT     defaultValue;
  1570.     void const  *pValue;
  1571.     ULONG       cbValue;
  1572.     DWORD       dwCPlusTypeFlag;
  1573.     mdMethodDef setter, getter, otherMethod[ENUM_BUFFER_SIZE];
  1574.     ULONG       others;
  1575.     mdFieldDef  backingField;
  1576.     PCCOR_SIGNATURE pbSigBlob;
  1577.     ULONG       ulSigBlob;
  1578.  
  1579.     if (!m_pImport) // if com99 not available
  1580.         return;
  1581.  
  1582.     ::VariantInit(&defaultValue);
  1583.  
  1584.     hr = m_pImport->GetPropertyProps(
  1585.         inProp,                         // [IN] property token
  1586.         &typeDef,                       // [OUT] typedef containing the property declarion.
  1587.                                         
  1588.         propName,                       // [OUT] Property name
  1589.         STRING_BUFFER_LEN,              // [IN] the count of wchar of szProperty
  1590.         NULL,                           // [OUT] actual count of wchar for property name
  1591.                                         
  1592.         &flags,                         // [OUT] property flags.
  1593.                                         
  1594.         &pbSigBlob,                     // [OUT] Signature Blob. 
  1595.         &ulSigBlob,                     // [OUT] Number of bytes in the signature blob.
  1596.                                         
  1597.         &dwCPlusTypeFlag,               // [OUT] default value
  1598.         &pValue,                        
  1599.         &cbValue,                       
  1600.                                         
  1601.         &setter,                        // [OUT] setter method of the property
  1602.         &getter,                        // [OUT] getter method of the property
  1603.                                         
  1604.         otherMethod,                    // [OUT] other methods of the property
  1605.         ENUM_BUFFER_SIZE,               // [IN] size of rmdOtherMethod
  1606.         &others,                        // [OUT] total number of other method of this property
  1607.                                         
  1608.         &backingField);                 // [OUT] backing field
  1609.     if (FAILED(hr)) Error("GetPropertyProps failed.", hr);
  1610.  
  1611.     VWriteLine("\t\tProp.Name : %ls  (%x)",propName, inProp);
  1612.  
  1613.     char sFlags[STRING_BUFFER_LEN];
  1614.     
  1615.     strcpy(sFlags, "");
  1616.     ISFLAG(Pr, SpecialName);
  1617.     ISFLAG(Pr, RTSpecialName);
  1618.     ISFLAG(Pr, HasDefault);         
  1619.     if (!*sFlags)
  1620.         strcpy(sFlags, "[none]");
  1621.  
  1622.     VWriteLine("\t\tFlags     : %s (%08x)", sFlags, flags);
  1623.  
  1624.     if (ulSigBlob)
  1625.         DisplaySignature(pbSigBlob, ulSigBlob, "");
  1626.  
  1627.     WCHAR szTempBuf[STRING_BUFFER_LEN];
  1628.  
  1629.     _FillVariant((BYTE)dwCPlusTypeFlag, pValue, &defaultValue);
  1630.     VWriteLine("\t\tDefltValue: %ls",VariantAsString(&defaultValue));
  1631.  
  1632.     VWriteLine("\t\tSetter    : (%08x) %ls",setter,MemberDeforRefName(setter, szTempBuf, NumItems(szTempBuf)));
  1633.     VWriteLine("\t\tGetter    : (%08x) %ls",getter,MemberDeforRefName(getter, szTempBuf, NumItems(szTempBuf))); 
  1634.  
  1635.     // do something with others?
  1636.     VWriteLine("\t\t%ld Others",others);
  1637.     VWriteLine("\t\tBckngField: (%08x) %ls",backingField, TokenName(backingField, szTempBuf, NumItems(szTempBuf)));
  1638.     DisplayCustomAttributes(inProp, "\t\t");
  1639. } // void MDInfo::DisplayPropertyInfo()
  1640.  
  1641. // displays info for each property
  1642. //
  1643. // available: com99 only
  1644.  
  1645. void MDInfo::DisplayProperties(mdTypeDef inTypeDef)
  1646. {
  1647.     HCORENUM propEnum = NULL;
  1648.     mdProperty props[ENUM_BUFFER_SIZE];
  1649.     ULONG count, totalCount = 1;
  1650.     HRESULT hr;
  1651.  
  1652.     if (!m_pImport) // if com99 not available
  1653.         return;
  1654.     
  1655.     while(SUCCEEDED(hr = m_pImport->EnumProperties( &propEnum,
  1656.                              inTypeDef,props,NumItems(props), &count)) &&
  1657.             count > 0)
  1658.     {
  1659.         for (ULONG i = 0; i < count; i++, totalCount++)
  1660.         {
  1661.             VWriteLine("\tProperty #%d", totalCount);
  1662.             WriteLine("\t-------------------------------------------------------");
  1663.             DisplayPropertyInfo(props[i]);
  1664.             DisplayPermissions(props[i], "\t");
  1665.             WriteLine("");
  1666.         }
  1667.     }
  1668.     m_pImport->CloseEnum( propEnum);
  1669. } // void MDInfo::DisplayProperties()
  1670.  
  1671. // Display all information about a particular event
  1672. //
  1673. // available: com99 only
  1674.  
  1675. void MDInfo::DisplayEventInfo(mdEvent inEvent)
  1676. {
  1677.     HRESULT hr;
  1678.     mdTypeDef typeDef;
  1679.     WCHAR eventName[STRING_BUFFER_LEN];
  1680.     DWORD flags;
  1681.     mdToken eventType;
  1682.     mdMethodDef addOn, removeOn, fire, otherMethod[ENUM_BUFFER_SIZE];
  1683.     ULONG totalOther;
  1684.  
  1685.     if (!m_pImport) // if com99 not available
  1686.         return;
  1687.  
  1688.     hr = m_pImport->GetEventProps(
  1689.                             // [IN] The scope.
  1690.         inEvent,                // [IN] event token
  1691.         &typeDef,               // [OUT] typedef containing the event declarion.
  1692.         
  1693.         eventName,              // [OUT] Event name
  1694.         STRING_BUFFER_LEN,      // [IN] the count of wchar of szEvent
  1695.         NULL,                   // [OUT] actual count of wchar for event's name
  1696.  
  1697.         &flags,                 // [OUT] Event flags.
  1698.         &eventType,             // [OUT] EventType class
  1699.  
  1700.         &addOn,                 // [OUT] AddOn method of the event
  1701.         &removeOn,              // [OUT] RemoveOn method of the event
  1702.         &fire,                  // [OUT] Fire method of the event
  1703.  
  1704.         otherMethod,            // [OUT] other method of the event
  1705.         NumItems(otherMethod),  // [IN] size of rmdOtherMethod
  1706.         &totalOther);           // [OUT] total number of other method of this event
  1707.     if (FAILED(hr)) Error("GetEventProps failed.", hr);
  1708.  
  1709.     VWriteLine("\t\tName      : %ls (%8.8X)",eventName,inEvent);
  1710.     
  1711.     char sFlags[STRING_BUFFER_LEN];
  1712.  
  1713.     strcpy(sFlags, "");
  1714.     ISFLAG(Ev, SpecialName); 
  1715.     ISFLAG(Ev, RTSpecialName);    
  1716.     if (!*sFlags)
  1717.         strcpy(sFlags, "[none]");
  1718.  
  1719.     VWriteLine("\t\tFlags     : %s (%08x)", sFlags, flags);
  1720.  
  1721.     WCHAR szTempBuf[STRING_BUFFER_LEN];
  1722.  
  1723.     VWriteLine("\t\tEventType : %8.8X [%s]",eventType,TokenTypeName(eventType));
  1724.     VWriteLine("\t\tAddOnMethd: (%08x) %ls",addOn,MemberDeforRefName(addOn, szTempBuf, NumItems(szTempBuf)));
  1725.     VWriteLine("\t\tRmvOnMethd: (%08x) %ls",removeOn,MemberDeforRefName(removeOn, szTempBuf, NumItems(szTempBuf)));
  1726.     VWriteLine("\t\tFireMethod: (%08x) %ls",fire,MemberDeforRefName(fire, szTempBuf, NumItems(szTempBuf)));
  1727.     
  1728.     // todo: do something with these
  1729.     VWriteLine("\t\t%ld OtherMethods",totalOther);
  1730.     
  1731.     DisplayCustomAttributes(inEvent, "\t\t");
  1732. } // void MDInfo::DisplayEventInfo()
  1733.  
  1734. // Display information about all events in a typedef
  1735. // 
  1736. // available: com99 only
  1737.  
  1738. void MDInfo::DisplayEvents(mdTypeDef inTypeDef)
  1739. {
  1740.     HCORENUM eventEnum = NULL;
  1741.     mdProperty events[ENUM_BUFFER_SIZE];
  1742.     ULONG count, totalCount = 1;
  1743.     HRESULT hr;
  1744.  
  1745.     if (!m_pImport) // if com99 not available
  1746.         return;
  1747.     
  1748.     while(SUCCEEDED(hr = m_pImport->EnumEvents( &eventEnum,
  1749.                              inTypeDef,events,NumItems(events), &count)) &&
  1750.             count > 0)
  1751.     {
  1752.         for (ULONG i = 0; i < count; i++, totalCount++)
  1753.         {
  1754.             VWriteLine("\tEvent #%d", totalCount);
  1755.             WriteLine("\t-------------------------------------------------------");
  1756.             DisplayEventInfo(events[i]);
  1757.             DisplayPermissions(events[i], "\t");
  1758.             WriteLine("");
  1759.         }
  1760.     }
  1761.     m_pImport->CloseEnum( eventEnum);
  1762. } // void MDInfo::DisplayEvents()
  1763.  
  1764. // returns a string represtenting the name of the type of the custom attribute passed
  1765. // in.  Client should sent allocated array into szAttr arg. where the attributes
  1766. // of the custom attribute will be placed.
  1767. //
  1768. // available: 98 and 99
  1769.  
  1770. char *MDInfo::VariantTypeName(ULONG valueType, char *sAttr)
  1771. {
  1772.     strcpy(sAttr,"");
  1773.  
  1774.     if (valueType & VT_BSTR_BLOB)   strcat(sAttr,"[BSTR_BLOB] ");
  1775.     if (valueType & VT_VECTOR)      strcat(sAttr,"[VECTOR] ");
  1776.     if (valueType & VT_ARRAY)       strcat(sAttr,"[ARRAY] ");
  1777.     if (valueType & VT_BYREF)       strcat(sAttr,"[BYREF] ");
  1778.     if (valueType & VT_RESERVED)    strcat(sAttr,"[RESERVED] ");
  1779.         
  1780.     switch(valueType & VT_TYPEMASK)
  1781.     {
  1782.     case VT_EMPTY:          strcat(sAttr,"VT_EMPTY"); break;
  1783.     case VT_NULL:           strcat(sAttr,"VT_NULL"); break;
  1784.     case VT_I2:             strcat(sAttr,"VT_I2"); break;
  1785.     case VT_I4:             strcat(sAttr,"VT_I4"); break;
  1786.     case VT_R4:             strcat(sAttr,"VT_EMPTY"); break;
  1787.     case VT_R8:             strcat(sAttr,"VT_EMPTY"); break;
  1788.     case VT_CY:             strcat(sAttr,"VT_R4"); break;
  1789.     case VT_DATE:           strcat(sAttr,"VT_DATE"); break;
  1790.     case VT_BSTR:           strcat(sAttr,"VT_BSTR"); break;
  1791.     case VT_DISPATCH:       strcat(sAttr,"VT_DISPATCH"); break;
  1792.     case VT_ERROR:          strcat(sAttr,"VT_ERROR"); break;
  1793.     case VT_BOOL:           strcat(sAttr,"VT_BOOL"); break;
  1794.     case VT_VARIANT:        strcat(sAttr,"VT_VARIANT"); break;
  1795.     case VT_UNKNOWN:        strcat(sAttr,"VT_UNKNOWN"); break;
  1796.     case VT_DECIMAL:        strcat(sAttr,"VT_DECIMAL"); break;
  1797.     case VT_I1:             strcat(sAttr,"VT_I1"); break;
  1798.     case VT_UI1:            strcat(sAttr,"VT_UI1"); break;
  1799.     case VT_UI2:            strcat(sAttr,"VT_UI2"); break;
  1800.     case VT_UI4:            strcat(sAttr,"VT_UI4"); break;
  1801.     case VT_I8:             strcat(sAttr,"VT_I8"); break;
  1802.     case VT_UI8:            strcat(sAttr,"VT_UI8"); break;
  1803.     case VT_INT:            strcat(sAttr,"VT_INT"); break;
  1804.     case VT_UINT:           strcat(sAttr,"VT_UINT"); break;
  1805.     case VT_VOID:           strcat(sAttr,"VT_VOID"); break;
  1806.     case VT_HRESULT:        strcat(sAttr,"VT_HRESULT"); break;
  1807.     case VT_PTR:            strcat(sAttr,"VT_PTR"); break;
  1808.     case VT_SAFEARRAY:      strcat(sAttr,"VT_SAFEARRAY"); break;
  1809.     case VT_CARRAY:         strcat(sAttr,"VT_CARRAY"); break;
  1810.     case VT_USERDEFINED:    strcat(sAttr,"VT_USERDEFINED"); break;
  1811.     case VT_LPSTR:          strcat(sAttr,"VT_LPSTR"); break;
  1812.     case VT_LPWSTR:         strcat(sAttr,"VT_LPWSTR"); break;
  1813.     case VT_RECORD:         strcat(sAttr,"VT_RECORD"); break;
  1814.     case VT_FILETIME:       strcat(sAttr,"VT_FILETIME"); break;
  1815.     case VT_BLOB:           strcat(sAttr,"VT_BLOB"); break;
  1816.     case VT_STREAM:         strcat(sAttr,"VT_STREAM"); break;
  1817.     case VT_STORAGE:        strcat(sAttr,"VT_STORAGE"); break;
  1818.     case VT_STREAMED_OBJECT:strcat(sAttr,"VT_STREAMED_OBJECT"); break;
  1819.     case VT_STORED_OBJECT:  strcat(sAttr,"VT_STORED_OBJECT"); break;
  1820.     case VT_BLOB_OBJECT:    strcat(sAttr,"VT_BLOB_OBJECT"); break;
  1821.     case VT_CF:             strcat(sAttr,"VT_CF"); break;
  1822.     case VT_CLSID:          strcat(sAttr,"VT_CLSID"); break;
  1823.     default:                strcat(sAttr,"[Unknown type]");
  1824.     }
  1825.     return sAttr;
  1826. } // char *MDInfo::VariantTypeName()
  1827.  
  1828. // print info for the passed-in custom attribute
  1829. // This function is used to print the custom attribute information for both TypeDefs and
  1830. // MethodDefs which need slightly different formatting.  preFix helps fix it up.
  1831. //
  1832. // available: com98 and com99
  1833.  
  1834. void MDInfo::DisplayCustomAttributeInfo(mdCustomAttribute inValue, const char *preFix)
  1835. {
  1836.     const BYTE  *pValue;                // The custom value.
  1837.     ULONG       cbValue;                // Length of the custom value.
  1838.     HRESULT     hr;                     // A result.
  1839.     char        *rcBuf;
  1840.     mdToken     tkObj;                  // Attributed object.
  1841.     mdToken     tkType;                 // Type of the custom attribute.
  1842.     LPCUTF8     pTypeName=0;            // Name of the custom attribute type.
  1843.     LPCUTF8     pMethName=0;            // Name of custom attribute ctor, if any.
  1844.     CQuickBytes qSigName;               // Buffer to pretty-print signature.
  1845.     PCCOR_SIGNATURE pSig=0;             // Signature of ctor.
  1846.     ULONG       cbSig;                  // Size of the signature.
  1847.     BOOL        bCoffSymbol = false;    // true for coff symbol CA's.
  1848.  
  1849.     hr = m_pImport->GetCustomAttributeProps( // S_OK or error.
  1850.         inValue,                    // The attribute.
  1851.         &tkObj,                     // The attributed object
  1852.         &tkType,                    // The attributes type.
  1853.         (const void**)&pValue,      // Put pointer to data here.
  1854.         &cbValue);                  // Put size here.
  1855.     if (FAILED(hr)) Error("GetCustomAttributeProps failed.", hr);
  1856.  
  1857.     VWriteLine("%s\tCustomAttribute Type: %08x", preFix, tkType);
  1858.     if (TypeFromToken(tkType) == mdtTypeRef)
  1859.     {
  1860.         mdToken tkResolutionScope;
  1861.         WCHAR typeRefName[STRING_BUFFER_LEN];
  1862.         ULONG nameLen;
  1863.         hr = m_pImport->GetTypeRefProps(           
  1864.             tkType,                 // The class ref token.
  1865.             &tkResolutionScope, // ResolutionScope.
  1866.             typeRefName,        // Put the name here.
  1867.             STRING_BUFFER_LEN,  // Size of the name buffer, wide chars.
  1868.             &nameLen);          // Put actual size of name here.
  1869.         if (FAILED(hr)) Error("GetTypeRefProps failed.", hr);
  1870.         if(!(m_DumpFilter & 0x10000000) && !lstrcmpW(typeRefName,L"Copyrighted.Material.Disassembly.Disabled"))
  1871.         {
  1872.             VWriteLine("%s\tInformation Unavailable",preFix);
  1873.             return;
  1874.         }
  1875.         VWrite("%s\tCustomAttributeName: %ls", preFix, typeRefName);
  1876.     }
  1877.     else
  1878.     {
  1879.         if (TypeFromToken(tkType) == mdtMemberRef)
  1880.         {
  1881.             hr = m_pImport->GetNameFromToken(tkType, &pMethName);
  1882.             if (FAILED(hr)) Error("GetNameFromToken failed.", hr);
  1883.             hr = m_pImport->GetMemberRefProps( tkType, &tkType, 0, 0, 0, &pSig, &cbSig);
  1884.             if (FAILED(hr)) Error("GetMemberRefProps failed.", hr);
  1885.         }
  1886.         else if (TypeFromToken(tkType) == mdtMethodDef)
  1887.         {
  1888.             hr = m_pImport->GetNameFromToken(tkType, &pMethName);
  1889.             if (FAILED(hr)) Error("GetNameFromToken failed.", hr);
  1890.             hr = m_pImport->GetMethodProps(tkType, &tkType, 0, 0, 0, 0, &pSig, &cbSig, 0, 0);
  1891.             if (FAILED(hr)) Error("GetMethodProps failed.", hr);
  1892.         }
  1893.  
  1894.         if (pSig && pMethName)
  1895.         {
  1896.             int iLen;
  1897.             LPWSTR pwzName = (LPWSTR)_alloca(sizeof(WCHAR)*(iLen=1+strlen(pMethName)));
  1898.             ::MultiByteToWideChar(CP_UTF8,0, pMethName,-1, pwzName,iLen);
  1899.             PrettyPrintSig(pSig, cbSig, pwzName, &qSigName, m_pImport);
  1900.         }
  1901.  
  1902.         hr = m_pImport->GetNameFromToken(tkType, &pTypeName);
  1903.         if (FAILED(hr)) Error("GetNameFromToken failed.", hr);
  1904.         VWrite("%s\tCustomAttributeName: %s", preFix, pTypeName);
  1905.         if (pSig && pMethName)
  1906.             VWrite(" :: %S", qSigName.Ptr());
  1907.  
  1908.         if (!strcmp("__DecoratedName", pTypeName))
  1909.         {
  1910.             bCoffSymbol = true;
  1911.             g_cbCoffNames += cbValue + 6;
  1912.         }
  1913.     }
  1914.     WriteLine("");
  1915.  
  1916.     VWriteLine("%s\tValue Blob length : %ld", preFix, cbValue);
  1917.     if (cbValue)
  1918.     {
  1919.         rcBuf = (char *)_alloca(3 * cbValue + 1);
  1920.         for (ULONG i=0; i<cbValue && i<170; ++i)
  1921.             sprintf(&rcBuf[i*3], "%02x ", pValue[i]);
  1922.     }
  1923.     VWriteLine("%s\tValue     : %s", preFix, cbValue ? rcBuf : "<null>");
  1924.     if (bCoffSymbol)
  1925.         VWriteLine("%s\t            %s", preFix, pValue);
  1926.     if (pSig)
  1927.     {   // Interpret the signature.
  1928.         //@todo: all sig elements
  1929.         PCCOR_SIGNATURE ps = pSig;
  1930.         ULONG cb;
  1931.         ULONG ulData;
  1932.         ULONG cParams;
  1933.         ULONG ulVal;
  1934.         ULONG cbVal;
  1935.         LPCUTF8 pStr;
  1936.         CustomAttributeParser CA(pValue, cbValue);
  1937.         CA.GetProlog();
  1938.  
  1939.         // Get the calling convention.
  1940.         cb = CorSigUncompressData(ps, &ulData);
  1941.         ps += cb;
  1942.         // Get the count of params.
  1943.         cb = CorSigUncompressData(ps, &cParams);
  1944.         ps += cb;
  1945.         // Get the return value.
  1946.         cb = CorSigUncompressData(ps, &ulData);
  1947.         ps += cb;
  1948.         if (ulData == ELEMENT_TYPE_VOID)
  1949.         {   
  1950.             VWrite("%s\tctor args: (", preFix);
  1951.             // For each param...
  1952.             for (ULONG i=0; i<cParams; ++i)
  1953.             {   // Get the next param type.
  1954.                 cb = CorSigUncompressData(ps, &ulData);
  1955.                 ps += cb;
  1956.                 if (i) Write(", ");
  1957.                 switch (ulData)
  1958.                 {
  1959.                 case ELEMENT_TYPE_I1:
  1960.                 case ELEMENT_TYPE_U1:
  1961.                     ulVal = CA.GetU1();
  1962.                     goto PrintVal;
  1963.                 case ELEMENT_TYPE_I2:
  1964.                 case ELEMENT_TYPE_U2:
  1965.                     ulVal = CA.GetU2();
  1966.                     goto PrintVal;
  1967.                 case ELEMENT_TYPE_I4:
  1968.                 case ELEMENT_TYPE_U4:
  1969.                     ulVal = CA.GetU4();
  1970.                 PrintVal:
  1971.                 VWrite("%d", ulVal);
  1972.                     break;
  1973.                 case ELEMENT_TYPE_STRING:
  1974.                     pStr = CA.GetString(&cbVal);
  1975.                     VWrite("%s", pStr);
  1976.                     break;
  1977.                 default:
  1978.                 case ELEMENT_TYPE_I8:
  1979.                 case ELEMENT_TYPE_U8:
  1980.                 case ELEMENT_TYPE_R4:
  1981.                 case ELEMENT_TYPE_R8:
  1982.                     // bail...
  1983.                     i = cParams;
  1984.                     break;
  1985.                 }
  1986.             }
  1987.             WriteLine(")");
  1988.         }
  1989.  
  1990.     }
  1991.     WriteLine("");
  1992. } // void MDInfo::DisplayCustomAttributeInfo()
  1993.  
  1994. // Print all custom values for the given token
  1995. // This function is used to print the custom value information for all tokens.
  1996. // which need slightly different formatting.  preFix helps fix it up.
  1997. //
  1998. // available: 98 and 99
  1999.  
  2000. void MDInfo::DisplayCustomAttributes(mdToken inToken, const char *preFix)
  2001. {
  2002.     HCORENUM customAttributeEnum = NULL;
  2003.     mdTypeRef customAttributes[ENUM_BUFFER_SIZE];
  2004.     ULONG count, totalCount = 1;
  2005.     HRESULT hr;
  2006.     
  2007.     while(SUCCEEDED(hr = m_pImport->EnumCustomAttributes( &customAttributeEnum, inToken, 0,
  2008.                              customAttributes, NumItems(customAttributes), &count)) &&
  2009.           count > 0)
  2010.     {
  2011.         for (ULONG i = 0; i < count; i++, totalCount++)
  2012.         {
  2013.             VWriteLine("%sCustomAttribute #%d (%08x)", preFix, totalCount, customAttributes[i]);
  2014.             VWriteLine("%s-------------------------------------------------------", preFix);
  2015.             DisplayCustomAttributeInfo(customAttributes[i], preFix);
  2016.         }
  2017.     }
  2018.     m_pImport->CloseEnum( customAttributeEnum);
  2019. } // void MDInfo::DisplayCustomAttributes()
  2020.  
  2021. //  Show the passed-in token's permissions
  2022. //
  2023. // avail: 99 only
  2024.  
  2025. void MDInfo::DisplayPermissions(mdToken tk, const char *preFix)
  2026. {
  2027.     HCORENUM permissionEnum = NULL;
  2028.     mdPermission permissions[ENUM_BUFFER_SIZE];
  2029.     ULONG count, totalCount = 1;
  2030.     HRESULT hr;
  2031.  
  2032.     if (!m_pImport) // com 99 only
  2033.         return;
  2034.     
  2035.     while (SUCCEEDED(hr = m_pImport->EnumPermissionSets( &permissionEnum,
  2036.                      tk, 0, permissions, NumItems(permissions), &count)) &&
  2037.             count > 0)
  2038.     {
  2039.         for (ULONG i = 0; i < count; i++, totalCount++)
  2040.         {
  2041.             VWriteLine("%s\tPermission #%d", preFix, totalCount);
  2042.             VWriteLine("%s\t-------------------------------------------------------", preFix);
  2043.             DisplayPermissionInfo(permissions[i], preFix);
  2044.             WriteLine("");
  2045.         }
  2046.     }
  2047.     m_pImport->CloseEnum( permissionEnum);
  2048. } // void MDInfo::DisplayPermissions()
  2049.  
  2050. // print properties of given rolecheck
  2051. //
  2052. // avail 98 and 99
  2053.  
  2054. void MDInfo::DisplayPermissionInfo(mdPermission inPermission, const char *preFix)
  2055. {
  2056.     DWORD dwAction;
  2057.     const BYTE *pvPermission;
  2058.     ULONG cbPermission;
  2059.     char *flagDesc;
  2060.     char *rcBuf = NULL;
  2061.     char newPreFix[STRING_BUFFER_LEN];
  2062.     HRESULT hr;
  2063.  
  2064.     if (!m_pImport) // com 99 only
  2065.         return;
  2066.  
  2067.     hr = m_pImport->GetPermissionSetProps( inPermission, &dwAction,
  2068.                                         (const void**)&pvPermission, &cbPermission);
  2069.     if (FAILED(hr)) Error("GetPermissionSetProps failed.", hr);
  2070.  
  2071.     switch(dwAction)
  2072.     {
  2073.     case dclActionNil:          flagDesc = "ActionNil"; break;
  2074.     case dclRequest:            flagDesc = "Request"; break;
  2075.     case dclDemand:             flagDesc = "Demand"; break;
  2076.     case dclAssert:             flagDesc = "Assert"; break;
  2077.     case dclDeny:               flagDesc = "Deny"; break;
  2078.     case dclPermitOnly:         flagDesc = "PermitOnly"; break;
  2079.     case dclLinktimeCheck:      flagDesc = "LinktimeCheck"; break;
  2080.     case dclInheritanceCheck:   flagDesc = "InheritanceCheck"; break;
  2081.     case dclRequestMinimum:     flagDesc = "RequestMinimum"; break;
  2082.     case dclRequestOptional:    flagDesc = "RequestOptional"; break;
  2083.     case dclRequestRefuse:      flagDesc = "RequestRefuse"; break;
  2084.     }
  2085.     VWriteLine("%s\t\tAction    : %s", preFix, flagDesc);
  2086.     VWriteLine("%s\t\tBlobLen   : %d", preFix, cbPermission);
  2087.     if (cbPermission)
  2088.     {
  2089.         rcBuf = (char*)_alloca(cbPermission * 3 + 1);
  2090.         if (rcBuf != NULL)
  2091.         {
  2092.             ULONG i;
  2093.             for (i=0; i<cbPermission; ++i)
  2094.                 sprintf(&rcBuf[i*3], "%02x ", pvPermission[i]);
  2095.             rcBuf[i*3] = '\0';
  2096.         }
  2097.     }
  2098.     VWrite("%s\t\tBlob : ", preFix);
  2099.     WriteLine(cbPermission ? (rcBuf ? rcBuf : "<not enough memory>") : "<null>");
  2100.  
  2101.     sprintf (newPreFix, "\t\t%s", preFix);
  2102.     DisplayCustomAttributes(inPermission, newPreFix);
  2103. } // void MDInfo::DisplayPermissionInfo()
  2104.  
  2105.  
  2106. // simply prints out the given GUID in standard form
  2107.  
  2108. LPWSTR MDInfo::GUIDAsString(GUID inGuid, LPWSTR guidString, ULONG bufLen)
  2109. {
  2110.     StringFromGUID2(inGuid, guidString, bufLen);
  2111.     return guidString;
  2112. } // LPWSTR MDInfo::GUIDAsString()
  2113.  
  2114. LPWSTR MDInfo::VariantAsString(VARIANT *pVariant)
  2115. {
  2116.     HRESULT hr = S_OK;
  2117.     if (pVariant->vt == VT_UNKNOWN)
  2118.     {
  2119.         _ASSERTE(pVariant->punkVal == NULL);
  2120.         return (L"NULL");
  2121.     }
  2122.     else if (SUCCEEDED(hr = ::VariantChangeType(pVariant, pVariant, 0, VT_BSTR)))
  2123.         return (LPWSTR) pVariant->pbstrVal;
  2124.     else if (hr == DISP_E_BADVARTYPE && pVariant->vt == VT_I8)
  2125.     {
  2126.         // allocate the bstr.
  2127.         char    szStr[32];
  2128.         WCHAR   wszStr[32];
  2129.         // Set variant type to bstr.
  2130.         pVariant->vt = VT_BSTR;
  2131.         // Create the ansi string.
  2132.         sprintf(szStr, "%I64d", pVariant->cyVal.int64);
  2133.         // Convert to unicode.
  2134.         ::MultiByteToWideChar(CP_ACP, 0, szStr, -1, wszStr, 32);
  2135.         // convert to bstr and set variant value.
  2136.         pVariant->bstrVal = ::SysAllocString(wszStr);
  2137.         if (pVariant->bstrVal == NULL)
  2138.             Error("SysAllocString() failed.", E_OUTOFMEMORY);
  2139.         return (LPWSTR) pVariant->pbstrVal;
  2140.     }
  2141.     else
  2142.         return (L"ERROR");
  2143.     
  2144. } // LPWSTR MDInfo::VariantAsString()
  2145.  
  2146. void MDInfo::DisplayFieldMarshal(mdToken inToken)
  2147. {
  2148.     PCCOR_SIGNATURE pvNativeType;     // [OUT] native type of this field
  2149.     ULONG       cbNativeType;         // [OUT] the count of bytes of *ppvNativeType
  2150.     HRESULT hr;
  2151.  
  2152.     if (!m_pImport) // com99 only
  2153.         return;
  2154.  
  2155.     hr = m_pImport->GetFieldMarshal( inToken, &pvNativeType, &cbNativeType);
  2156.     if (FAILED(hr) && hr != CLDB_E_RECORD_NOTFOUND) Error("GetFieldMarshal failed.", hr);
  2157.     if (hr != CLDB_E_RECORD_NOTFOUND)
  2158.     {
  2159.         ULONG cbCur = 0;
  2160.         ULONG ulData;
  2161.         ULONG ulStrLoc;
  2162.  
  2163.         char szNTDesc[STRING_BUFFER_LEN];
  2164.  
  2165.         while (cbCur < cbNativeType)
  2166.         {
  2167.             ulStrLoc = 0;
  2168.  
  2169.             ulData = NATIVE_TYPE_MAX;
  2170.             cbCur += CorSigUncompressData(&pvNativeType[cbCur], &ulData);
  2171.             ulStrLoc += sprintf(szNTDesc + ulStrLoc, "%s ", (ulData < sizeof(g_szNativeType)/sizeof(*g_szNativeType)) ? g_szNativeType[ulData] : "*OUTOFRANGE*");
  2172.             switch (ulData)
  2173.             {
  2174.             case NATIVE_TYPE_FIXEDSYSSTRING:
  2175.                 {
  2176.                     if (cbCur < cbNativeType)
  2177.                     {
  2178.                         cbCur += CorSigUncompressData(&pvNativeType[cbCur], &ulData);
  2179.                         ulStrLoc += sprintf(szNTDesc + ulStrLoc, "{StringElementCount: %d} ",ulData);
  2180.                     }
  2181.                 }
  2182.                 break;
  2183.             case NATIVE_TYPE_FIXEDARRAY:
  2184.                 {
  2185.                     if (cbCur < cbNativeType)
  2186.                     {
  2187.                         cbCur += CorSigUncompressData(&pvNativeType[cbCur], &ulData);
  2188.                         ulStrLoc += sprintf(szNTDesc + ulStrLoc, "{ArrayElementCount: %d",ulData);
  2189.  
  2190.                         if (cbCur < cbNativeType)
  2191.                         {
  2192.                             cbCur += CorSigUncompressData(&pvNativeType[cbCur], &ulData);
  2193.                             ulStrLoc += sprintf(szNTDesc + ulStrLoc, ", ArrayElementType(NT): %d",ulData);
  2194.                         }
  2195.  
  2196.                         ulStrLoc += sprintf(szNTDesc + ulStrLoc, "}");
  2197.                     }
  2198.                 }
  2199.                 break;
  2200.             case NATIVE_TYPE_ARRAY:
  2201.                 {
  2202.                     if (cbCur < cbNativeType)
  2203.                     {
  2204.                         BOOL bElemTypeSpecified;
  2205.  
  2206.                         cbCur += CorSigUncompressData(&pvNativeType[cbCur], &ulData);
  2207.                         if (ulData != NATIVE_TYPE_MAX)
  2208.                         {
  2209.                             ulStrLoc += sprintf(szNTDesc + ulStrLoc, "{ArrayElementType(NT): %d", ulData);
  2210.                             bElemTypeSpecified = TRUE;
  2211.                         }
  2212.                         else
  2213.                         {
  2214.                             ulStrLoc += sprintf(szNTDesc + ulStrLoc, "{");
  2215.                             bElemTypeSpecified = FALSE;
  2216.                         }
  2217.  
  2218.                         if (cbCur < cbNativeType)
  2219.                         {
  2220.                             if (bElemTypeSpecified)
  2221.                                 ulStrLoc += sprintf(szNTDesc + ulStrLoc, ", ",ulData);
  2222.  
  2223.                             cbCur += CorSigUncompressData(&pvNativeType[cbCur], &ulData);
  2224.                             ulStrLoc += sprintf(szNTDesc + ulStrLoc, "SizeParamIndex: %d",ulData);
  2225.  
  2226.                             if (cbCur < cbNativeType)
  2227.                             {
  2228.                                 cbCur += CorSigUncompressData(&pvNativeType[cbCur], &ulData);
  2229.                                 ulStrLoc += sprintf(szNTDesc + ulStrLoc, ", SizeParamMultiplier: %d",ulData);
  2230.  
  2231.                                 if (cbCur < cbNativeType)
  2232.                                 {
  2233.                                     cbCur += CorSigUncompressData(&pvNativeType[cbCur], &ulData);
  2234.                                     ulStrLoc += sprintf(szNTDesc + ulStrLoc, ", SizeConst: %d",ulData);
  2235.                                 }
  2236.                             }
  2237.                         }
  2238.  
  2239.                         ulStrLoc += sprintf(szNTDesc + ulStrLoc, "}");
  2240.                     }
  2241.                 }
  2242.                 break;
  2243.             case NATIVE_TYPE_SAFEARRAY:
  2244.                 {
  2245.                     if (cbCur < cbNativeType)
  2246.                     {
  2247.                         cbCur += CorSigUncompressData(&pvNativeType[cbCur], &ulData);
  2248.                         ulStrLoc += sprintf(szNTDesc + ulStrLoc, "{SafeArraySubType(VT): %d} ",ulData);
  2249.                     }
  2250.                 }
  2251.                 break;
  2252.             case NATIVE_TYPE_CUSTOMMARSHALER:
  2253.                 {
  2254.                     LPUTF8 strTemp = NULL;
  2255.                     int strLen = 0;
  2256.                     ULONG ByteCountLength = 0;         
  2257.  
  2258.                     // Extract the typelib GUID.
  2259.                     strLen = CorSigUncompressData(&pvNativeType[cbCur], &ByteCountLength);
  2260.                     cbCur += ByteCountLength;
  2261.                     strTemp = (LPUTF8)_alloca(strLen + 1);
  2262.                     memcpy(strTemp, (LPUTF8)&pvNativeType[cbCur], strLen);
  2263.                     strTemp[strLen] = 0;
  2264.                     ulStrLoc += sprintf(szNTDesc + ulStrLoc, "{Typelib: %s, ", strTemp);
  2265.                     cbCur += strLen;
  2266.                     _ASSERTE(cbCur < cbNativeType);
  2267.  
  2268.                     // Extract the name of the native type.
  2269.                     strLen = CorSigUncompressData(&pvNativeType[cbCur], &ByteCountLength);
  2270.                     cbCur += ByteCountLength;
  2271.                     strTemp = (LPUTF8)_alloca(strLen + 1);
  2272.                     memcpy(strTemp, (LPUTF8)&pvNativeType[cbCur], strLen);
  2273.                     strTemp[strLen] = 0;
  2274.                     ulStrLoc += sprintf(szNTDesc + ulStrLoc, "Native: %s, ", strTemp);
  2275.                     cbCur += strLen;
  2276.                     _ASSERTE(cbCur < cbNativeType);
  2277.  
  2278.                     // Extract the name of the custom marshaler.
  2279.                     strLen = CorSigUncompressData(&pvNativeType[cbCur], &ByteCountLength);
  2280.                     cbCur += ByteCountLength;
  2281.                     strTemp = (LPUTF8)_alloca(strLen + 1);
  2282.                     memcpy(strTemp, (LPUTF8)&pvNativeType[cbCur], strLen);
  2283.                     strTemp[strLen] = 0;
  2284.                     ulStrLoc += sprintf(szNTDesc + ulStrLoc, "Marshaler: %s, ", strTemp);
  2285.                     cbCur += strLen;
  2286.                     _ASSERTE(cbCur < cbNativeType);
  2287.  
  2288.                     // Extract the cookie string.
  2289.                     strLen = CorSigUncompressData(&pvNativeType[cbCur], &ByteCountLength);
  2290.                     cbCur += ByteCountLength;
  2291.                     if (strLen > 0)
  2292.                     {
  2293.                         strTemp = (LPUTF8)_alloca(strLen + 1);
  2294.                         memcpy(strTemp, (LPUTF8)&pvNativeType[cbCur], strLen);
  2295.                         strTemp[strLen] = 0;
  2296.                         ulStrLoc += sprintf(szNTDesc + ulStrLoc, "Cookie: ");
  2297.  
  2298.                         // Copy the cookie string and transform the embedded nulls into \0's.
  2299.                         for (int i = 0; i < strLen - 1; i++, cbCur++)
  2300.                         {
  2301.                             if (strTemp[i] == 0)
  2302.                                 ulStrLoc += sprintf(szNTDesc + ulStrLoc, "\\0");
  2303.                             else
  2304.                                 szNTDesc[ulStrLoc++] = strTemp[i];
  2305.                         }
  2306.                         szNTDesc[ulStrLoc++] = strTemp[strLen - 1];
  2307.                         cbCur++;
  2308.                     }
  2309.                     else
  2310.                     {
  2311.                         ulStrLoc += sprintf(szNTDesc + ulStrLoc, "Cookie: ");
  2312.                     }
  2313.  
  2314.                     // Finish the custom marshaler native type description.
  2315.                     ulStrLoc += sprintf(szNTDesc + ulStrLoc, "}");
  2316.                     _ASSERTE(cbCur <= cbNativeType);
  2317.                     break;
  2318.                 }           
  2319.                 break;
  2320.             default:
  2321.                 {
  2322.                     // normal nativetype element: do nothing
  2323.                 }
  2324.             }
  2325.             VWriteLine("\t\t\t\t%s",szNTDesc);
  2326.             if (ulData >= NATIVE_TYPE_MAX)
  2327.                 break;
  2328.         }
  2329.     }
  2330. } // void MDInfo::DisplayFieldMarshal()
  2331.  
  2332. void MDInfo::DisplayPinvokeInfo(mdToken inToken)
  2333. {
  2334.     HRESULT hr = NOERROR;
  2335.     DWORD flags;
  2336.     WCHAR rcImport[512];
  2337.     mdModuleRef tkModuleRef;
  2338.             
  2339.     char sFlags[STRING_BUFFER_LEN];
  2340.  
  2341.     hr = m_pImport->GetPinvokeMap(inToken, &flags, rcImport,
  2342.                                   NumItems(rcImport), 0, &tkModuleRef);
  2343.     if (FAILED(hr))
  2344.     {
  2345.         if (hr != CLDB_E_RECORD_NOTFOUND)
  2346.             VWriteLine("ERROR: GetPinvokeMap failed.", hr);
  2347.         return;
  2348.     }
  2349.                 
  2350.     WriteLine("\t\tPinvoke Map Data:");
  2351.     VWriteLine("\t\tEntry point:      %S", rcImport);
  2352.     VWriteLine("\t\tModule ref:       %08x", tkModuleRef);
  2353.             
  2354.     strcpy(sFlags, "");
  2355.     ISFLAG(Pm, NoMangle);           
  2356.     ISFLAG(Pm, CharSetNotSpec);
  2357.     ISFLAG(Pm, CharSetAnsi);        
  2358.     ISFLAG(Pm, CharSetUnicode); 
  2359.     ISFLAG(Pm, CharSetAuto);
  2360.     ISFLAG(Pm, PinvokeOLE);     
  2361.     ISFLAG(Pm, SupportsLastError);  
  2362.     ISFLAG(Pm, CallConvWinapi); 
  2363.     ISFLAG(Pm, CallConvCdecl);  
  2364.     ISFLAG(Pm, CallConvStdcall);
  2365.     ISFLAG(Pm, CallConvThiscall);   
  2366.     ISFLAG(Pm, CallConvFastcall);   
  2367.     if (!*sFlags)
  2368.         strcpy(sFlags, "[none]");
  2369.         
  2370.     VWriteLine("\t\tMapping flags:    %s (%08x)", sFlags, flags);
  2371. }   // void MDInfo::DisplayPinvokeInfo()
  2372.  
  2373.  
  2374. /////////////////////////////////////////////////////////////////////////
  2375. // void DisplaySignature(PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob);
  2376. //
  2377. // Display NGWS signature
  2378. /////////////////////////////////////////////////////////////////////////
  2379. void MDInfo::DisplaySignature(PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob, const char *preFix)
  2380. {
  2381.     ULONG       cbCur = 0;
  2382.     ULONG       cb;
  2383.     ULONG       ulData;
  2384.     ULONG       ulArgs;
  2385.     HRESULT     hr = NOERROR;
  2386.     ULONG       ulSigBlobStart = ulSigBlob;
  2387.  
  2388.     // initialize sigBuf
  2389.     InitSigBuffer();
  2390.  
  2391.     if (!m_pImport) // if not com99
  2392.         return;
  2393.  
  2394.     cb = CorSigUncompressData(pbSigBlob, &ulData);
  2395.     VWriteLine("%s\t\tCall conv.: %s", preFix, (g_strCalling[ulData & IMAGE_CEE_CS_CALLCONV_MASK]));
  2396.     if (cb>ulSigBlob) 
  2397.         goto ErrExit;
  2398.     cbCur += cb;
  2399.     ulSigBlob -= cb;
  2400.  
  2401.     if (ulData & IMAGE_CEE_CS_CALLCONV_HASTHIS)
  2402.         VWriteLine("%s\t\thasThis ", preFix);
  2403.     if (ulData & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS)
  2404.         VWriteLine("%s\t\texplicit ", preFix);
  2405.  
  2406.     // initialize sigBuf
  2407.     InitSigBuffer();
  2408.     if ( isCallConv(ulData,IMAGE_CEE_CS_CALLCONV_FIELD) )
  2409.     {
  2410.  
  2411.         // display field type
  2412.         if (FAILED(hr = GetOneElementType(&pbSigBlob[cbCur], ulSigBlob, &cb)))
  2413.             goto ErrExit;
  2414.         VWriteLine("%s\t\tField type: %s", preFix, (LPSTR)m_sigBuf.Ptr());
  2415.         if (cb>ulSigBlob) 
  2416.             goto ErrExit;
  2417.         cbCur += cb;
  2418.         ulSigBlob -= cb;
  2419.     }
  2420.     else 
  2421.     {
  2422.         cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulArgs);
  2423.         if (cb>ulSigBlob) 
  2424.             goto ErrExit;
  2425.         cbCur += cb;
  2426.         ulSigBlob -= cb;
  2427.  
  2428.         if (ulData != IMAGE_CEE_CS_CALLCONV_LOCAL_SIG)
  2429.         {
  2430.             // display return type when it is not a local varsig
  2431.             if (FAILED(hr = GetOneElementType(&pbSigBlob[cbCur], ulSigBlob, &cb)))
  2432.                 goto ErrExit;
  2433.             VWriteLine("%s\t\tReturnType:%s", preFix, (LPSTR)m_sigBuf.Ptr());
  2434.             if (cb>ulSigBlob) 
  2435.                 goto ErrExit;
  2436.             cbCur += cb;
  2437.             ulSigBlob -= cb;
  2438.         }
  2439.  
  2440.         // display count of argument
  2441.         // display arguments
  2442.         if (ulSigBlob)
  2443.             VWriteLine("%s\t\t%ld Arguments", preFix, ulArgs);
  2444.         else
  2445.             VWriteLine("%s\t\tNo arguments.", preFix);
  2446.  
  2447.         ULONG       i = 0;
  2448.         while (i < ulArgs && ulSigBlob > 0)
  2449.         {
  2450.             ULONG       ulData;
  2451.  
  2452.             // Handle the sentinal for varargs because it isn't counted in the args.
  2453.             CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
  2454.             ++i;
  2455.  
  2456.             // initialize sigBuf
  2457.             InitSigBuffer();
  2458.  
  2459.             if (FAILED(hr = GetOneElementType(&pbSigBlob[cbCur], ulSigBlob, &cb)))
  2460.                 goto ErrExit;
  2461.  
  2462.             VWriteLine("%s\t\t\tArgument #%ld: %s",preFix, i, (LPSTR)m_sigBuf.Ptr());
  2463.     
  2464.             if (cb>ulSigBlob) 
  2465.                 goto ErrExit;
  2466.  
  2467.             cbCur += cb;
  2468.             ulSigBlob -= cb;
  2469.         }
  2470.     }
  2471.  
  2472.     // Nothing consumed but not yet counted.
  2473.     cb = 0;
  2474.  
  2475. ErrExit:
  2476.     // We should have consumed all signature blob.  If not, dump the sig in hex.
  2477.     //  Also dump in hex if so requested.
  2478.     if (m_DumpFilter & dumpMoreHex || ulSigBlob != 0)
  2479.     {
  2480.         // Did we not consume enough, or try to consume too much?
  2481.         if (cb > ulSigBlob)
  2482.             WriteLine("\tERROR IN SIGNATURE:  Signature should be larger.");
  2483.         else
  2484.         if (cb < ulSigBlob)
  2485.         {
  2486.             VWrite("\tERROR IN SIGNATURE:  Not all of signature blob was consumed.  %d byte(s) remain", ulSigBlob);
  2487.             // If it is short, just append it to the end.
  2488.             if (ulSigBlob < 4)
  2489.             {
  2490.                 Write(": ");
  2491.                 for (; ulSigBlob; ++cbCur, --ulSigBlob)
  2492.                     VWrite("%02x ", pbSigBlob[cbCur]);
  2493.                 WriteLine("");
  2494.                 goto ErrExit2;
  2495.             }
  2496.             WriteLine("");
  2497.         }
  2498.  
  2499.         // Any appropriate error message has been issued.  Dump sig in hex, as determined
  2500.         //  by error or command line switch.
  2501.         cbCur = 0;
  2502.         ulSigBlob = ulSigBlobStart;
  2503.         WriteLine("\t\tSignature:");
  2504.         while (ulSigBlob)
  2505.         {   // Each line has 4 groups...
  2506.             Write("\t\t");
  2507.             for (ULONG i=0; i<4 && ulSigBlob ; ++i)
  2508.             {   // Of four values
  2509.                 for (ULONG j=0; j<4 && ulSigBlob; ++j, ++cbCur, --ulSigBlob)
  2510.                     VWrite("%02x ", pbSigBlob[cbCur]);
  2511.                 Write("  ");
  2512.             }
  2513.             WriteLine("");
  2514.         }
  2515.     }
  2516. ErrExit2:
  2517.     if (FAILED(hr))
  2518.         Error("ERROR!! Bad signature blob value!");
  2519.     return;
  2520. } // void MDInfo::DisplaySignature()
  2521.  
  2522.  
  2523. /////////////////////////////////////////////////////////////////////////
  2524. // HRESULT GetOneElementType(mdScope tkScope, BYTE *pbSigBlob, ULONG ulSigBlob, ULONG *pcb)
  2525. //
  2526. // Adds description of element type to the end of buffer -- caller must ensure
  2527. // buffer is large enough.
  2528. /////////////////////////////////////////////////////////////////////////
  2529. HRESULT MDInfo::GetOneElementType(PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob, ULONG *pcb)
  2530. {
  2531.     HRESULT     hr = S_OK;              // A result.
  2532.     ULONG       cbCur = 0;
  2533.     ULONG       cb;
  2534.     ULONG       ulData;
  2535.     ULONG       ulTemp;
  2536.     int         iTemp;
  2537.     mdToken     tk;
  2538.  
  2539.     cb = CorSigUncompressData(pbSigBlob, &ulData);
  2540.     cbCur += cb;
  2541.  
  2542.     // Handle the modifiers.
  2543.     if (ulData & ELEMENT_TYPE_MODIFIER)
  2544.     {
  2545.         if (ulData == ELEMENT_TYPE_SENTINEL)
  2546.             IfFailGo(AddToSigBuffer("<ELEMENT_TYPE_SENTINEL>"));
  2547.         else if (ulData == ELEMENT_TYPE_PINNED)
  2548.             IfFailGo(AddToSigBuffer("PINNED"));
  2549.         else
  2550.         {
  2551.             hr = E_FAIL;
  2552.             goto ErrExit;
  2553.         }
  2554.         if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
  2555.             goto ErrExit;
  2556.         cbCur += cb;
  2557.         goto ErrExit;
  2558.     }
  2559.  
  2560.     // Handle the underlying element types.
  2561.     if (ulData >= ELEMENT_TYPE_MAX) 
  2562.     {
  2563.         hr = E_FAIL;
  2564.         goto ErrExit;
  2565.     }
  2566.     while (ulData == ELEMENT_TYPE_PTR || ulData == ELEMENT_TYPE_BYREF || ulData == ELEMENT_TYPE_COPYCTOR)
  2567.     {
  2568.         IfFailGo(AddToSigBuffer(" "));
  2569.         IfFailGo(AddToSigBuffer(g_szMapElementType[ulData]));
  2570.         cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
  2571.         cbCur += cb;
  2572.     }
  2573.     IfFailGo(AddToSigBuffer(" "));
  2574.     IfFailGo(AddToSigBuffer(g_szMapElementType[ulData]));
  2575.     if (CorIsPrimitiveType((CorElementType)ulData) || 
  2576.         ulData == ELEMENT_TYPE_TYPEDBYREF ||
  2577.         ulData == ELEMENT_TYPE_OBJECT ||
  2578.         ulData == ELEMENT_TYPE_I ||
  2579.         ulData == ELEMENT_TYPE_U ||
  2580.         ulData == ELEMENT_TYPE_R)
  2581.     {
  2582.         // If this is a primitive type, we are done
  2583.         goto ErrExit;
  2584.     }
  2585.     if (ulData == ELEMENT_TYPE_VALUETYPE || 
  2586.         ulData == ELEMENT_TYPE_CLASS || 
  2587.         ulData == ELEMENT_TYPE_CMOD_REQD ||
  2588.         ulData == ELEMENT_TYPE_CMOD_OPT)
  2589.     {
  2590.         cb = CorSigUncompressToken(&pbSigBlob[cbCur], &tk);
  2591.         cbCur += cb;
  2592.  
  2593.         // get the name of type ref. Don't care if truncated
  2594.         if (TypeFromToken(tk) == mdtTypeDef || TypeFromToken(tk) == mdtTypeRef)
  2595.         {
  2596.             sprintf(m_tempFormatBuffer, " %ls",TypeDeforRefName(tk, m_szTempBuf, NumItems(m_szTempBuf)));
  2597.             IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
  2598.         }
  2599.         else
  2600.         {
  2601.             _ASSERTE(TypeFromToken(tk) == mdtTypeSpec);
  2602.             sprintf(m_tempFormatBuffer, " %8x", tk);
  2603.             IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
  2604.         }
  2605.         if (ulData == ELEMENT_TYPE_CMOD_REQD ||
  2606.             ulData == ELEMENT_TYPE_CMOD_OPT)
  2607.         {
  2608.             if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
  2609.                 goto ErrExit;
  2610.             cbCur += cb;
  2611.         }
  2612.  
  2613.         goto ErrExit;
  2614.     }
  2615.     if (ulData == ELEMENT_TYPE_VALUEARRAY)
  2616.     {
  2617.         // display the base type of SDARRAY
  2618.         if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
  2619.             goto ErrExit;
  2620.         cbCur += cb;
  2621.  
  2622.         // display the size of SDARRAY
  2623.         cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
  2624.         cbCur += cb;
  2625.         sprintf(m_tempFormatBuffer, " %d", ulData);
  2626.         IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
  2627.         goto ErrExit;
  2628.     }
  2629.     if (ulData == ELEMENT_TYPE_SZARRAY || ulData == ELEMENT_TYPE_GENERICARRAY)
  2630.     {
  2631.         // display the base type of SZARRAY or GENERICARRAY
  2632.         if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
  2633.             goto ErrExit;
  2634.         cbCur += cb;
  2635.         goto ErrExit;
  2636.     }
  2637.     if (ulData == ELEMENT_TYPE_FNPTR) 
  2638.     {
  2639.         cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
  2640.         cbCur += cb;
  2641.         if (ulData & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS)
  2642.             IfFailGo(AddToSigBuffer(" explicit"));
  2643.         if (ulData & IMAGE_CEE_CS_CALLCONV_HASTHIS)
  2644.             IfFailGo(AddToSigBuffer(" hasThis"));
  2645.  
  2646.         IfFailGo(AddToSigBuffer(" "));
  2647.         IfFailGo(AddToSigBuffer(g_strCalling[ulData & IMAGE_CEE_CS_CALLCONV_MASK]));
  2648.  
  2649.             // Get number of args
  2650.         ULONG numArgs;
  2651.         cb = CorSigUncompressData(&pbSigBlob[cbCur], &numArgs);
  2652.         cbCur += cb;
  2653.  
  2654.             // do return type
  2655.         if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
  2656.             goto ErrExit;
  2657.         cbCur += cb;
  2658.  
  2659.         IfFailGo(AddToSigBuffer("("));
  2660.         while (numArgs > 0) 
  2661.         {
  2662.             if (cbCur > ulSigBlob)
  2663.                 goto ErrExit;
  2664.             if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
  2665.                 goto ErrExit;
  2666.             cbCur += cb;
  2667.             --numArgs;
  2668.             if (numArgs > 0) 
  2669.                 IfFailGo(AddToSigBuffer(","));
  2670.         }
  2671.         IfFailGo(AddToSigBuffer(" )"));
  2672.         goto ErrExit;
  2673.     }
  2674.  
  2675.     _ASSERTE(ulData == ELEMENT_TYPE_ARRAY);
  2676.  
  2677.     // display the base type of SDARRAY
  2678.     if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
  2679.         goto ErrExit;
  2680.     cbCur += cb;
  2681.  
  2682.     // display the rank of MDARRAY
  2683.     cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
  2684.     cbCur += cb;
  2685.     sprintf(m_tempFormatBuffer, " %d", ulData);
  2686.     IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
  2687.     if (ulData == 0)
  2688.         // we are done if no rank specified
  2689.         goto ErrExit;
  2690.  
  2691.     // how many dimensions have size specified?
  2692.     cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
  2693.     cbCur += cb;
  2694.     sprintf(m_tempFormatBuffer, " %d", ulData);
  2695.     IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
  2696.     while (ulData)
  2697.     {
  2698.  
  2699.         cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulTemp);
  2700.         sprintf(m_tempFormatBuffer, " %d", ulTemp);
  2701.         IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
  2702.         cbCur += cb;
  2703.         ulData--;
  2704.     }
  2705.     // how many dimensions have lower bounds specified?
  2706.     cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
  2707.     cbCur += cb;
  2708.     sprintf(m_tempFormatBuffer, " %d", ulData);
  2709.     IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
  2710.     while (ulData)
  2711.     {
  2712.  
  2713.         cb = CorSigUncompressSignedInt(&pbSigBlob[cbCur], &iTemp);
  2714.         sprintf(m_tempFormatBuffer, " %d", iTemp);
  2715.         IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
  2716.         cbCur += cb;
  2717.         ulData--;
  2718.     }
  2719.     
  2720. ErrExit:
  2721.     if (cbCur > ulSigBlob)
  2722.         hr = E_FAIL;
  2723.     *pcb = cbCur;
  2724.     return hr;
  2725. } // HRESULT MDInfo::GetOneElementType()
  2726.  
  2727. // Display the fields of the N/Direct custom value structure.
  2728.  
  2729. void MDInfo::DisplayCorNativeLink(COR_NATIVE_LINK *pCorNLnk, const char *preFix)
  2730. {
  2731.     // Print the LinkType.
  2732.     char *curField = "\tLink Type : ";
  2733.     switch(pCorNLnk->m_linkType)
  2734.     {
  2735.     case nltNone:
  2736.         VWriteLine("%s%s%s(%02x)", preFix, curField, "nltNone", pCorNLnk->m_linkType);
  2737.         break;
  2738.     case nltAnsi:
  2739.         VWriteLine("%s%s%s(%02x)", preFix, curField, "nltAnsi", pCorNLnk->m_linkType);
  2740.         break;
  2741.     case nltUnicode:
  2742.         VWriteLine("%s%s%s(%02x)", preFix, curField, "nltUnicode", pCorNLnk->m_linkType);
  2743.         break;
  2744.     case nltAuto:
  2745.         VWriteLine("%s%s%s(%02x)", preFix, curField, "nltAuto", pCorNLnk->m_linkType);
  2746.         break;
  2747.     case nltOle:
  2748.         VWriteLine("%s%s%s(%02x)", preFix, curField, "nltOle", pCorNLnk->m_linkType);
  2749.         break;
  2750.     default:
  2751.         _ASSERTE(!"Invalid Native Link Type!");
  2752.     }
  2753.  
  2754.     // Print the link flags
  2755.     curField = "\tLink Flags : ";
  2756.     switch(pCorNLnk->m_flags)
  2757.     {
  2758.     case nlfNone:
  2759.         VWriteLine("%s%s%s(%02x)", preFix, curField, "nlfNone", pCorNLnk->m_flags);
  2760.         break;
  2761.     case nlfLastError:
  2762.         VWriteLine("%s%s%s(%02x)", preFix, curField, "nlfLastError", pCorNLnk->m_flags);
  2763.             break;
  2764.     default:
  2765.         _ASSERTE(!"Invalid Native Link Flags!");
  2766.     }
  2767.  
  2768.     // Print the entry point.
  2769.     WCHAR memRefName[STRING_BUFFER_LEN];
  2770.     HRESULT hr;
  2771.     hr = m_pImport->GetMemberRefProps( pCorNLnk->m_entryPoint, NULL, memRefName,
  2772.                                     STRING_BUFFER_LEN, NULL, NULL, NULL);
  2773.     if (FAILED(hr)) Error("GetMemberRefProps failed.", hr);
  2774.     VWriteLine("%s\tEntry Point : %ls (0x%08x)", preFix, memRefName, pCorNLnk->m_entryPoint);
  2775. } // void MDInfo::DisplayCorNativeLink()
  2776.  
  2777. // Fills given varaint with value given in pValue and of type in bCPlusTypeFlag
  2778. //
  2779. // Taken from MetaInternal.cpp
  2780.  
  2781. HRESULT _FillVariant(
  2782.     BYTE        bCPlusTypeFlag, 
  2783.     const void  *pValue,
  2784.     VARIANT     *pvar) 
  2785. {
  2786.     HRESULT     hr = NOERROR;
  2787.     switch (bCPlusTypeFlag)
  2788.     {
  2789.     case ELEMENT_TYPE_BOOLEAN:
  2790.         pvar->vt = VT_BOOL;
  2791.         pvar->boolVal = *((VARIANT_BOOL *)pValue);
  2792.         break;
  2793.     case ELEMENT_TYPE_I1:
  2794.         pvar->vt = VT_I1;
  2795.         pvar->cVal = *((CHAR*)pValue);
  2796.         break;  
  2797.     case ELEMENT_TYPE_U1:
  2798.         pvar->vt = VT_UI1;
  2799.         pvar->bVal = *((BYTE*)pValue);
  2800.         break;  
  2801.     case ELEMENT_TYPE_I2:
  2802.         pvar->vt = VT_I2;
  2803.         pvar->iVal = *((SHORT*)pValue);
  2804.         break;  
  2805.     case ELEMENT_TYPE_U2:
  2806.     case ELEMENT_TYPE_CHAR:
  2807.         pvar->vt = VT_UI2;
  2808.         pvar->uiVal = *((USHORT*)pValue);
  2809.         break;  
  2810.     case ELEMENT_TYPE_I4:
  2811.         pvar->vt = VT_I4;
  2812.         pvar->lVal = *((LONG*)pValue);
  2813.         break;  
  2814.     case ELEMENT_TYPE_U4:
  2815.         pvar->vt = VT_UI4;
  2816.         pvar->ulVal = *((ULONG*)pValue);
  2817.         break;  
  2818.     case ELEMENT_TYPE_R4:
  2819.         pvar->vt = VT_R4;
  2820.         pvar->fltVal = *((FLOAT*)pValue);
  2821.         break;  
  2822.     case ELEMENT_TYPE_R8:
  2823.         pvar->vt = VT_R8;
  2824.         pvar->dblVal = *((DOUBLE*)pValue);
  2825.         break;  
  2826.     case ELEMENT_TYPE_STRING:
  2827.         pvar->vt = VT_BSTR;
  2828.  
  2829.         // allocated bstr here
  2830.         pvar->bstrVal = ::SysAllocString((LPWSTR)pValue);
  2831.         if (pvar->bstrVal == NULL)
  2832.             hr = E_OUTOFMEMORY;
  2833.         break;  
  2834.     case ELEMENT_TYPE_CLASS:
  2835.         pvar->punkVal = NULL;
  2836.         pvar->vt = VT_UNKNOWN;
  2837.         _ASSERTE( *((IUnknown **)pValue) == NULL );
  2838.         break;  
  2839.     case ELEMENT_TYPE_I8:
  2840.         pvar->vt = VT_I8;
  2841.         pvar->cyVal.int64 = *((LONGLONG*)pValue);
  2842.         break;
  2843.     case ELEMENT_TYPE_U8:
  2844.         pvar->vt = VT_UI8;
  2845.         pvar->cyVal.int64 = *((LONGLONG*)pValue);
  2846.         break;
  2847.     case ELEMENT_TYPE_VOID:
  2848.         pvar->vt = VT_EMPTY;
  2849.         break;
  2850.     default:
  2851.         _ASSERTE(!"bad constant value type!");
  2852.     }
  2853.  
  2854.     return hr;
  2855. } // HRESULT _FillVariant()
  2856.  
  2857. void MDInfo::DisplayAssembly()
  2858. {
  2859.     if (m_pAssemblyImport) 
  2860.     {
  2861.         DisplayAssemblyInfo();
  2862.         DisplayAssemblyRefs();
  2863.         DisplayFiles();
  2864.         DisplayComTypes();
  2865.         DisplayManifestResources();
  2866.         DisplayExecutionLocations();
  2867.     }
  2868. } // void MDInfo::DisplayAssembly()
  2869.  
  2870. void MDInfo::DisplayAssemblyInfo()
  2871. {
  2872.     HRESULT         hr;
  2873.     char            *rcBuf;
  2874.     mdAssembly      mda;
  2875.     const BYTE      *pbOriginator;
  2876.     ULONG           cbOriginator;
  2877.     ULONG           ulHashAlgId;
  2878.     WCHAR           szName[STRING_BUFFER_LEN];
  2879.     ASSEMBLYMETADATA MetaData;
  2880.     WCHAR           szTitle[STRING_BUFFER_LEN];
  2881.     WCHAR           szDescription[STRING_BUFFER_LEN];
  2882.     DWORD           dwFlags;
  2883.  
  2884.     hr = m_pAssemblyImport->GetAssemblyFromScope(&mda);
  2885.     if (hr == CLDB_E_RECORD_NOTFOUND)
  2886.         return;
  2887.     else if (FAILED(hr)) Error("GetAssemblyFromScope() failed.", hr);
  2888.  
  2889.     // Get the required sizes for the arrays of locales, processors etc.
  2890.     ZeroMemory(&MetaData, sizeof(ASSEMBLYMETADATA));
  2891.     hr = m_pAssemblyImport->GetAssemblyProps(mda, 
  2892.                                              NULL, NULL,    // Originator.
  2893.                                              NULL,          // Hash Algorithm.
  2894.                                              NULL, 0, NULL, // Name.
  2895.                                              &MetaData,
  2896.                                              NULL, 0, NULL, // Title.
  2897.                                              NULL, 0, NULL, // Description.
  2898.                                              NULL, 0, NULL, // DefaultAlias. (soon to be gone)
  2899.                                              NULL);         // Flags.
  2900.     if (FAILED(hr)) Error("GetAssemblyProps() failed.", hr);
  2901.  
  2902.     // Allocate space for the arrays in the ASSEMBLYMETADATA structure.
  2903.     if (MetaData.cbLocale)
  2904.         MetaData.szLocale = (WCHAR *)_alloca(sizeof(WCHAR) * MetaData.cbLocale);
  2905.     if (MetaData.ulProcessor)
  2906.         MetaData.rProcessor = (DWORD *)_alloca(sizeof(DWORD) * MetaData.ulProcessor);
  2907.     if (MetaData.ulOS)
  2908.         MetaData.rOS = (OSINFO *)_alloca(sizeof(OSINFO) * MetaData.ulOS);
  2909.     if (MetaData.cbConfiguration)
  2910.         MetaData.szConfiguration = (WCHAR *)_alloca(sizeof(WCHAR) * MetaData.cbConfiguration);
  2911.  
  2912.     hr = m_pAssemblyImport->GetAssemblyProps(mda, 
  2913.                                              (const void **)&pbOriginator, &cbOriginator,
  2914.                                              &ulHashAlgId,
  2915.                                              szName, STRING_BUFFER_LEN, NULL,
  2916.                                              &MetaData,
  2917.                                              szTitle, STRING_BUFFER_LEN, NULL,
  2918.                                              szDescription, STRING_BUFFER_LEN, NULL,
  2919.                                              NULL, 0, NULL,
  2920.                                              &dwFlags);
  2921.     if (FAILED(hr)) Error("GetAssemblyProps() failed.", hr);
  2922.     WriteLine("Assembly");
  2923.     WriteLine("-------------------------------------------------------");
  2924.     VWriteLine("\tToken: 0x%08x", mda);
  2925.     VWriteLine("\tName : %ls", szName);
  2926.     if (cbOriginator)
  2927.     {
  2928.         rcBuf = (char*)_alloca(cbOriginator * 3 + 1);
  2929.         if (rcBuf)
  2930.         {
  2931.             ULONG i;
  2932.             for (i = 0; i < cbOriginator; i++)
  2933.                 sprintf(&rcBuf[i*3], "%02x ", pbOriginator[i]);
  2934.             rcBuf[i * 3] = '\0';
  2935.         }
  2936.     }
  2937.     Write("\tOriginator Blob : ");
  2938.     WriteLine(cbOriginator ? (rcBuf ? rcBuf : "<not enough memory>") : "<null>");
  2939.     VWriteLine("\tHash Algorithm : 0x%08x", ulHashAlgId);
  2940.     DisplayASSEMBLYMETADATA(&MetaData);
  2941.     VWriteLine("\tTitle : %ls", szTitle);
  2942.     VWriteLine("\tDescription : %ls", szDescription);
  2943.  
  2944.     char sFlags[STRING_BUFFER_LEN];
  2945.     DWORD flags = dwFlags;
  2946.  
  2947.     strcpy(sFlags, "");
  2948.     ISFLAG(Af, ImplicitComTypes);
  2949.     ISFLAG(Af, ImplicitResources);
  2950.     ISFLAG(Af, SideBySideCompatible);
  2951.     ISFLAG(Af, NonSideBySideAppDomain);
  2952.     ISFLAG(Af, NonSideBySideProcess);
  2953.     ISFLAG(Af, NonSideBySideMachine);
  2954.     if (!*sFlags)
  2955.         strcpy(sFlags, "[none]");
  2956.  
  2957.     VWriteLine("\tFlags : %s (%08x)", sFlags, dwFlags);
  2958.     DisplayCustomAttributes(mda, "\t");
  2959.     DisplayPermissions(mda, "");
  2960.     WriteLine("");
  2961. }   // void MDInfo::DisplayAssemblyInfo()
  2962.  
  2963. void MDInfo::DisplayAssemblyRefs()
  2964. {
  2965.     HCORENUM        assemblyRefEnum = NULL;
  2966.     mdAssemblyRef   AssemblyRefs[ENUM_BUFFER_SIZE];
  2967.     ULONG           count;
  2968.     ULONG           totalCount = 1;
  2969.     HRESULT         hr;
  2970.  
  2971.     while (SUCCEEDED(hr = m_pAssemblyImport->EnumAssemblyRefs( &assemblyRefEnum,
  2972.                              AssemblyRefs, NumItems(AssemblyRefs), &count)) &&
  2973.             count > 0)
  2974.     {
  2975.         for (ULONG i = 0; i < count; i++, totalCount++)
  2976.         {
  2977.             VWriteLine("AssemblyRef #%d", totalCount);
  2978.             WriteLine("-------------------------------------------------------");
  2979.             DisplayAssemblyRefInfo(AssemblyRefs[i]);
  2980.             WriteLine("");
  2981.         }
  2982.     }
  2983.     m_pAssemblyImport->CloseEnum(assemblyRefEnum);
  2984. }   // void MDInfo::DisplayAssemblyRefs()
  2985.  
  2986. void MDInfo::DisplayAssemblyRefInfo(mdAssemblyRef inAssemblyRef)
  2987. {
  2988.     HRESULT         hr;
  2989.     char            *rcBuf;
  2990.     const BYTE      *pbOriginator;
  2991.     ULONG           cbOriginator;
  2992.     WCHAR           szName[STRING_BUFFER_LEN];
  2993.     ASSEMBLYMETADATA MetaData;
  2994.     const BYTE      *pbHashValue;
  2995.     ULONG           cbHashValue;
  2996.     mdExecutionLocation tkel;
  2997.     DWORD           dwFlags;
  2998.     
  2999.     VWriteLine("\tToken: 0x%08x", inAssemblyRef);
  3000.  
  3001.     // Get sizes for the arrays in the ASSEMBLYMETADATA structure.
  3002.     ZeroMemory(&MetaData, sizeof(ASSEMBLYMETADATA));
  3003.     hr = m_pAssemblyImport->GetAssemblyRefProps(inAssemblyRef,
  3004.                                              NULL, NULL,    // Originator.
  3005.                                              NULL, 0, NULL, // Name.
  3006.                                              &MetaData,
  3007.                                              NULL, NULL,    // HashValue.
  3008.                                              NULL,          // Execution Location token.
  3009.                                              NULL);         // Flags.
  3010.     if (FAILED(hr)) Error("GetAssemblyRefProps() failed.", hr);
  3011.     
  3012.     // Allocate space for the arrays in the ASSEMBLYMETADATA structure.
  3013.     if (MetaData.cbLocale)
  3014.         MetaData.szLocale = (WCHAR *)_alloca(sizeof(WCHAR) * MetaData.cbLocale);
  3015.     if (MetaData.ulProcessor)
  3016.         MetaData.rProcessor = (DWORD *)_alloca(sizeof(DWORD) * MetaData.ulProcessor);
  3017.     if (MetaData.ulOS)
  3018.         MetaData.rOS = (OSINFO *)_alloca(sizeof(OSINFO) * MetaData.ulOS);
  3019.     if (MetaData.cbConfiguration)
  3020.         MetaData.szConfiguration = (WCHAR *)_alloca(sizeof(WCHAR) * MetaData.cbConfiguration);
  3021.  
  3022.     hr = m_pAssemblyImport->GetAssemblyRefProps(inAssemblyRef,
  3023.                                              (const void **)&pbOriginator, &cbOriginator,
  3024.                                              szName, STRING_BUFFER_LEN, NULL,
  3025.                                              &MetaData,
  3026.                                              (const void **)&pbHashValue, &cbHashValue,
  3027.                                              &tkel,
  3028.                                              &dwFlags);
  3029.     if (FAILED(hr)) Error("GetAssemblyRefProps() failed.", hr);
  3030.  
  3031.     if (cbOriginator)
  3032.     {
  3033.         rcBuf = (char*)_alloca(cbOriginator * 3 + 1);
  3034.         if (rcBuf)
  3035.         {
  3036.             ULONG i;
  3037.             for (i = 0; i < cbOriginator; i++)
  3038.                 sprintf(&rcBuf[i*3], "%02x ", pbOriginator[i]);
  3039.             rcBuf[i * 3] = '\0';
  3040.         }
  3041.     }
  3042.     Write("\tOriginator Blob: ");
  3043.     WriteLine(cbOriginator ? (rcBuf ? rcBuf : "<not enough memory>") : "<null>");
  3044.     VWriteLine("\tName: %ls", szName);
  3045.     DisplayASSEMBLYMETADATA(&MetaData);
  3046.     if (cbHashValue)
  3047.     {
  3048.         rcBuf = (char*)_alloca(cbHashValue * 3 + 1);
  3049.         if (rcBuf)
  3050.         {
  3051.             ULONG i;
  3052.             for (i = 0; i < cbHashValue; i++)
  3053.                 sprintf(&rcBuf[i*3], "%02x ", pbHashValue[i]);
  3054.             rcBuf[i * 3] = '\0';
  3055.         }
  3056.     }
  3057.     Write("\tHashValue Blob: ");
  3058.     WriteLine(cbHashValue ? (rcBuf ? rcBuf : "<not enough memory>") : "<null>");
  3059.     VWriteLine("\tExecutionLocation token: 0x%08x", tkel);
  3060.  
  3061.     char sFlags[STRING_BUFFER_LEN];
  3062.     DWORD flags = dwFlags;
  3063.  
  3064.     strcpy(sFlags, "");
  3065.     ISFLAG(Ar, FullOriginator);     
  3066.     if (!*sFlags)
  3067.         strcpy(sFlags, "[none]");
  3068.  
  3069.     VWriteLine("\tFlags: %s (%08x)", sFlags, dwFlags);
  3070.     DisplayCustomAttributes(inAssemblyRef, "\t");
  3071.     WriteLine("");
  3072. }   // void MDInfo::DisplayAssemblyRefInfo()
  3073.  
  3074. void MDInfo::DisplayFiles()
  3075. {
  3076.     HCORENUM        fileEnum = NULL;
  3077.     mdFile          Files[ENUM_BUFFER_SIZE];
  3078.     ULONG           count;
  3079.     ULONG           totalCount = 1;
  3080.     HRESULT         hr;
  3081.  
  3082.     while (SUCCEEDED(hr = m_pAssemblyImport->EnumFiles( &fileEnum,
  3083.                              Files, NumItems(Files), &count)) &&
  3084.             count > 0)
  3085.     {
  3086.         for (ULONG i = 0; i < count; i++, totalCount++)
  3087.         {
  3088.             VWriteLine("File #%d", totalCount);
  3089.             WriteLine("-------------------------------------------------------");
  3090.             DisplayFileInfo(Files[i]);
  3091.             WriteLine("");
  3092.         }
  3093.     }
  3094.     m_pAssemblyImport->CloseEnum(fileEnum);
  3095. }   // void MDInfo::DisplayFiles()
  3096.  
  3097. void MDInfo::DisplayFileInfo(mdFile inFile)
  3098. {
  3099.     HRESULT         hr;
  3100.     char            *rcBuf;
  3101.     WCHAR           szName[STRING_BUFFER_LEN];
  3102.     const BYTE      *pbHashValue;
  3103.     ULONG           cbHashValue;
  3104.     DWORD           dwFlags;
  3105.  
  3106.     VWriteLine("\tToken: 0x%08x", inFile);
  3107.  
  3108.     hr = m_pAssemblyImport->GetFileProps(inFile,
  3109.                                          szName, STRING_BUFFER_LEN, NULL,
  3110.                                          (const void **)&pbHashValue, &cbHashValue,
  3111.                                          &dwFlags);
  3112.     if (FAILED(hr)) Error("GetFileProps() failed.", hr);
  3113.     VWriteLine("\tName : %ls", szName);
  3114.     if (cbHashValue)
  3115.     {
  3116.         rcBuf = (char*)_alloca(cbHashValue * 3 + 1);
  3117.         if (rcBuf)
  3118.         {
  3119.             ULONG i;
  3120.             for (i = 0; i < cbHashValue; i++)
  3121.                 sprintf(&rcBuf[i*3], "%02x ", pbHashValue[i]);
  3122.             rcBuf[i * 3] = '\0';
  3123.         }
  3124.     }
  3125.     Write("\tHashValue Blob : ");
  3126.     WriteLine(cbHashValue ? (rcBuf ? rcBuf : "<not enough memory>") : "<null>");
  3127.  
  3128.     char sFlags[STRING_BUFFER_LEN];
  3129.     DWORD flags = dwFlags;
  3130.  
  3131.     strcpy(sFlags, "");
  3132.     ISFLAG(Ff, Writeable);      
  3133.     if (!*sFlags)
  3134.         strcpy(sFlags, "[none]");
  3135.  
  3136.     VWriteLine("\tFlags : %s (%08x)", sFlags, dwFlags);
  3137.     DisplayCustomAttributes(inFile, "\t");
  3138.     WriteLine("");
  3139.  
  3140. }   // MDInfo::DisplayFileInfo()
  3141.  
  3142. void MDInfo::DisplayComTypes()
  3143. {
  3144.     HCORENUM        comTypeEnum = NULL;
  3145.     mdComType       ComTypes[ENUM_BUFFER_SIZE];
  3146.     ULONG           count;
  3147.     ULONG           totalCount = 1;
  3148.     HRESULT         hr;
  3149.  
  3150.     while (SUCCEEDED(hr = m_pAssemblyImport->EnumComTypes( &comTypeEnum,
  3151.                              ComTypes, NumItems(ComTypes), &count)) &&
  3152.             count > 0)
  3153.     {
  3154.         for (ULONG i = 0; i < count; i++, totalCount++)
  3155.         {
  3156.             VWriteLine("ComType #%d", totalCount);
  3157.             WriteLine("-------------------------------------------------------");
  3158.             DisplayComTypeInfo(ComTypes[i]);
  3159.             WriteLine("");
  3160.         }
  3161.     }
  3162.     m_pAssemblyImport->CloseEnum(comTypeEnum);
  3163. }   // void MDInfo::DisplayComTypes()
  3164.  
  3165. void MDInfo::DisplayComTypeInfo(mdComType inComType)
  3166. {
  3167.     HRESULT         hr;
  3168.     WCHAR           szName[STRING_BUFFER_LEN];
  3169.     WCHAR           szDescription[STRING_BUFFER_LEN];
  3170.     mdToken         tkImplementation;
  3171.     mdTypeDef       tkTypeDef;
  3172.     mdExecutionLocation tkExecutionLocation;
  3173.     DWORD           dwFlags;
  3174.     char            sFlags[STRING_BUFFER_LEN];
  3175.  
  3176.     VWriteLine("\tToken: 0x%08x", inComType);
  3177.  
  3178.     hr = m_pAssemblyImport->GetComTypeProps(inComType,
  3179.                                             szName, STRING_BUFFER_LEN, NULL,
  3180.                                             szDescription, STRING_BUFFER_LEN, NULL,
  3181.                                             &tkImplementation,
  3182.                                             &tkTypeDef,
  3183.                                             &tkExecutionLocation,
  3184.                                             &dwFlags);
  3185.     if (FAILED(hr)) Error("GetComTypeProps() failed.", hr);
  3186.     VWriteLine("\tName: %ls", szName);
  3187.     VWriteLine("\tDescription token: %ls", szDescription);
  3188.     VWriteLine("\tImplementation token: 0x%08x", tkImplementation);
  3189.     VWriteLine("\tTypeDef token: 0x%08x", tkTypeDef);
  3190.     VWriteLine("\tExecutionLocation token: 0x%08x", tkExecutionLocation);
  3191.     VWriteLine("\tFlags     : %s (%08x)",ClassFlags(dwFlags, sFlags), dwFlags);
  3192.     DisplayCustomAttributes(inComType, "\t");
  3193.     WriteLine("");
  3194. }   // void MDInfo::DisplayComTypeInfo()
  3195.  
  3196. void MDInfo::DisplayManifestResources()
  3197. {
  3198.     HCORENUM        manifestResourceEnum = NULL;
  3199.     mdManifestResource ManifestResources[ENUM_BUFFER_SIZE];
  3200.     ULONG           count;
  3201.     ULONG           totalCount = 1;
  3202.     HRESULT         hr;
  3203.  
  3204.     while (SUCCEEDED(hr = m_pAssemblyImport->EnumManifestResources( &manifestResourceEnum,
  3205.                              ManifestResources, NumItems(ManifestResources), &count)) &&
  3206.             count > 0)
  3207.     {
  3208.         for (ULONG i = 0; i < count; i++, totalCount++)
  3209.         {
  3210.             VWriteLine("ManifestResource #%d", totalCount);
  3211.             WriteLine("-------------------------------------------------------");
  3212.             DisplayManifestResourceInfo(ManifestResources[i]);
  3213.             WriteLine("");
  3214.         }
  3215.     }
  3216.     m_pAssemblyImport->CloseEnum(manifestResourceEnum);
  3217. }   // void MDInfo::DisplayManifestResources()
  3218.  
  3219. void MDInfo::DisplayManifestResourceInfo(mdManifestResource inManifestResource)
  3220. {
  3221.     HRESULT         hr;
  3222.     WCHAR           szName[STRING_BUFFER_LEN];
  3223.     WCHAR           szDescription[STRING_BUFFER_LEN];
  3224.     mdToken         tkImplementation;
  3225.     DWORD           dwOffset;
  3226.     WCHAR           szMIMEType[STRING_BUFFER_LEN];
  3227.     WCHAR           szLocale[STRING_BUFFER_LEN];
  3228.     DWORD           dwFlags;
  3229.  
  3230.     VWriteLine("\tToken: 0x%08x", inManifestResource);
  3231.  
  3232.     hr = m_pAssemblyImport->GetManifestResourceProps(inManifestResource,
  3233.                                                      szName, STRING_BUFFER_LEN, NULL,
  3234.                                                      szDescription, STRING_BUFFER_LEN, NULL,
  3235.                                                      &tkImplementation,
  3236.                                                      &dwOffset,
  3237.                                                      szMIMEType, STRING_BUFFER_LEN, NULL,
  3238.                                                      szLocale, STRING_BUFFER_LEN, NULL,
  3239.                                                      &dwFlags);
  3240.     if (FAILED(hr)) Error("GetManifestResourceProps() failed.", hr);
  3241.     VWriteLine("Name: %ls", szName);
  3242.     VWriteLine("Description: %ls", szDescription);
  3243.     VWriteLine("Implementation token: 0x%08x", tkImplementation);
  3244.     VWriteLine("Offset: 0x%08x", dwOffset);
  3245.     VWriteLine("MIMEType: %ls", szMIMEType);
  3246.     VWriteLine("Locale: %ls", szLocale);
  3247.  
  3248.     char sFlags[STRING_BUFFER_LEN];
  3249.     DWORD flags = dwFlags;
  3250.  
  3251.     strcpy(sFlags, "");
  3252.     ISFLAG(Mr, Public);     
  3253.     ISFLAG(Mr, Private);            
  3254.     if (!*sFlags)
  3255.         strcpy(sFlags, "[none]");
  3256.  
  3257.     VWriteLine("\tFlags: %s (%08x)", sFlags, dwFlags);
  3258.     DisplayCustomAttributes(inManifestResource, "\t");
  3259.     WriteLine("");
  3260. }   // void MDInfo::DisplayManifestResourceInfo()
  3261.  
  3262. void MDInfo::DisplayExecutionLocations()
  3263. {
  3264.     HCORENUM        executionLocationEnum = NULL;
  3265.     mdExecutionLocation ExecutionLocations[ENUM_BUFFER_SIZE];
  3266.     ULONG           count;
  3267.     ULONG           totalCount = 1;
  3268.     HRESULT         hr;
  3269.  
  3270.     while (SUCCEEDED(hr = m_pAssemblyImport->EnumExecutionLocations( &executionLocationEnum,
  3271.                              ExecutionLocations, NumItems(ExecutionLocations), &count)) &&
  3272.             count > 0)
  3273.     {
  3274.         for (ULONG i = 0; i < count; i++, totalCount++)
  3275.         {
  3276.             VWriteLine("ExecutionLocation #%d", totalCount);
  3277.             WriteLine("-------------------------------------------------------");
  3278.             DisplayExecutionLocationInfo(ExecutionLocations[i]);
  3279.             WriteLine("");
  3280.         }
  3281.     }
  3282.     m_pAssemblyImport->CloseEnum(executionLocationEnum);
  3283. }   // void MDInfo::DisplayExecutionLocations()
  3284.  
  3285. void MDInfo::DisplayExecutionLocationInfo(mdExecutionLocation inExecutionLocation)
  3286. {
  3287.     HRESULT         hr;
  3288.     WCHAR           szName[STRING_BUFFER_LEN];
  3289.     WCHAR           szDescription[STRING_BUFFER_LEN];
  3290.     WCHAR           szLocation[STRING_BUFFER_LEN];
  3291.     DWORD           dwFlags;
  3292.  
  3293.     VWriteLine("\tToken: 0x%08x", inExecutionLocation);
  3294.  
  3295.     hr = m_pAssemblyImport->GetExecutionLocationProps(inExecutionLocation,
  3296.                                                       szName, STRING_BUFFER_LEN, NULL,
  3297.                                                       szDescription, STRING_BUFFER_LEN, NULL,
  3298.                                                       szLocation, STRING_BUFFER_LEN, NULL,
  3299.                                                       &dwFlags);
  3300.     if (FAILED(hr)) Error("GetExecutionLocationProps() failed.", hr);
  3301.     VWriteLine("\tName: %ls", szName);
  3302.     VWriteLine("\tDescription: %ls", szDescription);
  3303.     VWriteLine("\tLocation: %ls", szLocation);
  3304.     VWriteLine("\tFlags: 0x%08x", dwFlags);
  3305.     DisplayCustomAttributes(inExecutionLocation, "\t");
  3306.     WriteLine("");
  3307. }   // void MDInfo::DisplayExecutionLocationInfo()
  3308.  
  3309. void MDInfo::DisplayASSEMBLYMETADATA(ASSEMBLYMETADATA *pMetaData)
  3310. {
  3311.     ULONG           i;
  3312.  
  3313.     VWriteLine("\tMajor Version: 0x%08x", pMetaData->usMajorVersion);
  3314.     VWriteLine("\tMinor Version: 0x%08x", pMetaData->usMinorVersion);
  3315.     VWriteLine("\tRevision Number: 0x%08x", pMetaData->usRevisionNumber);
  3316.     VWriteLine("\tBuild Number: 0x%08x", pMetaData->usBuildNumber);
  3317.     VWriteLine("\tLocale: %ls", pMetaData->cbLocale ? pMetaData->szLocale : L"<null>");
  3318.     for (i = 0; i < pMetaData->ulProcessor; i++)
  3319.         VWriteLine("\tProcessor #%ld: 0x%08x", i+1, pMetaData->rProcessor[i]);
  3320.     for (i = 0; i < pMetaData->ulOS; i++)
  3321.     {
  3322.         VWriteLine("\tOS #%ld:", i+1);
  3323.         VWriteLine("\t\tOS Platform ID: 0x%08x", pMetaData->rOS[i].dwOSPlatformId);
  3324.         VWriteLine("\t\tOS Major Version: 0x%08x", pMetaData->rOS[i].dwOSMajorVersion);
  3325.         VWriteLine("\t\tOS Minor Version: 0x%08x", pMetaData->rOS[i].dwOSMinorVersion);
  3326.     }
  3327.     VWriteLine("\tConfiguration: %ls", pMetaData->cbConfiguration ? pMetaData->szConfiguration : L"<null>");
  3328. }   // void MDInfo::DisplayASSEMBLYMETADATA()
  3329.  
  3330. void MDInfo::DisplayUserStrings()
  3331. {
  3332.     HCORENUM    stringEnum = NULL;      // string enumerator.
  3333.     mdString    Strings[ENUM_BUFFER_SIZE]; // String tokens from enumerator.
  3334.     CQuickArray<WCHAR> rUserString;     // Buffer to receive string.
  3335.     WCHAR       *szUserString;          // Working pointer into buffer.
  3336.     ULONG       chUserString;           // Size of user string.
  3337.     CQuickArray<char> rcBuf;            // Buffer to hold the BLOB version of the string.
  3338.     char        *szBuf;                 // Working pointer into buffer.
  3339.     ULONG       chBuf;                  // Saved size of the user string.
  3340.     ULONG       count;                  // Items returned from enumerator.
  3341.     ULONG       totalCount = 1;         // Running count of strings.
  3342.     bool        bUnprint = false;       // Is an unprintable character found?
  3343.     HRESULT     hr;                     // A result.
  3344.  
  3345.     while (SUCCEEDED(hr = m_pImport->EnumUserStrings( &stringEnum,
  3346.                              Strings, NumItems(Strings), &count)) &&
  3347.             count > 0)
  3348.     {
  3349.         if (totalCount == 1)
  3350.         {   // If only one, it is the NULL string, so don't print it.
  3351.             WriteLine("User Strings");
  3352.             WriteLine("-------------------------------------------------------");
  3353.         }
  3354.         for (ULONG i = 0; i < count; i++, totalCount++)
  3355.         {
  3356.             do { // Try to get the string into the existing buffer.
  3357.                 hr = m_pImport->GetUserString( Strings[i], rUserString.Ptr(),rUserString.MaxSize(), &chUserString);
  3358.                 if (hr == CLDB_S_TRUNCATION)
  3359.                 {   // Buffer wasn't big enough, try to enlarge it.
  3360.                     if (FAILED(rUserString.ReSize(chUserString)))
  3361.                         Error("malloc failed.", E_OUTOFMEMORY);
  3362.                     continue;
  3363.                 }
  3364.             } while (0);
  3365.             if (FAILED(hr)) Error("GetUserString failed.", hr);
  3366.  
  3367.             szUserString = rUserString.Ptr();
  3368.             chBuf = chUserString;
  3369.  
  3370.             VWrite("%08x : (%2d) L\"", Strings[i], chUserString);
  3371.             while (chUserString)
  3372.             {   
  3373.                 switch (*szUserString)
  3374.                 {
  3375.                 case 0:
  3376.                     Write("\\0"); break;
  3377.                 case L'\r':
  3378.                     Write("\\r"); break;
  3379.                 case L'\n':
  3380.                     Write("\\n"); break;
  3381.                 case L'\t':
  3382.                     Write("\\t"); break;
  3383.                 default:
  3384.                     if (iswprint(*szUserString))
  3385.                         VWrite("%lc", *szUserString);
  3386.                     else 
  3387.                     {
  3388.                         bUnprint = true;
  3389.                         Write(".");
  3390.                     }
  3391.                     break;
  3392.                 }
  3393.                 ++szUserString;
  3394.                 --chUserString;
  3395.             }
  3396.             WriteLine("\"");
  3397.  
  3398.             // Print the user string as a blob if an unprintable character is found.
  3399.             if (bUnprint)
  3400.             {
  3401.                 bUnprint = false;
  3402.                 szUserString = rUserString.Ptr();
  3403.                 rcBuf.ReSize(chBuf * 5 + 1);
  3404.                 szBuf = rcBuf.Ptr();
  3405.                 ULONG j;
  3406.                 for (j = 0; j < chBuf; j++)
  3407.                     sprintf (&szBuf[j*5], "%04x ", szUserString[j]);
  3408.                 szBuf[j*5] = '\0';
  3409.                 WriteLine("\t\tUser string has unprintables, hex format below:");
  3410.                 VWriteLine("\t\t%s", szBuf);
  3411.             }
  3412.         }
  3413.     }
  3414.     if (stringEnum)
  3415.         m_pImport->CloseEnum(stringEnum);
  3416. }   // void MDInfo::DisplayUserStrings()
  3417.  
  3418. void MDInfo::DisplayUnsatInfo()
  3419. {
  3420.     HRESULT     hr = S_OK;
  3421.  
  3422.     HCORENUM henum = 0;
  3423.     mdToken  tk;
  3424.     ULONG cMethods;
  3425.  
  3426.     Write("\nUnresolved Externals\n");
  3427.     Write("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
  3428.  
  3429.     while ( (hr = m_pImport->EnumUnresolvedMethods(
  3430.         &henum, 
  3431.         &tk, 
  3432.         1, 
  3433.         &cMethods)) == S_OK && cMethods )
  3434.     {
  3435.         if ( TypeFromToken(tk) == mdtMethodDef )
  3436.         {
  3437.             // a method definition without implementation
  3438.             DisplayMethodInfo( tk );
  3439.         }
  3440.         else if ( TypeFromToken(tk) == mdtMemberRef )
  3441.         {
  3442.             // an unresolved MemberRef to a global function 
  3443.             DisplayMemberRefInfo( tk, "" );
  3444.         }
  3445.         else
  3446.         { 
  3447.             _ASSERTE(!"Unknown token kind!");
  3448.         }
  3449.     }
  3450.     m_pImport->CloseEnum(henum);
  3451. } // void MDInfo::DisplayUnsatInfo()
  3452.  
  3453. /***********************************************************************/
  3454. static WCHAR* asStringW(CQuickBytes *out) 
  3455. {
  3456.     unsigned oldSize = out->Size();
  3457.     if (FAILED(out->ReSize(oldSize + 1)))
  3458.         return 0;
  3459.     WCHAR * cur = (WCHAR *) ((BYTE *) out->Ptr() + oldSize);
  3460.     *cur = 0;    
  3461.     return((WCHAR*) out->Ptr()); 
  3462. } // static WCHAR* asStringW()
  3463.  
  3464. static HRESULT appendStrW(CQuickBytes *out, const WCHAR* str) 
  3465. {
  3466.     unsigned len = (unsigned)(wcslen(str) * sizeof(WCHAR)); 
  3467.     unsigned oldSize = out->Size();
  3468.     if (FAILED(out->ReSize(oldSize + len)))
  3469.         return E_OUTOFMEMORY;
  3470.     WCHAR * cur = (WCHAR *) ((BYTE *) out->Ptr() + oldSize);
  3471.     memcpy(cur, str, len);    
  3472.         // Note no trailing null!    
  3473.     return S_OK;
  3474. } // static HRESULT appendStrW()
  3475.  
  3476. static HRESULT appendStrNumW(CQuickBytes *out, int num) 
  3477. {
  3478.     WCHAR buff[16];    
  3479.     swprintf(buff, L"%d", num);    
  3480.     return appendStrW(out, buff);    
  3481. } // static HRESULT appendStrNumW()
  3482.  
  3483. //*****************************************************************************
  3484. //*****************************************************************************
  3485. const unsigned int iRidMax            = 63;
  3486. const unsigned int iCodedToken        = 64;    // base of coded tokens.
  3487. const unsigned int iCodedTokenMax    = 95;
  3488. const unsigned int iSHORT            = 96;    // fixed types.
  3489. const unsigned int iUSHORT            = 97;
  3490. const unsigned int iLONG            = 98;
  3491. const unsigned int iULONG            = 99;
  3492. const unsigned int iBYTE            = 100;
  3493. const unsigned int iSTRING            = 101;    // pool types.
  3494. const unsigned int iGUID            = 102;
  3495. const unsigned int iBLOB            = 103;
  3496.  
  3497. inline int IsRidType(ULONG ix) { return ix <= iRidMax; }
  3498. inline int IsCodedTokenType(ULONG ix) { return (ix >= iCodedToken) && (ix <= iCodedTokenMax); }
  3499. inline int IsRidOrToken(ULONG ix) { return ix <= iCodedTokenMax; }
  3500. inline int IsHeapType(ULONG ix) { return ix >= iSTRING; }
  3501. inline int IsFixedType(ULONG ix) { return (ix < iSTRING) && (ix > iCodedTokenMax); }
  3502.  
  3503. //*****************************************************************************
  3504. // pretty prints 'type' to the buffer 'out' returns a poitner to the next type, 
  3505. // or 0 on a format failure 
  3506.  
  3507. static PCCOR_SIGNATURE PrettyPrintType(
  3508.     PCCOR_SIGNATURE typePtr,            // type to convert,     
  3509.     CQuickBytes *out,                    // where to put the pretty printed string    
  3510.     IMetaDataImport *pIMDI)                // ptr to IMDInternal class with ComSig
  3511. {
  3512.     mdToken        tk;    
  3513.     const WCHAR    *str;    
  3514.     bool        isValueArray;
  3515.     HRESULT        hr;
  3516.  
  3517.     switch(*typePtr++) 
  3518.     {    
  3519.         case ELEMENT_TYPE_VOID            :    
  3520.             str = L"void"; goto APPEND;    
  3521.         case ELEMENT_TYPE_BOOLEAN        :    
  3522.             str = L"bool"; goto APPEND;    
  3523.         case ELEMENT_TYPE_CHAR            :    
  3524.             str = L"wchar"; goto APPEND; 
  3525.         case ELEMENT_TYPE_I1            :    
  3526.             str = L"int8"; goto APPEND;    
  3527.         case ELEMENT_TYPE_U1            :    
  3528.             str = L"unsigned int8"; goto APPEND; 
  3529.         case ELEMENT_TYPE_I2            :    
  3530.             str = L"int16"; goto APPEND; 
  3531.         case ELEMENT_TYPE_U2            :    
  3532.             str = L"unsigned int16"; goto APPEND;    
  3533.         case ELEMENT_TYPE_I4            :    
  3534.             str = L"int32"; goto APPEND; 
  3535.         case ELEMENT_TYPE_U4            :    
  3536.             str = L"unsigned int32"; goto APPEND;    
  3537.         case ELEMENT_TYPE_I8            :    
  3538.             str = L"int64"; goto APPEND; 
  3539.         case ELEMENT_TYPE_U8            :    
  3540.             str = L"unsigned int64"; goto APPEND;    
  3541.         case ELEMENT_TYPE_R4            :    
  3542.             str = L"float32"; goto APPEND;    
  3543.         case ELEMENT_TYPE_R8            :    
  3544.             str = L"float64"; goto APPEND;    
  3545.         case ELEMENT_TYPE_U             :    
  3546.             str = L"unsigned int"; goto APPEND;     
  3547.         case ELEMENT_TYPE_I             :    
  3548.             str = L"int"; goto APPEND;     
  3549.         case ELEMENT_TYPE_R             :    
  3550.             str = L"float"; goto APPEND;  
  3551.         case ELEMENT_TYPE_OBJECT        :    
  3552.             str = L"class System.Object"; goto APPEND;     
  3553.         case ELEMENT_TYPE_STRING        :    
  3554.             str = L"class System.String"; goto APPEND;     
  3555.         case ELEMENT_TYPE_TYPEDBYREF        :    
  3556.             str = L"refany"; goto APPEND;    
  3557.         APPEND: 
  3558.             appendStrW(out, str);    
  3559.             break;    
  3560.  
  3561.         case ELEMENT_TYPE_VALUECLASS    :    
  3562.             str = L"value class ";    
  3563.             goto DO_CLASS;    
  3564.         case ELEMENT_TYPE_CLASS         :    
  3565.             str = L"class "; 
  3566.             goto DO_CLASS;    
  3567.  
  3568.         DO_CLASS:
  3569.             typePtr += CorSigUncompressToken(typePtr, &tk); 
  3570.             appendStrW(out, str);    
  3571.             str = L"<UNKNOWN>";    
  3572.  
  3573.             // Example: consume the <Rid>
  3574.             if (!(TypeFromToken(tk) == mdtTypeRef))
  3575.             {
  3576.                 _ASSERTE(TypeFromToken(tk) == mdtTypeDef);
  3577.                 WCHAR rcname[512];
  3578.                 rcname[0] = 0;
  3579.                 str = rcname;
  3580.  
  3581.                 hr = pIMDI->GetTypeDefProps(tk, 
  3582.                         rcname, NumItems(rcname), 0,
  3583.                         0, 0, 0);
  3584.             }
  3585.             appendStrW(out, str);    
  3586.             break;    
  3587.  
  3588.         case ELEMENT_TYPE_SZARRAY     :     
  3589.             typePtr = PrettyPrintType(typePtr, out, pIMDI); 
  3590.             appendStrW(out, L"[]");
  3591.             break;
  3592.         case ELEMENT_TYPE_VALUEARRAY    :    
  3593.             isValueArray = true; goto DO_ARRAY;
  3594.         DO_ARRAY:
  3595.             {    
  3596.             typePtr = PrettyPrintType(typePtr, out, pIMDI); 
  3597.             unsigned bound = CorSigUncompressData(typePtr); 
  3598.  
  3599.             if (isValueArray)
  3600.                 appendStrW(out, L" value");
  3601.                 
  3602.             WCHAR buff[32];    
  3603.             swprintf(buff, L"[%d]", bound);    
  3604.             appendStrW(out, buff);    
  3605.             } break;    
  3606.         case ELEMENT_TYPE_GENERICARRAY        :
  3607.             typePtr = PrettyPrintType(typePtr, out, pIMDI); 
  3608.             appendStrW(out, L"[?]");
  3609.             break;
  3610.         case ELEMENT_TYPE_ARRAY        :    
  3611.             {    
  3612.             typePtr = PrettyPrintType(typePtr, out, pIMDI); 
  3613.             unsigned rank = CorSigUncompressData(typePtr);    
  3614.                 // TODO what is the syntax for the rank 0 case? 
  3615.             if (rank == 0) 
  3616.             {
  3617.                 appendStrW(out, L"[??]");
  3618.             }
  3619.             else 
  3620.             {
  3621.                 _ASSERTE(rank != 0);    
  3622.                 int* lowerBounds = (int*) _alloca(sizeof(int)*2*rank);    
  3623.                 int* sizes         = &lowerBounds[rank];    
  3624.                 memset(lowerBounds, 0, sizeof(int)*2*rank); 
  3625.                 
  3626.                 unsigned numSizes = CorSigUncompressData(typePtr);    
  3627.                 _ASSERTE(numSizes <= rank); 
  3628.                 for(unsigned i =0; i < numSizes; i++)    
  3629.                     sizes[i] = CorSigUncompressData(typePtr);    
  3630.                 
  3631.                 unsigned numLowBounds = CorSigUncompressData(typePtr);    
  3632.                 _ASSERTE(numLowBounds <= rank); 
  3633.                 for(i = 0; i < numLowBounds; i++)    
  3634.                     lowerBounds[i] = CorSigUncompressData(typePtr); 
  3635.                 
  3636.                 appendStrW(out, L"[");    
  3637.                 for(i = 0; i < rank; i++)    
  3638.                 {    
  3639.                     if (sizes[i] != 0 && lowerBounds[i] != 0)    
  3640.                     {    
  3641.                         if (lowerBounds[i] == 0)    
  3642.                             appendStrNumW(out, sizes[i]);    
  3643.                         else    
  3644.                         {    
  3645.                             appendStrNumW(out, lowerBounds[i]);    
  3646.                             appendStrW(out, L"...");    
  3647.                             if (sizes[i] != 0)    
  3648.                                 appendStrNumW(out, lowerBounds[i] + sizes[i] + 1);    
  3649.                         }    
  3650.                     }    
  3651.                     if (i < rank-1) 
  3652.                         appendStrW(out, L",");    
  3653.                 }    
  3654.                 appendStrW(out, L"]");  
  3655.             }
  3656.             } break;    
  3657.  
  3658.         case ELEMENT_TYPE_VAR        :   
  3659.             appendStrW(out, L"!");  
  3660.             appendStrNumW(out, CorSigUncompressData(typePtr));
  3661.             break;
  3662.             // Modifiers or depedant types  
  3663.         case ELEMENT_TYPE_PINNED    :
  3664.             str = L" pinned"; goto MODIFIER;    
  3665.         case ELEMENT_TYPE_COPYCTOR           :   
  3666.             str = L"%"; goto MODIFIER;   
  3667.         case ELEMENT_TYPE_PTR           :   
  3668.             str = L"*"; goto MODIFIER;   
  3669.         case ELEMENT_TYPE_BYREF         :   
  3670.             str = L"&"; goto MODIFIER;   
  3671.         MODIFIER:
  3672.             typePtr = PrettyPrintType(typePtr, out, pIMDI); 
  3673.             appendStrW(out, str);    
  3674.             break;    
  3675.  
  3676.         default:    
  3677.         case ELEMENT_TYPE_SENTINEL        :    
  3678.         case ELEMENT_TYPE_END            :    
  3679.             _ASSERTE(!"Unknown Type");    
  3680.             return(typePtr);    
  3681.             break;    
  3682.     }    
  3683.     return(typePtr);    
  3684. } // static PCCOR_SIGNATURE PrettyPrintType()
  3685.  
  3686. //*****************************************************************************
  3687. // Converts a com signature to a text signature.
  3688. //
  3689. // Note that this function DOES NULL terminate the result signature string.
  3690. //*****************************************************************************
  3691. LPCWSTR PrettyPrintSig(
  3692.     PCCOR_SIGNATURE typePtr,            // type to convert,     
  3693.     unsigned    typeLen,                // length of type
  3694.     const WCHAR    *name,                    // can be "", the name of the method for this sig    
  3695.     CQuickBytes *out,                    // where to put the pretty printed string    
  3696.     IMetaDataImport *pIMDI)             // Import api to use.
  3697. {
  3698.     out->ReSize(0); 
  3699.     unsigned numArgs;    
  3700.     PCCOR_SIGNATURE typeEnd = typePtr + typeLen;
  3701.  
  3702.     if (name != 0)                        // 0 means a local var sig    
  3703.     {
  3704.             // get the calling convention out    
  3705.         unsigned callConv = CorSigUncompressData(typePtr);    
  3706.  
  3707.         if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD))
  3708.         {
  3709.             PrettyPrintType(typePtr, out, pIMDI);    
  3710.             if (name != 0 && *name != 0)    
  3711.             {    
  3712.                 appendStrW(out, L" ");    
  3713.                 appendStrW(out, name);    
  3714.             }    
  3715.             return(asStringW(out));    
  3716.         }
  3717.  
  3718.         if (callConv & IMAGE_CEE_CS_CALLCONV_HASTHIS)    
  3719.             appendStrW(out, L"instance ");    
  3720.  
  3721.         static WCHAR* callConvNames[8] = 
  3722.         {    
  3723.             L"", 
  3724.             L"unmanaged cdecl ", 
  3725.             L"unmanaged stdcall ",    
  3726.             L"unmanaged thiscall ",    
  3727.             L"unmanaged fastcall ",    
  3728.             L"vararg ",     
  3729.             L"<error> "     
  3730.             L"<error> "     
  3731.         };    
  3732.         appendStrW(out, callConvNames[callConv & 7]);    
  3733.  
  3734.         numArgs = CorSigUncompressData(typePtr);    
  3735.             // do return type    
  3736.         typePtr = PrettyPrintType(typePtr, out, pIMDI); 
  3737.  
  3738.     }
  3739.     else    
  3740.         numArgs = CorSigUncompressData(typePtr);    
  3741.  
  3742.     if (name != 0 && *name != 0)    
  3743.     {    
  3744.         appendStrW(out, L" ");    
  3745.         appendStrW(out, name);    
  3746.     }    
  3747.     appendStrW(out, L"(");    
  3748.  
  3749.     bool needComma = false;
  3750.     while(typePtr < typeEnd) 
  3751.     {
  3752.         if (*typePtr == ELEMENT_TYPE_SENTINEL) 
  3753.         {
  3754.             if (needComma)
  3755.                 appendStrW(out, L",");    
  3756.             appendStrW(out, L"...");      
  3757.             typePtr++;
  3758.         }
  3759.         else 
  3760.         {
  3761.             if (numArgs <= 0)
  3762.                 break;
  3763.             if (needComma)
  3764.                 appendStrW(out, L",");    
  3765.             typePtr = PrettyPrintType(typePtr, out, pIMDI); 
  3766.             --numArgs;    
  3767.         }
  3768.         needComma = true;
  3769.     }
  3770.     appendStrW(out, L")");    
  3771.     return (asStringW(out));    
  3772. } // LPCWSTR PrettyPrintSig()
  3773.  
  3774. //*******************************************************************************
  3775. // This code is used for debugging purposes only.  This will just print out the
  3776. // entire database.
  3777. //*******************************************************************************
  3778. const char *MDInfo::DumpRawNameOfType(ULONG iType)
  3779. {
  3780.     if (iType <= iRidMax)
  3781.     {
  3782.         const char *pNameTable;
  3783.         m_pTables->GetTableInfo(iType, 0,0,0,0, &pNameTable);
  3784.         return pNameTable;
  3785.     }
  3786.     else
  3787.     // Is the field a coded token?
  3788.     if (iType <= iCodedTokenMax)
  3789.     {
  3790.         int iCdTkn = iType - iCodedToken;
  3791.         const char *pNameCdTkn;
  3792.         m_pTables->GetCodedTokenInfo(iCdTkn, 0,0, &pNameCdTkn);
  3793.         return pNameCdTkn;
  3794.     }
  3795.  
  3796.     // Fixed type.
  3797.     switch (iType)
  3798.     {
  3799.     case iBYTE:
  3800.         return "BYTE";
  3801.     case iSHORT:
  3802.         return "short";
  3803.     case iUSHORT:
  3804.         return "USHORT";
  3805.     case iLONG:
  3806.         return "long";
  3807.     case iULONG:
  3808.         return "ULONG";
  3809.     case iSTRING:
  3810.         return "string";
  3811.     case iGUID:
  3812.         return "GUID";
  3813.     case iBLOB:
  3814.         return "blob";
  3815.     }
  3816.     // default:
  3817.     static char buf[30];
  3818.     sprintf(buf, "unknown type 0x%02x", iType);
  3819.     return buf;
  3820. } // const char *MDInfo::DumpRawNameOfType()
  3821.  
  3822. void MDInfo::DumpRawCol(ULONG ixTbl, ULONG ixCol, ULONG rid, bool bStats)
  3823. {
  3824.     ULONG       ulType;                 // Type of a column.
  3825.     ULONG       ulVal;                  // Value of a column.
  3826.     LPCUTF8     pString;                // Pointer to a string.
  3827.     const void  *pBlob;                 // Pointer to a blob.
  3828.     ULONG       cb;                     // Size of something.
  3829.  
  3830.     m_pTables->GetColumn(ixTbl, ixCol, rid, &ulVal);
  3831.     m_pTables->GetColumnInfo(ixTbl, ixCol, 0, 0, &ulType, 0);
  3832.  
  3833.     if (ulType <= iRidMax)
  3834.     {
  3835.         const char *pNameTable;
  3836.         m_pTables->GetTableInfo(ulType, 0,0,0,0, &pNameTable);
  3837.         VWrite("%s[%x]", pNameTable, ulVal);
  3838.     }
  3839.     else
  3840.     // Is the field a coded token?
  3841.     if (ulType <= iCodedTokenMax)
  3842.     {
  3843.         int iCdTkn = ulType - iCodedToken; 
  3844.         const char *pNameCdTkn;
  3845.         m_pTables->GetCodedTokenInfo(iCdTkn, 0,0, &pNameCdTkn);
  3846.         VWrite("%s[%08x]", pNameCdTkn, ulVal);
  3847.     }
  3848.     else
  3849.     {
  3850.         // Fixed type.
  3851.         switch (ulType)
  3852.         {
  3853.         case iBYTE:
  3854.             VWrite("%02x", ulVal);
  3855.             break;
  3856.         case iSHORT:
  3857.         case iUSHORT:
  3858.             VWrite("%04x", ulVal);
  3859.             break;
  3860.         case iLONG:
  3861.         case iULONG:
  3862.             VWrite("%08x", ulVal);
  3863.             break;
  3864.         case iSTRING:
  3865.             VWrite("string#%x", ulVal);
  3866.             if (bStats || ulVal)
  3867.             {
  3868.                 m_pTables->GetString(ulVal, &pString);
  3869.                 VWrite("(%s)", pString);
  3870.                 //cb = strlen(pString) + 1;
  3871.                 //VWrite("(%d)", cb);
  3872.             }
  3873.             break;
  3874.         case iGUID:
  3875.             VWrite("guid#%x", ulVal);
  3876.             if (bStats && ulVal)
  3877.             {
  3878.                 VWrite("(16)");
  3879.             }
  3880.             break;
  3881.         case iBLOB:
  3882.             VWrite("blob#%x", ulVal);
  3883.             if (bStats && ulVal)
  3884.             {
  3885.                 m_pTables->GetBlob(ulVal, &cb, &pBlob);
  3886.                 cb += 1;
  3887.                 if (cb > 128)
  3888.                     cb += 1;
  3889.                 if (cb > 16535)
  3890.                     cb += 1;
  3891.                 VWrite("(%d)", cb);
  3892.             }
  3893.             break;
  3894.         default:
  3895.             VWrite("unknown type 0x%04x", ulVal);
  3896.             break;
  3897.         }
  3898.     }
  3899. } // void MDInfo::DumpRawCol()
  3900.  
  3901. ULONG MDInfo::DumpRawColStats(ULONG ixTbl, ULONG ixCol, ULONG cRows)
  3902. {
  3903.     ULONG rslt = 0;
  3904.     ULONG       ulType;                 // Type of a column.
  3905.     ULONG       ulVal;                  // Value of a column.
  3906.     LPCUTF8     pString;                // Pointer to a string.
  3907.     const void  *pBlob;                 // Pointer to a blob.
  3908.     ULONG       cb;                     // Size of something.
  3909.  
  3910.     m_pTables->GetColumnInfo(ixTbl, ixCol, 0, 0, &ulType, 0);
  3911.  
  3912.     if (IsHeapType(ulType))
  3913.     {
  3914.         for (ULONG rid=1; rid<=cRows; ++rid)
  3915.         {
  3916.             m_pTables->GetColumn(ixTbl, ixCol, rid, &ulVal);
  3917.             // Fixed type.
  3918.             switch (ulType)
  3919.             {
  3920.             case iSTRING:
  3921.                 if (ulVal)
  3922.                 {
  3923.                     m_pTables->GetString(ulVal, &pString);
  3924.                     cb = strlen(pString);
  3925.                     rslt += cb + 1;
  3926.                 }
  3927.                 break;
  3928.             case iGUID:
  3929.                 if (ulVal)
  3930.                     rslt += 16;
  3931.                 break;
  3932.             case iBLOB:
  3933.                 if (ulVal)
  3934.                 {
  3935.                     m_pTables->GetBlob(ulVal, &cb, &pBlob);
  3936.                     rslt += cb + 1;
  3937.                     if (cb > 128)
  3938.                         rslt += 1;
  3939.                     if (cb > 16535)
  3940.                         rslt += 1;
  3941.                 }
  3942.                 break;
  3943.             default:
  3944.                 break;
  3945.             }
  3946.         }
  3947.     }
  3948.     return rslt;
  3949. } // ULONG MDInfo::DumpRawColStats()
  3950.  
  3951. void MDInfo::DumpRawHeaps()
  3952. {
  3953.     ULONG       ulSize;                 // Bytes in a heap.
  3954.     const BYTE  *pStart;                // Pointer to start of heap.
  3955.     const BYTE  *pData;                 // Pointer to a blob.
  3956.     ULONG       cbData;                 // Size of a blob.
  3957.     ULONG       oData;                  // Offset of current blob.
  3958.     ULONG       i, j;                   // Loop control.
  3959.     ULONG       nPrint;                 // Number to print in an iteration.
  3960.     ULONG       nSpace;                 // Spacing calculations.
  3961.  
  3962.     m_pTables->GetBlobHeapSize(&ulSize);
  3963.     VWrite("\nBlob Heap:  %d(%#x) bytes", ulSize,ulSize);
  3964.     oData = 0;
  3965.     m_pTables->GetBlob(0, &cbData, (const void**)&pStart);
  3966.     --pStart;
  3967.     while (oData < ulSize)
  3968.     {
  3969.         m_pTables->GetBlob(oData, &cbData, (const void**)&pData);
  3970.         VWrite("\n%5x,%-2x: ", oData, cbData);
  3971.         for(i=0; i<cbData; i+=16)
  3972.         {   // Calculate spacing.
  3973.             nPrint = min(cbData-i, 16);
  3974.             nSpace = 16 - nPrint;
  3975.             // Offset of the segment.
  3976.             // VWrite("  %04x:  ", i);
  3977.             if (i>0)
  3978.                 VWrite("\n%*s: ", oData>99999 ? 9 : 8, "");
  3979.             // dump in hex.
  3980.             for(j=0; j<nPrint; j++)
  3981.             {
  3982.                 if (j == 8)
  3983.                     Write(" ");
  3984.                 VWrite("%02x ", pData[i+j]);
  3985.             }
  3986.             // Space out to the text spot.
  3987.             if (nSpace)
  3988.                 VWrite("%*s", nSpace*3+nSpace/8, "");
  3989.             // Dump in text.
  3990.             Write(">");
  3991.             for(j=0; j<nPrint; j++)
  3992.                 VWrite("%c", (isprint(pData[i+j])) ? pData[i+j] : ' ');
  3993.             VWrite("%*s<", nSpace, "");
  3994.         }
  3995.         oData = (pData - pStart) + cbData;
  3996.         //oData += cbData;
  3997.     }
  3998.  
  3999.     m_pTables->GetStringHeapSize(&ulSize);
  4000.     VWrite("\n\nString Heap:  %d(%#x) bytes\n", ulSize,ulSize);
  4001.     oData = 0;
  4002.     const char *pString;
  4003.     m_pTables->GetString(oData, &pString);
  4004.     while (oData < ulSize)
  4005.     {
  4006.         if (*pString == 0)
  4007.         {
  4008.             ++oData;
  4009.             ++pString;
  4010.             continue;
  4011.         }
  4012.         VWrite("%08x: %s\n", oData, pString);
  4013.         int iLen = strlen(pString) + 1;
  4014.         oData += iLen;
  4015.         pString += iLen;
  4016.     }
  4017.     
  4018.     DisplayUserStrings();
  4019.  
  4020. } // void MDInfo::DumpRawHeaps()
  4021.  
  4022.  
  4023. void MDInfo::DumpRaw(int iDump, bool bStats)
  4024. {
  4025.     ULONG       cTables;                // Tables in the database.
  4026.     ULONG       cCols;                  // Columns in a table.
  4027.     ULONG       cRows;                  // Rows in a table.
  4028.     ULONG       cbRow;                  // Bytes in a row of a table.
  4029.     ULONG       iKey;                   // Key column of a table.
  4030.     const char  *pNameTable;            // Name of a table.
  4031.     ULONG       oCol;                   // Offset of a column.
  4032.     ULONG       cbCol;                  // Size of a column.
  4033.     ULONG       ulType;                 // Type of a column.
  4034.     const char  *pNameColumn;           // Name of a column.
  4035.     ULONG       ulSize;
  4036.  
  4037.     m_pTables->GetNumTables(&cTables);
  4038.  
  4039.     m_pTables->GetStringHeapSize(&ulSize);
  4040.     VWrite("Strings: %d(%#x)", ulSize, ulSize);
  4041.     m_pTables->GetBlobHeapSize(&ulSize);
  4042.     VWrite(", Blobs: %d(%#x)", ulSize, ulSize);
  4043.     m_pTables->GetGuidHeapSize(&ulSize);
  4044.     VWrite(", Guids: %d(%#x)", ulSize, ulSize);
  4045.     m_pTables->GetUserStringHeapSize(&ulSize);
  4046.     VWriteLine(", User strings: %d(%#x)", ulSize, ulSize);
  4047.  
  4048.     for (ULONG ixTbl = 0; ixTbl < cTables; ++ixTbl)
  4049.     {
  4050.         m_pTables->GetTableInfo(ixTbl, &cbRow, &cRows, &cCols, &iKey, &pNameTable);
  4051.  
  4052.         if (cRows == 0 && iDump < 3)
  4053.             continue;
  4054.  
  4055.         if (iDump >= 2)
  4056.             VWriteLine("=================================================");
  4057.         VWriteLine("%2d: %-20s cRecs:%5d(%#x), cbRec:%3d(%#x), cbTable:%6d(%#x)",
  4058.             ixTbl, pNameTable, cRows, cRows, cbRow, cbRow, cbRow * cRows, cbRow * cRows);
  4059.  
  4060.         if (iDump < 2)
  4061.             continue;
  4062.  
  4063.         // Dump column definitions for the table.
  4064.         for (ULONG ixCol=0; ixCol<cCols; ++ixCol)
  4065.         {
  4066.             m_pTables->GetColumnInfo(ixTbl, ixCol, &oCol, &cbCol, &ulType, &pNameColumn);
  4067.  
  4068.             VWrite("  col %2x:%c %-12s oCol:%2x, cbCol:%x, %-7s",
  4069.                 ixCol, ((ixCol==iKey)?'*':' '), pNameColumn, oCol, cbCol, DumpRawNameOfType(ulType));
  4070.  
  4071.             if (bStats)
  4072.             {
  4073.                 ulSize = DumpRawColStats(ixTbl, ixCol, cRows);
  4074.                 if (ulSize)
  4075.                     VWrite("(%d)", ulSize);
  4076.             }
  4077.             VWriteLine("");
  4078.         }
  4079.  
  4080.         if (iDump < 3) 
  4081.             continue;
  4082.  
  4083.         // Dump the rows.
  4084.         for (ULONG rid = 1; rid <= cRows; ++rid)
  4085.         {
  4086.             if (rid == 1)
  4087.                 VWriteLine("-------------------------------------------------");
  4088.             VWrite(" %3x == ", rid);
  4089.             for (ixCol=0; ixCol < cCols; ++ixCol)
  4090.             {
  4091.                 if (ixCol) VWrite(", ");
  4092.                 VWrite("%d:", ixCol);
  4093.                 DumpRawCol(ixTbl, ixCol, rid, bStats);
  4094.             }
  4095.             VWriteLine("");
  4096.         }
  4097.     }
  4098.  
  4099.     if (m_DumpFilter & dumpRawHeaps)
  4100.         DumpRawHeaps();
  4101.  
  4102. } // void MDInfo::DumpRaw()
  4103.  
  4104. void MDInfo::DumpRawCSV()
  4105. {
  4106.     ULONG       cTables;                // Tables in the database.
  4107.     ULONG       cCols;                  // Columns in a table.
  4108.     ULONG       cRows;                  // Rows in a table.
  4109.     ULONG       cbRow;                  // Bytes in a row of a table.
  4110.     const char  *pNameTable;            // Name of a table.
  4111.     ULONG       ulSize;
  4112.  
  4113.     m_pTables->GetNumTables(&cTables);
  4114.  
  4115.     VWriteLine("Name,Size,cRecs,cbRec");
  4116.  
  4117.     m_pTables->GetStringHeapSize(&ulSize);
  4118.     VWriteLine("Strings,%d", ulSize);
  4119.  
  4120.     m_pTables->GetBlobHeapSize(&ulSize);
  4121.     VWriteLine("Blobs,%d", ulSize);
  4122.  
  4123.     m_pTables->GetGuidHeapSize(&ulSize);
  4124.     VWriteLine("Guids,%d", ulSize);
  4125.  
  4126.     for (ULONG ixTbl = 0; ixTbl < cTables; ++ixTbl)
  4127.     {
  4128.         m_pTables->GetTableInfo(ixTbl, &cbRow, &cRows, &cCols, NULL, &pNameTable);
  4129.         VWriteLine("%s,%d,%d,%d", pNameTable, cbRow*cRows, cRows, cbRow);
  4130.     }
  4131.  
  4132. } // void MDInfo::DumpRawCSV()
  4133.  
  4134.