summaryrefslogtreecommitdiff
path: root/src/ildasm/dasm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ildasm/dasm.cpp')
-rw-r--r--src/ildasm/dasm.cpp7974
1 files changed, 7974 insertions, 0 deletions
diff --git a/src/ildasm/dasm.cpp b/src/ildasm/dasm.cpp
new file mode 100644
index 0000000000..86ff5a8932
--- /dev/null
+++ b/src/ildasm/dasm.cpp
@@ -0,0 +1,7974 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include "ildasmpch.h"
+#include <crtdbg.h>
+#include <utilcode.h>
+#include "specstrings.h"
+#include "debugmacros.h"
+#include "corpriv.h"
+#include "ceeload.h"
+#include "dynamicarray.h"
+#include <metamodelpub.h>
+#include "formattype.h"
+
+#define DECLARE_DATA
+#include "dasmenum.hpp"
+#include "dis.h"
+
+#include "dasmgui.h"
+#include "resource.h"
+#include "dasm_sz.h"
+
+//#define MAX_FILENAME_LENGTH 2048 //moved to dis.h
+
+#include <corsym.h>
+#include <ndpversion.h>
+
+// Disable the "initialization of static local vars is no thread safe" error
+#ifdef _MSC_VER
+#pragma warning(disable : 4640)
+#endif
+
+#if defined(_DEBUG) && defined(FEATURE_PREJIT)
+#include <corcompile.h>
+#endif
+
+#ifndef FEATURE_CORECLR
+// Define also LegacyActivationShim::CoInitializeEE wrapper around CoInitializeEE
+#define LEGACY_ACTIVATION_SHIM_DEFINE_CoInitializeEE
+#include "LegacyActivationShim.h"
+#include "clrinternal.h"
+#endif
+
+#ifdef FEATURE_PAL
+#include "coreclrloader.h"
+#include "resourcestring.h"
+#define NATIVE_STRING_RESOURCE_NAME dasm_rc
+DECLARE_NATIVE_STRING_RESOURCE_TABLE(NATIVE_STRING_RESOURCE_NAME);
+#endif
+
+struct MIDescriptor
+{
+ mdToken tkClass; // defining class token
+ mdToken tkDecl; // implemented method token
+ mdToken tkBody; // implementing method token
+ mdToken tkBodyParent; // parent of the implementing method
+};
+
+ISymUnmanagedReader* g_pSymReader = NULL;
+
+IMDInternalImport* g_pImport = NULL;
+IMetaDataImport2* g_pPubImport;
+extern IMetaDataAssemblyImport* g_pAssemblyImport;
+PELoader * g_pPELoader;
+void * g_pMetaData;
+unsigned g_cbMetaData;
+IMAGE_COR20_HEADER * g_CORHeader;
+DynamicArray<__int32> *g_pPtrTags = NULL; //to keep track of all "ldptr"
+DynamicArray<DWORD> *g_pPtrSize= NULL; //to keep track of all "ldptr"
+int g_iPtrCount = 0;
+mdToken * g_cl_list = NULL;
+mdToken * g_cl_enclosing = NULL;
+BYTE* g_enum_td_type = NULL; // enum (TD) underlying types
+BYTE* g_enum_tr_type = NULL; // enum (TR) underlying types
+IMDInternalImport** g_asmref_import = NULL; // IMDInternalImports for external assemblies
+DynamicArray<MIDescriptor> *g_pmi_list = NULL;
+DWORD g_NumMI;
+DWORD g_NumClasses;
+DWORD g_NumTypeRefs;
+DWORD g_NumAsmRefs;
+DWORD g_NumModules;
+BOOL g_fDumpIL = TRUE;
+BOOL g_fDumpHeader = FALSE;
+BOOL g_fDumpAsmCode = TRUE;
+extern BOOL g_fDumpTokens; // declared in formatType.cpp
+BOOL g_fDumpStats = FALSE;
+BOOL g_fTDC = TRUE;
+BOOL g_fShowCA = TRUE;
+BOOL g_fCAVerbal = FALSE;
+BOOL g_fShowRefs = FALSE;
+
+BOOL g_fDumpToPerfWriter = FALSE;
+HANDLE g_PerfDataFilePtr = NULL;
+
+BOOL g_fDumpClassList = FALSE;
+BOOL g_fDumpTypeList = FALSE;
+BOOL g_fDumpSummary = FALSE;
+BOOL g_fDecompile = FALSE; // still in progress
+BOOL g_fShowBytes = FALSE;
+BOOL g_fShowSource = FALSE;
+BOOL g_fPrettyPrint = FALSE;
+BOOL g_fInsertSourceLines = FALSE;
+BOOL g_fThisIsInstanceMethod;
+BOOL g_fTryInCode = TRUE;
+
+BOOL g_fLimitedVisibility = FALSE;
+#if defined(_DEBUG) && defined(FEATURE_PREJIT)
+BOOL g_fNGenNativeMetadata = FALSE;
+#endif
+BOOL g_fHidePub = TRUE;
+BOOL g_fHidePriv = TRUE;
+BOOL g_fHideFam = TRUE;
+BOOL g_fHideAsm = TRUE;
+BOOL g_fHideFAA = TRUE;
+BOOL g_fHideFOA = TRUE;
+BOOL g_fHidePrivScope = TRUE;
+
+BOOL g_fProject = FALSE; // if .winmd file, transform to .NET view
+
+extern BOOL g_fQuoteAllNames; // declared in formatType.cpp, init to FALSE
+BOOL g_fShowProgressBar = TRUE;
+BOOL g_fForwardDecl=FALSE;
+
+char g_szAsmCodeIndent[MAX_MEMBER_LENGTH];
+char g_szNamespace[MAX_MEMBER_LENGTH];
+
+DWORD g_Mode = MODE_DUMP_ALL;
+
+char g_pszClassToDump[MAX_CLASSNAME_LENGTH];
+char g_pszMethodToDump[MAX_MEMBER_LENGTH];
+char g_pszSigToDump[MAX_SIGNATURE_LENGTH];
+
+BOOL g_fCustomInstructionEncodingSystem = FALSE;
+
+COR_FIELD_OFFSET *g_rFieldOffset = NULL;
+ULONG g_cFieldsMax, g_cFieldOffsets;
+
+char* g_pszExeFile;
+char g_szInputFile[MAX_FILENAME_LENGTH]; // in UTF-8
+WCHAR g_wszFullInputFile[MAX_PATH + 1]; // in UTF-16
+char g_szOutputFile[MAX_FILENAME_LENGTH]; // in UTF-8
+char* g_pszObjFileName;
+FILE* g_pFile = NULL;
+
+mdToken g_tkClassToDump = 0;
+mdToken g_tkMethodToDump = 0;
+
+unsigned g_uConsoleCP = CP_ACP;
+unsigned g_uCodePage = g_uConsoleCP;
+
+char* g_rchCA = NULL; // dyn.allocated array of CA dumped/not flags
+unsigned g_uNCA = 0; // num. of CAs
+
+struct ResourceNode;
+extern DynamicArray<LocalComTypeDescr*> *g_pLocalComType;
+extern ULONG g_LocalComTypeNum;
+
+// MetaInfo integration:
+#include "../tools/metainfo/mdinfo.h"
+#include "ivehandler.h"
+BOOL g_fDumpMetaInfo = FALSE;
+ULONG g_ulMetaInfoFilter = MDInfo::dumpDefault;
+// Validator module type.
+DWORD g_ValModuleType = ValidatorModuleTypeInvalid;
+IMetaDataDispenserEx *g_pDisp = NULL;
+void DisplayFile(__in __nullterminated wchar_t* szFile,
+ BOOL isFile,
+ ULONG DumpFilter,
+ __in_opt __nullterminated wchar_t* szObjFile,
+ strPassBackFn pDisplayString);
+extern mdMethodDef g_tkEntryPoint; // integration with MetaInfo
+// Abort disassembly flag:
+BOOL g_fAbortDisassembly = FALSE;
+
+DWORD DumpResourceToFile(__in __nullterminated WCHAR* wzFileName); // see DRES.CPP
+
+struct VTableRef
+{
+ mdMethodDef tkTok;
+ WORD wEntry;
+ WORD wSlot;
+};
+
+DynamicArray<VTableRef> *g_prVTableRef = NULL;
+ULONG g_nVTableRef = 0;
+
+struct EATableRef
+{
+ mdMethodDef tkTok;
+ char* pszName;
+};
+DynamicArray<EATableRef> *g_prEATableRef=NULL;
+ULONG g_nEATableRef = 0;
+ULONG g_nEATableBase = 0;
+
+extern HINSTANCE g_hResources;
+void DumpCustomAttributeProps(mdToken tkCA, mdToken tkType, mdToken tkOwner, BYTE*pBlob, ULONG ulLen, void *GUICookie, bool bWithOwner);
+
+WCHAR* RstrW(unsigned id)
+{
+ static WCHAR buffer[1024];
+ DWORD cchBuff = (DWORD)COUNTOF(buffer);
+ WCHAR* buff = (WCHAR*)buffer;
+ memset(buffer,0,sizeof(buffer));
+ switch(id)
+ {
+ case IDS_E_DASMOK:
+ case IDS_E_PARTDASM:
+ case IDS_E_PARAMSEQNO:
+ case IDS_E_MEMBRENUM:
+ case IDS_E_ODDMEMBER:
+ case IDS_E_ENUMINIT:
+ case IDS_E_NODATA:
+ case IDS_E_VTFUTABLE:
+ case IDS_E_BOGUSRVA:
+ case IDS_E_EATJTABLE:
+ case IDS_E_EATJSIZE:
+ case IDS_E_RESFLAGS:
+ case IDS_E_MIHENTRY:
+ case IDS_E_CODEMGRTBL:
+ case IDS_E_COMIMAGE:
+ case IDS_E_MDDETAILS:
+ case IDS_E_MISTART:
+ case IDS_E_MIEND:
+ case IDS_E_ONLYITEMS:
+ case IDS_E_DECOMPRESS:
+ case IDS_E_COMPRESSED:
+ case IDS_E_INSTRDECOD:
+ case IDS_E_INSTRTYPE:
+ case IDS_E_SECTHEADER:
+ case IDS_E_MDAIMPORT:
+ case IDS_E_MDAFROMMDI:
+ case IDS_E_MDIIMPORT:
+ case IDS_E_NOMANIFEST:
+ case IDS_W_CREATEDW32RES:
+ case IDS_E_CORRUPTW32RES:
+ case IDS_E_CANTACCESSW32RES:
+ case IDS_E_CANTOPENW32RES:
+ case IDS_ERRORREOPENINGFILE:
+ wcscpy_s(buffer,COUNTOF(buffer),W("// "));
+ buff +=3;
+ cchBuff -= 3;
+ break;
+ case IDS_E_AUTOCA:
+ case IDS_E_METHBEG:
+ case IDS_E_DASMNATIVE:
+ case IDS_E_METHODRT:
+ case IDS_E_CODESIZE:
+ case IDS_W_CREATEDMRES:
+ case IDS_E_READINGMRES:
+ wcscpy_s(buffer,COUNTOF(buffer),W("%s// "));
+ buff +=5;
+ cchBuff -= 5;
+ break;
+ case IDS_E_NORVA:
+ wcscpy_s(buffer,COUNTOF(buffer),W("/* "));
+ buff += 3;
+ cchBuff -= 3;
+ break;
+ default:
+ break;
+ }
+#ifdef FEATURE_PAL
+ LoadNativeStringResource(NATIVE_STRING_RESOURCE_TABLE(NATIVE_STRING_RESOURCE_NAME),id, buff, cchBuff, NULL);
+#else
+ _ASSERTE(g_hResources != NULL);
+ WszLoadString(g_hResources,id,buff,cchBuff);
+#endif
+ if(id == IDS_E_NORVA)
+ wcscat_s(buff,cchBuff,W(" */"));
+ return buffer;
+}
+
+char* RstrA(unsigned n, unsigned codepage)
+{
+ static char buff[2048];
+ WCHAR* wz = RstrW(n);
+ // Unicode -> UTF-8
+ memset(buff,0,sizeof(buff));
+ if(!WszWideCharToMultiByte(codepage,0,(LPCWSTR)wz,-1,buff,sizeof(buff),NULL,NULL))
+ buff[0] = 0;
+ return buff;
+}
+char* RstrUTF(unsigned n)
+{
+ return RstrA(n,CP_UTF8);
+}
+
+char* RstrANSI(unsigned n)
+{
+ return RstrA(n,g_uConsoleCP);
+}
+
+#if 0
+void PrintEncodingSystem()
+{
+ long i;
+
+ printf("Custom opcode encoding system employed\n");
+ printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
+
+ for (i = 0; i < 256; i++)
+ {
+ long value = g_pInstructionDecodingTable->m_SingleByteOpcodes[i];
+
+ printf("0x%02x --> ", i);
+ printf("%s\n", OpcodeInfo[value].pszName);
+ }
+}
+#endif
+
+// buffers for formatType functions
+extern CQuickBytes * g_szBuf_KEYWORD;
+extern CQuickBytes * g_szBuf_COMMENT;
+extern CQuickBytes * g_szBuf_ERRORMSG;
+extern CQuickBytes * g_szBuf_ANCHORPT;
+extern CQuickBytes * g_szBuf_JUMPPT;
+extern CQuickBytes * g_szBuf_UnquotedProperName;
+extern CQuickBytes * g_szBuf_ProperName;
+
+#ifndef FEATURE_CORECLR
+// CLR internal hosting API
+ICLRRuntimeHostInternal *g_pCLRRuntimeHostInternal = NULL;
+#endif
+
+#ifdef FEATURE_CORECLR
+#ifdef FEATURE_PAL
+CoreCLRLoader *g_loader;
+#endif
+MetaDataGetDispenserFunc metaDataGetDispenser;
+GetMetaDataInternalInterfaceFunc getMetaDataInternalInterface;
+GetMetaDataInternalInterfaceFromPublicFunc getMetaDataInternalInterfaceFromPublic;
+GetMetaDataPublicInterfaceFromInternalFunc getMetaDataPublicInterfaceFromInternal;
+#endif
+
+BOOL Init()
+{
+#ifdef FEATURE_CORECLR
+#ifdef FEATURE_PAL
+ g_loader = CoreCLRLoader::Create(g_pszExeFile);
+ if (g_loader == NULL)
+ {
+ return FALSE;
+ }
+ metaDataGetDispenser = (MetaDataGetDispenserFunc)g_loader->LoadFunction("MetaDataGetDispenser");
+ getMetaDataInternalInterface = (GetMetaDataInternalInterfaceFunc)g_loader->LoadFunction("GetMetaDataInternalInterface");
+ getMetaDataInternalInterfaceFromPublic = (GetMetaDataInternalInterfaceFromPublicFunc)g_loader->LoadFunction("GetMetaDataInternalInterfaceFromPublic");
+ getMetaDataPublicInterfaceFromInternal = (GetMetaDataPublicInterfaceFromInternalFunc)g_loader->LoadFunction("GetMetaDataPublicInterfaceFromInternal");
+#else // FEATURE_PAL
+ metaDataGetDispenser = (MetaDataGetDispenserFunc)MetaDataGetDispenser;
+ getMetaDataInternalInterface = (GetMetaDataInternalInterfaceFunc)GetMetaDataInternalInterface;
+ getMetaDataInternalInterfaceFromPublic = (GetMetaDataInternalInterfaceFromPublicFunc)GetMetaDataInternalInterfaceFromPublic;
+ getMetaDataPublicInterfaceFromInternal = (GetMetaDataPublicInterfaceFromInternalFunc)GetMetaDataPublicInterfaceFromInternal;
+#endif // FEATURE_PAL
+#else // FEATURE_CORECLR
+ if (FAILED(CoInitialize(NULL)))
+ {
+ return FALSE;
+ }
+
+ if (FAILED(LegacyActivationShim::CoInitializeCor(COINITCOR_DEFAULT)))
+ {
+ return FALSE;
+ }
+
+ if (FAILED(LegacyActivationShim::CoInitializeEE(COINITEE_DEFAULT)))
+ {
+ return FALSE;
+ }
+
+ ICLRRuntimeInfo *pCLRRuntimeInfo = NULL;
+ if (FAILED(LegacyActivationShim::Util::GetCLRRuntimeInfo(&pCLRRuntimeInfo)))
+ {
+ return FALSE;
+ }
+
+ if (FAILED(pCLRRuntimeInfo->GetInterface(
+ CLSID_CLRRuntimeHostInternal,
+ IID_ICLRRuntimeHostInternal,
+ (LPVOID *)&g_pCLRRuntimeHostInternal)))
+ {
+ return FALSE;
+ }
+#endif // FEATURE_CORECLR
+
+ g_szBuf_KEYWORD = new CQuickBytes();
+ g_szBuf_COMMENT = new CQuickBytes();
+ g_szBuf_ERRORMSG = new CQuickBytes();
+ g_szBuf_ANCHORPT = new CQuickBytes();
+ g_szBuf_JUMPPT = new CQuickBytes();
+ g_szBuf_UnquotedProperName = new CQuickBytes();
+ g_szBuf_ProperName = new CQuickBytes();
+ return TRUE;
+} // Init
+
+extern LPCSTR *rAsmRefName; // decl. in formatType.cpp -- for AsmRef aliases
+extern ULONG ulNumAsmRefs; // decl. in formatType.cpp -- for AsmRef aliases
+
+void Cleanup()
+{
+ if (g_pAssemblyImport != NULL)
+ {
+ g_pAssemblyImport->Release();
+ g_pAssemblyImport = NULL;
+ }
+ if (g_pPubImport != NULL)
+ {
+ g_pPubImport->Release();
+ g_pPubImport = NULL;
+ }
+ if (g_pImport != NULL)
+ {
+ g_pImport->Release();
+ g_pImport = NULL;
+ TokenSigDelete();
+ }
+ if (g_pDisp != NULL)
+ {
+ g_pDisp->Release();
+ g_pDisp = NULL;
+ }
+
+ if (g_pSymReader != NULL)
+ {
+ g_pSymReader->Release();
+ g_pSymReader = NULL;
+ }
+ if (g_pPELoader != NULL)
+ {
+ g_pPELoader->close();
+ SDELETE(g_pPELoader);
+ }
+ g_iPtrCount = 0;
+ g_NumClasses = 0;
+ g_NumTypeRefs = 0;
+ g_NumModules = 0;
+ g_tkEntryPoint = 0;
+ g_szAsmCodeIndent[0] = 0;
+ g_szNamespace[0]=0;
+ g_pszClassToDump[0]=0;
+ g_pszMethodToDump[0]=0;
+ g_pszSigToDump[0] = 0;
+ g_NumDups = 0;
+ g_NumRefs = 0;
+ g_NumMI = 0;
+ g_LocalComTypeNum = 0;
+ g_nEATableRef = 0;
+
+ g_fCustomInstructionEncodingSystem = FALSE;
+
+ if (rAsmRefName != NULL)
+ {
+ for (int i = 0; (unsigned)i < ulNumAsmRefs; i++)
+ {
+ if (rAsmRefName[i] != NULL) VDELETE(rAsmRefName[i]);
+ }
+ VDELETE(rAsmRefName);
+ ulNumAsmRefs = 0;
+ }
+
+ if (g_rchCA != NULL)
+ VDELETE(g_rchCA);
+
+ if (g_cl_list != NULL) VDELETE(g_cl_list);
+ if (g_cl_enclosing != NULL) VDELETE(g_cl_enclosing);
+ if (g_pmi_list != NULL) SDELETE(g_pmi_list);
+ if (g_dups != NULL) SDELETE(g_dups);
+ if (g_enum_td_type != NULL) VDELETE(g_enum_td_type);
+ if (g_enum_tr_type != NULL) VDELETE(g_enum_tr_type);
+ if (g_asmref_import != NULL)
+ {
+ for (DWORD i = 0; i < g_NumAsmRefs; i++)
+ {
+ if (g_asmref_import[i] != NULL)
+ g_asmref_import[i]->Release();
+ }
+ VDELETE(g_asmref_import);
+ g_NumAsmRefs = 0;
+ }
+} // Cleanup
+
+void Uninit()
+{
+#ifndef FEATURE_CORECLR
+ GUIAddOpcode(NULL,NULL);
+#endif
+
+ if (g_pPtrTags != NULL)
+ {
+ SDELETE(g_pPtrTags);
+ }
+ if (g_pPtrSize != NULL)
+ {
+ SDELETE(g_pPtrSize);
+ }
+ if (g_pmi_list != NULL)
+ {
+ SDELETE(g_pmi_list);
+ }
+ if (g_dups != NULL) SDELETE(g_dups);
+ if (g_refs != NULL) SDELETE(g_refs);
+ if (g_pLocalComType != NULL)
+ {
+ SDELETE(g_pLocalComType);
+ }
+ if (g_prVTableRef != NULL)
+ {
+ SDELETE(g_prVTableRef);
+ }
+ if (g_prEATableRef != NULL)
+ {
+ SDELETE(g_prEATableRef);
+ }
+ if (g_szBuf_KEYWORD != NULL)
+ {
+ SDELETE(g_szBuf_KEYWORD);
+ }
+ if (g_szBuf_COMMENT != NULL)
+ {
+ SDELETE(g_szBuf_COMMENT);
+ }
+ if (g_szBuf_ERRORMSG != NULL)
+ {
+ SDELETE(g_szBuf_ERRORMSG);
+ }
+ if (g_szBuf_ANCHORPT != NULL)
+ {
+ SDELETE(g_szBuf_ANCHORPT);
+ }
+ if (g_szBuf_JUMPPT != NULL)
+ {
+ SDELETE(g_szBuf_JUMPPT);
+ }
+ if (g_szBuf_UnquotedProperName != NULL)
+ {
+ SDELETE(g_szBuf_UnquotedProperName);
+ }
+ if (g_szBuf_UnquotedProperName != NULL)
+ {
+ SDELETE(g_szBuf_ProperName);
+ }
+
+#ifdef FEATURE_CORECLR
+#ifdef FEATURE_PAL
+ if (g_loader != NULL)
+ {
+ g_loader->Finish();
+ }
+#endif
+#else
+ if (g_pCLRRuntimeHostInternal != NULL)
+ {
+ g_pCLRRuntimeHostInternal->Release();
+ g_pCLRRuntimeHostInternal = NULL;
+ }
+
+ LegacyActivationShim::CoUninitializeEE(COUNINITEE_DEFAULT);
+ LegacyActivationShim::CoUninitializeCor();
+ CoUninitialize();
+#endif
+} // Uninit
+
+HRESULT IsClassRefInScope(mdTypeRef classref)
+{
+ HRESULT hr = S_OK;
+ const char *pszNameSpace;
+ const char *pszClassName;
+ mdTypeDef classdef;
+ mdToken tkRes;
+
+ IfFailRet(g_pImport->GetNameOfTypeRef(classref, &pszNameSpace, &pszClassName));
+ MAKE_NAME_IF_NONE(pszClassName,classref);
+ IfFailRet(g_pImport->GetResolutionScopeOfTypeRef(classref, &tkRes));
+
+ hr = g_pImport->FindTypeDef(pszNameSpace, pszClassName,
+ (TypeFromToken(tkRes) == mdtTypeRef) ? tkRes : mdTokenNil, &classdef);
+
+ return hr;
+}
+
+#ifdef _PREFAST_
+#pragma warning(push)
+#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
+#endif
+BOOL EnumClasses()
+{
+ HRESULT hr;
+ HENUMInternal hEnum;
+ ULONG i = 0,j;
+ //char szString[1024];
+ HENUMInternal hBody;
+ HENUMInternal hDecl;
+
+ if(g_cl_list) VDELETE(g_cl_list);
+ if(g_cl_enclosing) VDELETE(g_cl_enclosing);
+ if (g_pmi_list) SDELETE(g_pmi_list);
+ if (g_dups) SDELETE(g_dups);
+ if (g_enum_td_type) VDELETE(g_enum_td_type);
+ if (g_enum_tr_type) VDELETE(g_enum_tr_type);
+ if (g_asmref_import)
+ {
+ for (DWORD nIndex = 0; nIndex < g_NumAsmRefs; nIndex++)
+ {
+ if (g_asmref_import[nIndex] != NULL)
+ g_asmref_import[nIndex]->Release();
+ }
+ VDELETE(g_asmref_import);
+ g_NumAsmRefs = 0;
+ }
+ //--------------------------------------------------------------
+ if (FAILED(g_pImport->EnumAllInit(mdtTypeRef,&hEnum)))
+ {
+ printError(g_pFile, "MetaData error: cannot enumerate all TypeRefs");
+ return FALSE;
+ }
+ g_NumTypeRefs = g_pImport->EnumGetCount(&hEnum);
+ g_pImport->EnumClose(&hEnum);
+
+ if(g_NumTypeRefs)
+ {
+ g_enum_tr_type = new BYTE[g_NumTypeRefs+1];
+ if(g_enum_tr_type == NULL) return FALSE;
+ memset(g_enum_tr_type,0xFF,g_NumTypeRefs+1);
+ }
+ //--------------------------------------------------------------
+ if (FAILED(g_pImport->EnumAllInit(mdtAssemblyRef, &hEnum)))
+ {
+ printError(g_pFile, "MetaData error: cannot enumerate all AssemblyRefs");
+ return FALSE;
+ }
+ g_NumAsmRefs = g_pImport->EnumGetCount(&hEnum);
+ g_pImport->EnumClose(&hEnum);
+ if(g_NumAsmRefs)
+ {
+ g_asmref_import = new IMDInternalImport*[g_NumAsmRefs+1];
+ if(g_asmref_import == NULL) return FALSE;
+ memset(g_asmref_import,0,(g_NumAsmRefs+1)*sizeof(IMDInternalImport*));
+ }
+ //--------------------------------------------------------------
+ hr = g_pImport->EnumTypeDefInit(
+ &hEnum);
+ if (FAILED(hr))
+ {
+ printError(g_pFile,RstrUTF(IDS_E_CLSENUM));
+ return FALSE;
+ }
+
+ g_NumClasses = g_pImport->EnumTypeDefGetCount(&hEnum);
+
+ g_tkClassToDump = 0;
+
+ g_NumMI = 0;
+ g_NumDups = 0;
+
+ if(g_NumClasses == 0) return TRUE;
+
+ g_enum_td_type = new BYTE[g_NumClasses+1];
+ if(g_enum_td_type == NULL) return FALSE;
+ memset(g_enum_td_type,0xFF,g_NumClasses+1);
+
+ g_cl_list = new mdToken[g_NumClasses];
+ if(g_cl_list == NULL) return FALSE;
+
+ g_cl_enclosing = new mdToken[g_NumClasses];
+ if(g_cl_enclosing == NULL)
+ {
+ VDELETE(g_cl_list);
+ return FALSE;
+ }
+
+ g_pmi_list = new DynamicArray<MIDescriptor>;
+ if(g_pmi_list == NULL)
+ {
+ VDELETE(g_cl_enclosing);
+ VDELETE(g_cl_list);
+ return FALSE;
+ }
+
+ g_dups = new DynamicArray<mdToken>;
+ if(g_dups == NULL)
+ {
+ SDELETE(g_pmi_list);
+ VDELETE(g_cl_enclosing);
+ VDELETE(g_cl_list);
+ return FALSE;
+ }
+
+ // fill the list of typedef tokens
+ while(g_pImport->EnumTypeDefNext(&hEnum, &g_cl_list[i]))
+ {
+ mdToken tkEnclosing;
+
+ if (g_Mode == MODE_DUMP_CLASS || g_Mode == MODE_DUMP_CLASS_METHOD || g_Mode == MODE_DUMP_CLASS_METHOD_SIG)
+ {
+ CQuickBytes out;
+
+ // we want plain class name without token values
+ BOOL fDumpTokens = g_fDumpTokens;
+ g_fDumpTokens = FALSE;
+
+ PAL_CPP_TRY
+ {
+ if (strcmp(PrettyPrintClass(&out, g_cl_list[i], g_pImport), g_pszClassToDump) == 0)
+ {
+ g_tkClassToDump = g_cl_list[i];
+ }
+ }
+ PAL_CPP_CATCH_ALL
+ { }
+ PAL_CPP_ENDTRY;
+
+ g_fDumpTokens = fDumpTokens;
+ }
+ g_cl_enclosing[i] = mdTypeDefNil;
+
+ hr = g_pImport->GetNestedClassProps(g_cl_list[i],&tkEnclosing);
+ if (SUCCEEDED(hr) && RidFromToken(tkEnclosing)) // No need to check token validity here, it's done later
+ g_cl_enclosing[i] = tkEnclosing;
+ if (SUCCEEDED(g_pImport->EnumMethodImplInit(g_cl_list[i],&hBody,&hDecl)))
+ {
+ if ((j = g_pImport->EnumMethodImplGetCount(&hBody,&hDecl)))
+ {
+ mdToken tkBody,tkDecl,tkBodyParent;
+ for (ULONG k = 0; k < j; k++)
+ {
+ if (g_pImport->EnumMethodImplNext(&hBody,&hDecl,&tkBody,&tkDecl) == S_OK)
+ {
+ if (SUCCEEDED(g_pImport->GetParentToken(tkBody,&tkBodyParent)))
+ {
+ (*g_pmi_list)[g_NumMI].tkClass = g_cl_list[i];
+ (*g_pmi_list)[g_NumMI].tkBody = tkBody;
+ (*g_pmi_list)[g_NumMI].tkDecl = tkDecl;
+ (*g_pmi_list)[g_NumMI].tkBodyParent = tkBodyParent;
+ g_NumMI++;
+ }
+ }
+ }
+ }
+ g_pImport->EnumMethodImplClose(&hBody,&hDecl);
+ }
+ i++;
+ }
+ g_pImport->EnumTypeDefClose(&hEnum);
+ // check nesting consistency (circular nesting, invalid enclosers)
+ for(i = 0; i < g_NumClasses; i++)
+ {
+ mdToken tkThis = g_cl_list[i];
+ mdToken tkEncloser = g_cl_enclosing[i];
+ mdToken tkPrevLevel = tkThis;
+ while(tkEncloser != mdTypeDefNil)
+ {
+ if(tkThis == tkEncloser)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_SELFNSTD),tkThis);
+ printError(g_pFile,szString);
+ g_cl_enclosing[i] = mdTypeDefNil;
+ break;
+ }
+ else
+ {
+ for(j = 0; (j < g_NumClasses)&&(tkEncloser != g_cl_list[j]); j++);
+ if(j == g_NumClasses)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_NOENCLOS),
+ tkPrevLevel,tkEncloser);
+ printError(g_pFile,szString);
+ g_cl_enclosing[i] = mdTypeDefNil;
+ break;
+ }
+ else
+ {
+ tkPrevLevel = tkEncloser;
+ tkEncloser = g_cl_enclosing[j];
+ }
+ }
+ } // end while(tkEncloser != mdTypeDefNil)
+ } // end for(i = 0; i < g_NumClasses; i++)
+
+ // register all class dups
+ const char *pszClassName;
+ const char *pszNamespace;
+ const char *pszClassName1;
+ const char *pszNamespace1;
+
+ if (FAILED(g_pImport->GetNameOfTypeDef(
+ g_cl_list[0],
+ &pszClassName,
+ &pszNamespace)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), g_cl_list[0]);
+ printLine(g_pFile, sz);
+ return FALSE;
+ }
+ if((g_cl_enclosing[0]==mdTypeDefNil)
+ &&(0==strcmp(pszClassName,"<Module>"))
+ &&(*pszNamespace == 0))
+ {
+ (*g_dups)[g_NumDups++] = g_cl_list[0];
+ }
+ for(i = 1; i < g_NumClasses; i++)
+ {
+ if (FAILED(g_pImport->GetNameOfTypeDef(
+ g_cl_list[i],
+ &pszClassName,
+ &pszNamespace)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), g_cl_list[i]);
+ printLine(g_pFile, sz);
+ return FALSE;
+ }
+
+ for(j = 0; j < i; j++)
+ {
+ if (FAILED(g_pImport->GetNameOfTypeDef(
+ g_cl_list[j],
+ &pszClassName1,
+ &pszNamespace1)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), g_cl_list[j]);
+ printLine(g_pFile, sz);
+ return FALSE;
+ }
+
+ if((g_cl_enclosing[i]==g_cl_enclosing[j])
+ &&(0==strcmp(pszClassName,pszClassName1))
+ &&(0==strcmp(pszNamespace,pszNamespace1)))
+ {
+ (*g_dups)[g_NumDups++] = g_cl_list[i];
+ break;
+ }
+ }
+ } // end for(i = 1; i < g_NumClasses; i++)
+
+ //register all field and method dups
+ for(i = 0; i <= g_NumClasses; i++)
+ {
+ HENUMInternal hEnumMember;
+ mdToken *pMemberList = NULL;
+ DWORD NumMembers,k;
+
+ // methods
+ if (i != 0)
+ {
+ hr = g_pImport->EnumInit(mdtMethodDef, g_cl_list[i-1], &hEnumMember);
+ }
+ else
+ {
+ hr = g_pImport->EnumGlobalFunctionsInit(&hEnumMember);
+ }
+ if (FAILED(hr))
+ {
+ printLine(g_pFile,RstrUTF(IDS_E_MEMBRENUM));
+ return FALSE;
+ }
+ NumMembers = g_pImport->EnumGetCount(&hEnumMember);
+ pMemberList = new mdToken[NumMembers];
+ for (j = 0; g_pImport->EnumNext(&hEnumMember, &pMemberList[j]); j++);
+ _ASSERTE(j == NumMembers);
+ g_pImport->EnumClose(&hEnumMember);
+ for (j = 1; j < NumMembers; j++)
+ {
+ const char *pszName;
+ ULONG cSig;
+ PCCOR_SIGNATURE pSig;
+ if (FAILED(g_pImport->GetNameOfMethodDef(pMemberList[j], &pszName)) ||
+ FAILED(g_pImport->GetSigOfMethodDef(pMemberList[j], &cSig, &pSig)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), pMemberList[j]);
+ printLine(g_pFile, sz);
+ return FALSE;
+ }
+ for (k = 0; k < j; k++)
+ {
+ const char *szName1;
+ if (FAILED(g_pImport->GetNameOfMethodDef(pMemberList[k], &szName1)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), pMemberList[k]);
+ printLine(g_pFile, sz);
+ return FALSE;
+ }
+ if (strcmp(pszName, szName1) == 0)
+ {
+ ULONG cSig1;
+ PCCOR_SIGNATURE pSig1;
+ if (FAILED(g_pImport->GetSigOfMethodDef(pMemberList[k], &cSig1, &pSig1)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), pMemberList[k]);
+ printLine(g_pFile, sz);
+ return FALSE;
+ }
+ if((cSig == cSig1)&&(0==memcmp(pSig,pSig1,cSig)))
+ {
+ (*g_dups)[g_NumDups++] = pMemberList[j];
+ break;
+ }
+ }
+ }
+ }
+ VDELETE(pMemberList);
+
+ // fields
+ if (i != 0)
+ {
+ hr = g_pImport->EnumInit(mdtFieldDef, g_cl_list[i-1], &hEnumMember);
+ }
+ else
+ {
+ hr = g_pImport->EnumGlobalFieldsInit(&hEnumMember);
+ }
+ if (FAILED(hr))
+ {
+ printLine(g_pFile,RstrUTF(IDS_E_MEMBRENUM));
+ return FALSE;
+ }
+ NumMembers = g_pImport->EnumGetCount(&hEnumMember);
+ pMemberList = new mdToken[NumMembers];
+ for (j = 0; g_pImport->EnumNext(&hEnumMember, &pMemberList[j]); j++);
+ _ASSERTE(j == NumMembers);
+ g_pImport->EnumClose(&hEnumMember);
+ for (j = 1; j < NumMembers; j++)
+ {
+ const char *pszName;
+ ULONG cSig;
+ PCCOR_SIGNATURE pSig;
+ if (FAILED(g_pImport->GetNameOfFieldDef(pMemberList[j], &pszName)) ||
+ FAILED(g_pImport->GetSigOfFieldDef(pMemberList[j], &cSig, &pSig)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), pMemberList[j]);
+ printLine(g_pFile, sz);
+ return FALSE;
+ }
+ for (k = 0; k < j; k++)
+ {
+ const char *szName1;
+ if (FAILED(g_pImport->GetNameOfFieldDef(pMemberList[k], &szName1)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), pMemberList[k]);
+ printLine(g_pFile, sz);
+ return FALSE;
+ }
+ if (strcmp(pszName, szName1) == 0)
+ {
+ ULONG cSig1;
+ PCCOR_SIGNATURE pSig1;
+ if (FAILED(g_pImport->GetSigOfFieldDef(pMemberList[k], &cSig1, &pSig1)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), pMemberList[k]);
+ printLine(g_pFile, sz);
+ return FALSE;
+ }
+ if((cSig == cSig1)&&(0==memcmp(pSig,pSig1,cSig)))
+ {
+ (*g_dups)[g_NumDups++] = pMemberList[j];
+ break;
+ }
+ }
+ }
+ }
+ VDELETE(pMemberList);
+
+ } // end for(i = 0; i <= g_NumClasses; i++)
+ return TRUE;
+}
+#ifdef _PREFAST_
+#pragma warning(pop)
+#endif
+
+#ifndef _DEBUG
+bool HasSuppressingAttribute()
+{
+ const void* pData;
+ ULONG cbData;
+
+ return ((S_OK == g_pImport->GetCustomAttributeByName(TokenFromRid(mdtModule,1),
+ (LPCUTF8)"System.Runtime.CompilerServices.SuppressIldasmAttribute",
+ &pData,
+ &cbData))
+ || (S_OK == g_pImport->GetCustomAttributeByName(TokenFromRid(mdtAssembly,1),
+ (LPCUTF8)"System.Runtime.CompilerServices.SuppressIldasmAttribute",
+ &pData,
+ &cbData)));
+}
+#endif
+void DumpMscorlib(void* GUICookie)
+{
+ if(g_pAssemblyImport==NULL) g_pAssemblyImport = GetAssemblyImport(GUICookie);
+ if(g_pAssemblyImport!=NULL)
+ {
+ mdAssembly tkAsm;
+ if(SUCCEEDED(g_pAssemblyImport->GetAssemblyFromScope(&tkAsm))&&(tkAsm != mdAssemblyNil))
+ {
+ const void* pPublicKey;
+ ULONG cbPublicKey = 0;
+ ULONG ulHashAlgId;
+ WCHAR wzName[1024];
+ ULONG ulNameLen=0;
+ ASSEMBLYMETADATA md;
+ WCHAR wzLocale[1024];
+ DWORD dwFlags;
+ //char szString[4096];
+
+ md.szLocale = wzLocale;
+ md.cbLocale = 1024;
+ md.rProcessor = NULL;
+ md.ulProcessor = 0;
+ md.rOS = NULL;
+ md.ulOS = 0;
+
+ if(SUCCEEDED(g_pAssemblyImport->GetAssemblyProps( // S_OK or error.
+ tkAsm, // [IN] The Assembly for which to get the properties.
+ &pPublicKey, // [OUT] Pointer to the public key.
+ &cbPublicKey,// [OUT] Count of bytes in the public key.
+ &ulHashAlgId,// [OUT] Hash Algorithm.
+ wzName, // [OUT] Buffer to fill with name.
+ 1024, // [IN] Size of buffer in wide chars.
+ &ulNameLen, // [OUT] Actual # of wide chars in name.
+ &md, // [OUT] Assembly MetaData.
+ &dwFlags))) // [OUT] Flags.
+ {
+ if(wcscmp(wzName,W("mscorlib")) == 0)
+ {
+ printLine(GUICookie,"");
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".mscorlib"));
+ printLine(GUICookie,szString);
+ printLine(GUICookie,"");
+ }
+ }
+ }
+ }
+}
+void DumpTypelist(void* GUICookie)
+{
+ if(g_NumClasses > 1)
+ {
+ DWORD i;
+ CQuickBytes out;
+ printLine(GUICookie,"");
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".typelist"));
+ printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+
+ for(i = 0; i < g_NumClasses; i++)
+ {
+ out.Shrink(0);
+ sprintf_s(szString,SZSTRING_SIZE, "%s%s",g_szAsmCodeIndent, PrettyPrintClass(&out, g_cl_list[i], g_pImport));
+ printLine(GUICookie,szString);
+ }
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
+ printLine(GUICookie,szString);
+ printLine(GUICookie,"");
+ }
+
+}
+#define ELEMENT_TYPE_TYPEDEF ELEMENT_TYPE_MAX+1
+BOOL EnumTypedefs()
+{
+ HENUMInternal hEnum;
+ ULONG i,l;
+ mdToken tk;
+ if (g_typedefs) SDELETE(g_typedefs);
+ g_typedefs = new DynamicArray<TypeDefDescr>;
+ g_NumTypedefs = 0;
+ if (FAILED(g_pImport->EnumAllInit(mdtTypeSpec, &hEnum)))
+ {
+ return FALSE;
+ }
+ for (i = 0; g_pImport->EnumNext(&hEnum, &tk); i++)
+ {
+ ULONG cSig;
+ PCCOR_SIGNATURE sig;
+ if (FAILED(g_pImport->GetSigFromToken(tk, &cSig, &sig)))
+ {
+ return FALSE;
+ }
+ if (*sig == ELEMENT_TYPE_TYPEDEF)
+ {
+ TypeDefDescr* pTDD = &((*g_typedefs)[g_NumTypedefs]);
+ pTDD->szName = (char*)sig+1;
+ l = 2+(ULONG)strlen((char*)sig+1);
+ pTDD->tkTypeSpec = GET_UNALIGNED_VAL32(sig + l);
+ pTDD->tkSelf = tk;
+ if (TypeFromToken(pTDD->tkTypeSpec) == mdtTypeSpec)
+ {
+ if (FAILED(g_pImport->GetSigFromToken(pTDD->tkTypeSpec,&(pTDD->cb), &(pTDD->psig))))
+ {
+ return FALSE;
+ }
+ }
+ else if (TypeFromToken(pTDD->tkTypeSpec) == mdtCustomAttribute)
+ {
+ l += sizeof(mdToken);
+ pTDD->psig = sig + l;
+ pTDD->cb = cSig - l;
+ }
+ else
+ {
+ pTDD->psig = NULL;
+ pTDD->cb = 0;
+ }
+ g_NumTypedefs++;
+ }
+ }
+ g_pImport->EnumClose(&hEnum);
+ return TRUE;
+}
+
+void DumpTypedefs(void* GUICookie)
+{
+ HRESULT hr;
+ DWORD i;
+ char* szptr;
+ CQuickBytes out;
+ printLine(GUICookie,"");
+ for(i = 0; i < g_NumTypedefs; i++)
+ {
+ TypeDefDescr* pTDD = &((*g_typedefs)[i]);
+ szptr = &szString[0];
+ szString[0] = 0;
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,ANCHORPT(KEYWORD(".typedef"),pTDD->tkSelf));
+ if(g_fDumpTokens)
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),pTDD->tkSelf);
+
+ {
+ ULONG n = g_NumTypedefs;
+ DWORD tk = pTDD->tkTypeSpec;
+ switch (TypeFromToken(tk))
+ {
+ default:
+ break;
+
+ case mdtCustomAttribute:
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+ {
+ mdToken tkType;
+ mdToken tkOwner;
+ BYTE* pBlob=NULL;
+ ULONG uLen=0;
+ tkType = GET_UNALIGNED_VAL32(pTDD->psig);
+ tkOwner = GET_UNALIGNED_VAL32(pTDD->psig + sizeof(mdToken));
+ if(pTDD->cb > 2*sizeof(mdToken))
+ {
+ pBlob = (BYTE*)pTDD->psig + 2*sizeof(mdToken);
+ uLen = pTDD->cb - 2*sizeof(mdToken);
+ }
+ DumpCustomAttributeProps(0,tkType,tkOwner,pBlob,uLen,GUICookie,
+ (RidFromToken(tkOwner)!=0));
+
+ }
+ sprintf_s(szString,SZSTRING_SIZE,"%s %s %s", g_szAsmCodeIndent,KEYWORD("as"),
+ ProperName((*g_typedefs)[i].szName));
+ printLine(GUICookie,szString);
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-8]=0;
+ continue;
+
+ case mdtMethodDef:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("method "));
+ break;
+
+ case mdtFieldDef:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("field "));
+ break;
+
+ case mdtMemberRef:
+ {
+ PCCOR_SIGNATURE typePtr;
+ const char *pszMemberName;
+ ULONG cComSig;
+
+ if (FAILED(g_pImport->GetNameAndSigOfMemberRef(
+ tk,
+ &typePtr,
+ &cComSig,
+ &pszMemberName)))
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"ERROR ");
+ break;
+ }
+ unsigned callConv = CorSigUncompressData(typePtr);
+
+ if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD))
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("field "));
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("method "));
+ break;
+ }
+ }
+ g_NumTypedefs = 0;
+ PrettyPrintToken(szString, tk, g_pImport,g_pFile,0);
+ g_NumTypedefs = n;
+ szptr = &szString[strlen(szString)];
+ }
+ szptr+= sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %s %s", KEYWORD("as"), ProperName((*g_typedefs)[i].szName));
+ printLine(GUICookie,szString);
+ }
+}
+
+BOOL PrintClassList()
+{
+ DWORD i;
+ BOOL fSuccess = FALSE;
+ //char szString[1024];
+ char* szptr;
+
+ if(g_NumClasses)
+ {
+ printLine(g_pFile,COMMENT("// Classes defined in this module:"));
+ printLine(g_pFile,COMMENT("//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"));
+
+ for (i = 0; i < g_NumClasses; i++)
+ {
+ const char *pszClassName;
+ const char *pszNamespace;
+ DWORD dwClassAttrs;
+ mdTypeRef crExtends;
+
+ if (FAILED(g_pImport->GetNameOfTypeDef(
+ g_cl_list[i],
+ &pszClassName,
+ &pszNamespace)))
+ {
+ printLine(g_pFile, COMMENT("// Invalid TypeDef record"));
+ return FALSE;
+ }
+ MAKE_NAME_IF_NONE(pszClassName,g_cl_list[i]);
+ // if this is the "<Module>" class (there is a misnomer) then skip it!
+ if (FAILED(g_pImport->GetTypeDefProps(
+ g_cl_list[i],
+ &dwClassAttrs,
+ &crExtends)))
+ {
+ printLine(g_pFile, COMMENT("// Invalid TypeDef record"));
+ return FALSE;
+ }
+ szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"// ");
+ if (IsTdInterface(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"Interface ");
+ //else if (IsTdValueType(dwClassAttrs)) szptr+=sprintf(szptr,"Value Class");
+ //else if (IsTdUnmanagedValueType(dwClassAttrs)) szptr+=sprintf(szptr,"NotInGCHeap Value Class");
+ else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"Class ");
+
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%-30s ", pszClassName);
+
+ if (IsTdPublic(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(public) ");
+ if (IsTdAbstract(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(abstract) ");
+ if (IsTdAutoLayout(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(auto) ");
+ if (IsTdSequentialLayout(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(sequential) ");
+ if (IsTdExplicitLayout(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(explicit) ");
+ if (IsTdAnsiClass(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(ansi) ");
+ if (IsTdUnicodeClass(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(unicode) ");
+ if (IsTdAutoClass(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(autochar) ");
+ if (IsTdImport(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(import) ");
+ if (IsTdWindowsRuntime(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(windowsruntime) ");
+ //if (IsTdEnum(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(enum) ");
+ if (IsTdSealed(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(sealed) ");
+ if (IsTdNestedPublic(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(nested public) ");
+ if (IsTdNestedPrivate(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(nested private) ");
+ if (IsTdNestedFamily(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(nested family) ");
+ if (IsTdNestedAssembly(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(nested assembly) ");
+ if (IsTdNestedFamANDAssem(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(nested famANDassem) ");
+ if (IsTdNestedFamORAssem(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(nested famORassem) ");
+
+ printLine(g_pFile,COMMENT(szString));
+ }
+ printLine(g_pFile,COMMENT("//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"));
+ printLine(g_pFile,"");
+ }
+ else
+ printLine(g_pFile,COMMENT("// No classes defined in this module"));
+ fSuccess = TRUE;
+
+ return fSuccess;
+}
+
+BOOL ValidateToken(mdToken tk, ULONG type = (ULONG) ~0)
+{
+ BOOL bRtn;
+ //char szString[1024];
+ bRtn = g_pImport->IsValidToken(tk);
+ if (!bRtn)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_INVALIDTK), tk);
+ printError(g_pFile,szString);
+ }
+ else if (type != (ULONG) ~0 && TypeFromToken(tk) != type)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_UNEXPTYPE),
+ TypeFromToken(type), TypeFromToken(tk));
+ printError(g_pFile,szString);
+ bRtn = FALSE;
+ }
+ return bRtn;
+}
+
+
+BOOL DumpModule(mdModuleRef mdMod)
+{
+ const char *pszModName;
+ //char szString[1024];
+ if (FAILED(g_pImport->GetModuleRefProps(mdMod,&pszModName)))
+ {
+ pszModName = "Invalid ModuleRef record";
+ }
+ MAKE_NAME_IF_NONE(pszModName,mdMod);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s \"%s\"",g_szAsmCodeIndent,KEYWORD(".import"),pszModName); // what about GUID and MVID?
+ printLine(g_pFile,szString);
+ return TRUE;
+}
+
+char* DumpPinvokeMap(DWORD dwMappingFlags, const char *szImportName,
+ mdModuleRef mrImportDLL, __inout __nullterminated char* szString, void* GUICookie)
+{
+ const char *szImportDLLName;
+ char* szptr = &szString[strlen(szString)];
+
+ if (FAILED(g_pImport->GetModuleRefProps(mrImportDLL,&szImportDLLName)))
+ {
+ szImportDLLName = "Invalid ModuleRef record";
+ }
+ if(strlen(szImportDLLName) != 0)
+ {
+ szptr = DumpQString(GUICookie,
+ (char*)szImportDLLName,
+ g_szAsmCodeIndent,
+ 80);
+ }
+
+ //if(strlen(szImportDLLName)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"\"%s\"",szImportDLLName);
+ //if(szImportName && strlen(szImportName)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," as \"%s\"",szImportName);
+ if(szImportName && strlen(szImportName))
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD(" as "));
+ szptr = DumpQString(GUICookie,
+ (char*)szImportName,
+ g_szAsmCodeIndent,
+ 80);
+ }
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)0));
+ if(IsPmNoMangle(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," nomangle");
+ if(IsPmCharSetAnsi(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," ansi");
+ if(IsPmCharSetUnicode(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," unicode");
+ if(IsPmCharSetAuto(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," autochar");
+ if(IsPmSupportsLastError(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," lasterr");
+ if(IsPmCallConvWinapi(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," winapi");
+ if(IsPmCallConvCdecl(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," cdecl");
+ if(IsPmCallConvThiscall(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," thiscall");
+ if(IsPmCallConvFastcall(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," fastcall");
+ if(IsPmCallConvStdcall(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," stdcall");
+ if(IsPmBestFitEnabled(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," bestfit:on");
+ if(IsPmBestFitDisabled(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," bestfit:off");
+ if(IsPmThrowOnUnmappableCharEnabled(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," charmaperror:on");
+ if(IsPmThrowOnUnmappableCharDisabled(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," charmaperror:off");
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)-1));
+ return szptr;
+}
+
+void DumpByteArray(__inout __nullterminated char* szString, const BYTE* pBlob, ULONG ulLen, void* GUICookie)
+{
+ ULONG32 ulStrOffset = 0;
+ ULONG32 j = 0;
+ ULONG32 k = 0;
+ ULONG32 m = 0;
+ char sz[256];
+ bool printsz = FALSE;
+ char* szptr = NULL;
+ BYTE byt = 0;
+
+
+ ulStrOffset = (ULONG32) strlen(szString);
+ szptr = &szString[ulStrOffset];
+ if(!pBlob) ulLen = 0;
+ for(j = 0, k=0, m=0; j < ulLen; j++,k++,m++)
+ {
+ if(k == 16)
+ {
+ if(printsz)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT(" // %s"),sz);
+ }
+ printLine(GUICookie,szString);
+ strcpy_s(szString,SZSTRING_SIZE,g_szAsmCodeIndent);
+ for(k=(ULONG32) strlen(szString); k < ulStrOffset; k++) szString[k] = ' ';
+ szString[k] = 0;
+ szptr = &szString[ulStrOffset];
+ k = 0;
+ m = 0;
+ printsz = FALSE;
+ }
+ bool bBreak = FALSE;
+ PAL_CPP_TRY {
+ byt = pBlob[j];
+ }
+ PAL_CPP_CATCH_ALL
+ {
+ strcat_s(szString, SZSTRING_SIZE,ERRORMSG("INVALID DATA ADDRESS"));
+ bBreak = TRUE;
+ }
+ PAL_CPP_ENDTRY;
+
+ if (bBreak)
+ break;
+
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%2.2X ",byt);
+ if(isprint(byt))
+ {
+ if(g_fDumpRTF)
+ {
+ if((byt == '\\')||(byt=='{')||(byt=='}')) sz[m++]='\\';
+ sz[m] = byt;
+ }
+ else if(g_fDumpHTML)
+ {
+ if(byt == '<') { sz[m] = 0; strcat_s(sz,256-m,LTN()); m+=(ULONG32)(strlen(LTN())); }
+ else if(byt == '>') { sz[m] = 0; strcat_s(sz,256-m,GTN()); m+=(ULONG32)(strlen(GTN())); }
+ else sz[m] = byt;
+ }
+ else sz[m] = byt;
+ printsz = TRUE;
+ }
+ else sz[m] = '.';
+ sz[m+1] = 0;
+ }
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),") ");
+ if(printsz)
+ {
+ for(j = k; j < 16; j++) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," ");
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("// %s"),sz);
+ }
+}
+
+mdToken ResolveTypeDefReflectionNotation(IMDInternalImport *pIMDI,
+ LPCUTF8 szNamespace,
+ __inout LPUTF8 szName,
+ mdToken tkEncloser)
+{
+ mdToken tk = 0;
+ LPUTF8 pch = strrchr(szName, '+');
+ if(pch != NULL)
+ {
+ *pch = 0;
+ tkEncloser = ResolveTypeDefReflectionNotation(pIMDI,szNamespace,szName,tkEncloser);
+ szNamespace = "";
+ szName = pch+1;
+ }
+ if(SUCCEEDED(pIMDI->FindTypeDef(szNamespace,szName,tkEncloser,&tk)))
+ return tk;
+ else
+ return 0;
+}
+
+mdToken ResolveTypeRefReflectionNotation(IMDInternalImport *pIMDI,
+ __in __nullterminated const char* szNamespace,
+ __inout __nullterminated char* szName,
+ mdToken tkResScope)
+{
+ mdToken tk = 0;
+ char* pch = strrchr(szName, '+');
+ if(pch != NULL)
+ {
+ *pch = 0;
+ tkResScope = ResolveTypeRefReflectionNotation(pIMDI,szNamespace,szName,tkResScope);
+ szNamespace = "";
+ szName = pch+1;
+ }
+ if(SUCCEEDED(pIMDI->FindTypeRefByName((LPCSTR)szNamespace,(LPCSTR)szName,tkResScope,&tk)))
+ return tk;
+ else
+ return 0;
+}
+mdToken ResolveReflectionNotation(BYTE* dataPtr,
+ unsigned Lstr,
+ IMDInternalImport *pIMDI,
+ void* GUICookie)
+{
+ char* str = new char[Lstr+1];
+ mdToken ret = 0;
+ if(str)
+ {
+ char szNamespaceDefault[] = "";
+ char* szNamespace = szNamespaceDefault;
+ char* szName = str;
+ char* szAssembly = NULL;
+ char szAssemblyMscorlib[] = "mscorlib";
+ char* pch;
+ memcpy(str,dataPtr,Lstr);
+ str[Lstr] = 0;
+ //format: Namespace.Name, Assembly,...
+ pch = strchr(str,',');
+ if(pch)
+ {
+ *pch = 0;
+ for(szAssembly = pch+1; *szAssembly == ' '; szAssembly++);
+ pch = strchr(szAssembly,',');
+ if(pch) *pch = 0;
+ }
+ pch = strrchr(str,'.');
+ if(pch)
+ {
+ *pch = 0;
+ szNamespace = str;
+ szName = pch+1;
+ }
+ if(szAssembly == NULL)
+ {
+ // Look in TypeDefs
+ mdToken tk = ResolveTypeDefReflectionNotation(pIMDI,szNamespace,szName,mdTypeDefNil);
+ if(tk != 0)
+ ret = tk;
+ else
+ // TypeDef not found, try TypeRef from mscorlib
+ szAssembly = szAssemblyMscorlib;
+ }
+ if(szAssembly != NULL)
+ {
+ // Look in TypeRefs
+ // First, identify resolution scope
+ _ASSERTE(*szName);
+ ULONG mAsmRefs = pIMDI->GetCountWithTokenKind(mdtAssemblyRef);
+ if(mAsmRefs)
+ {
+ mdToken tkResScope = 0;
+ mdToken tk=TokenFromRid(mdtAssemblyRef,1), tkmax=TokenFromRid(mdtAssemblyRef,mAsmRefs);
+ LPCSTR szAsmRefName;
+ // these are dummies
+ const void* pPKT, *pHash;
+ ULONG ulPKT,ulHash;
+ AssemblyMetaDataInternal MD;
+ DWORD dwFlags;
+
+ for (;tk <= tkmax; tk++)
+ {
+ if (FAILED(pIMDI->GetAssemblyRefProps(tk,&pPKT,&ulPKT,&szAsmRefName,&MD,&pHash,&ulHash,&dwFlags)))
+ {
+ continue;
+ }
+ if(0==strcmp(szAsmRefName,szAssembly))
+ {
+ tkResScope = tk;
+ break;
+ }
+ }
+ if(tkResScope)
+ {
+ ret = ResolveTypeRefReflectionNotation(pIMDI,szNamespace,szName,tkResScope);
+ }
+ }
+ }
+ }
+ VDELETE(str);
+ return ret;
+}
+
+unsigned UnderlyingTypeOfEnumTypeDef(mdToken tk, IMDInternalImport *pIMDI)
+{
+ HRESULT hr;
+ // make sure it's a TypeDef
+ if(TypeFromToken(tk) != mdtTypeDef) return 0;
+
+ // make sure it's an enum
+ mdToken tkParent;
+ DWORD dwAttr;
+ if (FAILED(pIMDI->GetTypeDefProps(tk,&dwAttr,&tkParent)))
+ {
+ return 0;
+ }
+ if(RidFromToken(tkParent)==0) return 0;
+ LPCSTR szName, szNamespace;
+ switch(TypeFromToken(tkParent))
+ {
+ case mdtTypeDef:
+ if (FAILED(pIMDI->GetNameOfTypeDef(tkParent, &szName, &szNamespace)))
+ {
+ return 0;
+ }
+ break;
+
+ case mdtTypeRef:
+ if (FAILED(pIMDI->GetNameOfTypeRef(tkParent, &szNamespace, &szName)))
+ {
+ return 0;
+ }
+ break;
+
+ default:
+ return 0;
+ }
+
+ if (strcmp(szName,"Enum") != 0 || strcmp(szNamespace,"System") != 0)
+ {
+ // the parent type is not System.Enum so this type has no underlying type
+ return 0;
+ }
+
+ // OK, it's an enum; find its instance field and get its type
+ HENUMInternal hEnum;
+ mdToken tkField;
+ if (FAILED(pIMDI->EnumInit(mdtFieldDef,tk,&hEnum)))
+ {
+ return 0;
+ }
+ while(pIMDI->EnumNext(&hEnum,&tkField))
+ {
+ if (FAILED(pIMDI->GetFieldDefProps(tkField, &dwAttr)))
+ {
+ continue;
+ }
+ if (IsFdStatic(dwAttr))
+ {
+ continue;
+ }
+ PCCOR_SIGNATURE psig;
+ if (FAILED(pIMDI->GetSigOfFieldDef(tkField,(ULONG*)&dwAttr, &psig)))
+ {
+ continue;
+ }
+ pIMDI->EnumClose(&hEnum);
+ return (unsigned) *(psig+1);
+ }
+ // no instance field found -- error!
+ pIMDI->EnumClose(&hEnum);
+ return 0;
+}
+mdToken TypeRefToTypeDef(mdToken tk, IMDInternalImport *pIMDI, IMDInternalImport **ppIMDInew)
+{
+ mdToken tkEncloser = mdTypeDefNil;
+ mdToken tkTypeDef = mdTypeDefNil;
+ *ppIMDInew = NULL;
+
+ // get the resolution scope of TypeRef
+ mdToken tkRS;
+ if (FAILED(pIMDI->GetResolutionScopeOfTypeRef(tk, &tkRS)))
+ {
+ goto AssignAndReturn;
+ }
+ if (TypeFromToken(tkRS) == mdtTypeRef)
+ tkEncloser = TypeRefToTypeDef(tkRS,pIMDI,ppIMDInew);
+ else if (TypeFromToken(tkRS) == mdtAssemblyRef)
+ {
+ *ppIMDInew = g_asmref_import[RidFromToken(tkRS)];
+ if (*ppIMDInew == NULL)
+ {
+ // get that assembly and open IMDInternalImport
+ IMetaDataAssemblyImport* pAssemblyImport;
+ if (FAILED(g_pPubImport->QueryInterface(IID_IMetaDataAssemblyImport, (void**) &pAssemblyImport)))
+ goto AssignAndReturn;
+
+ const void *pPKT, *pHash;
+ ULONG cHash,cName;
+ WCHAR wzName[2048];
+ ASSEMBLYMETADATA md;
+ WCHAR wzLocale[1024];
+ DWORD dwFlags;
+ IUnknown* pIAMDI[64];
+ memset(&md,0,sizeof(ASSEMBLYMETADATA));
+ md.szLocale = wzLocale;
+ md.cbLocale = 1024;
+
+ struct Param
+ {
+ IMetaDataAssemblyImport* pAssemblyImport;
+ WCHAR *wzName;
+ IUnknown **pIAMDI;
+ ULONG cPKT;
+ } param;
+ param.pAssemblyImport = pAssemblyImport;
+ param.wzName = wzName;
+ param.pIAMDI = pIAMDI;
+
+ pAssemblyImport->GetAssemblyRefProps(tkRS,&pPKT,&param.cPKT,wzName,2048,&cName,&md,&pHash,&cHash,&dwFlags);
+
+ PAL_TRY(Param *, pParam, &param) {
+ if(FAILED(pParam->pAssemblyImport->FindAssembliesByName(NULL,NULL,(LPCWSTR)pParam->wzName,pParam->pIAMDI,64,&pParam->cPKT)))
+ pParam->cPKT=0;
+ } PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
+ param.cPKT=0;
+ } PAL_ENDTRY
+
+ pAssemblyImport->Release();
+ if(param.cPKT == 0) goto AssignAndReturn;
+ _ASSERTE(pIAMDI[0] != NULL);
+
+ IUnknown *pUnk;
+ if(FAILED(pIAMDI[0]->QueryInterface(IID_IUnknown, (void**)&pUnk))) goto AssignAndReturn;
+
+#ifdef FEATURE_CORECLR
+ if (FAILED(getMetaDataInternalInterfaceFromPublic(
+ pUnk,
+ IID_IMDInternalImport,
+ (LPVOID *)ppIMDInew)))
+#else
+ if (FAILED(g_pCLRRuntimeHostInternal->GetMetaDataInternalInterfaceFromPublic(
+ pUnk,
+ IID_IMDInternalImport,
+ (LPVOID *)ppIMDInew)))
+#endif
+ {
+ goto AssignAndReturn;
+ }
+ _ASSERTE(*ppIMDInew != NULL);
+ g_asmref_import[RidFromToken(tkRS)] = *ppIMDInew;
+ pUnk->Release();
+ for(cHash=0; cHash<param.cPKT; cHash++)
+ if(pIAMDI[cHash]) pIAMDI[cHash]->Release();
+ }
+ }
+ if (*ppIMDInew != NULL)
+ {
+ LPCSTR szName, szNamespace;
+ if (FAILED(pIMDI->GetNameOfTypeRef(tk, &szNamespace, &szName)))
+ {
+ tkTypeDef = mdTypeDefNil;
+ goto AssignAndReturn;
+ }
+
+ if (FAILED((*ppIMDInew)->FindTypeDef(szNamespace,szName,tkEncloser,&tkTypeDef)))
+ {
+ tkTypeDef = mdTypeDefNil;
+ }
+ }
+AssignAndReturn:
+ return tkTypeDef;
+}
+unsigned UnderlyingTypeOfEnum(mdToken tk, IMDInternalImport *pIMDI)
+{
+ unsigned uRet = 0;
+ unsigned ix = RidFromToken(tk);
+ if(TypeFromToken(tk)==mdtTypeDef)
+ {
+ if(g_enum_td_type[ix] == 0xFF)
+ {
+ g_enum_td_type[ix] = (BYTE)UnderlyingTypeOfEnumTypeDef(tk,pIMDI);
+ }
+ return (unsigned)g_enum_td_type[ix];
+ }
+ else if(TypeFromToken(tk)==mdtTypeRef)
+ {
+ if(g_enum_tr_type[ix] == 0xFF)
+ {
+ IMDInternalImport *pIMDInew = NULL;
+ mdToken tkTypeDef = TypeRefToTypeDef(tk,pIMDI, &pIMDInew);
+ if((RidFromToken(tkTypeDef)!=0)&&(pIMDInew != NULL))
+ {
+ uRet = UnderlyingTypeOfEnumTypeDef(tkTypeDef,pIMDInew);
+ }
+ g_enum_tr_type[ix] = (BYTE)uRet;
+ }
+ return (unsigned)g_enum_tr_type[ix];
+ }
+ else return 0;
+}
+
+/**************************************************************************/
+/* move 'ptr past the exactly one type description */
+
+BYTE* skipType(BYTE* ptr)
+{
+ mdToken tk;
+AGAIN:
+ switch(*ptr++) {
+ case ELEMENT_TYPE_VOID :
+ case ELEMENT_TYPE_BOOLEAN :
+ case ELEMENT_TYPE_CHAR :
+ case ELEMENT_TYPE_I1 :
+ case ELEMENT_TYPE_U1 :
+ case ELEMENT_TYPE_I2 :
+ case ELEMENT_TYPE_U2 :
+ case ELEMENT_TYPE_I4 :
+ case ELEMENT_TYPE_U4 :
+ case ELEMENT_TYPE_I8 :
+ case ELEMENT_TYPE_U8 :
+ case ELEMENT_TYPE_R4 :
+ case ELEMENT_TYPE_R8 :
+ case ELEMENT_TYPE_U :
+ case ELEMENT_TYPE_I :
+ case ELEMENT_TYPE_STRING :
+ case ELEMENT_TYPE_OBJECT :
+ case ELEMENT_TYPE_TYPEDBYREF :
+ case ELEMENT_TYPE_SENTINEL :
+ case SERIALIZATION_TYPE_TYPE :
+ case SERIALIZATION_TYPE_TAGGED_OBJECT :
+ /* do nothing */
+ break;
+
+ case SERIALIZATION_TYPE_ENUM :
+ {
+ unsigned Lstr = CorSigUncompressData((PCCOR_SIGNATURE&)ptr);
+ ptr += Lstr;
+ break;
+ }
+
+ case ELEMENT_TYPE_VALUETYPE :
+ case ELEMENT_TYPE_CLASS :
+ ptr += CorSigUncompressToken(ptr, &tk);
+ break;
+
+ case ELEMENT_TYPE_CMOD_REQD :
+ case ELEMENT_TYPE_CMOD_OPT :
+ ptr += CorSigUncompressToken(ptr, &tk);
+ goto AGAIN;
+
+ case ELEMENT_TYPE_ARRAY :
+ {
+ ptr = skipType(ptr); // element Type
+ unsigned rank = CorSigUncompressData((PCCOR_SIGNATURE&) ptr);
+ if (rank != 0)
+ {
+ unsigned numSizes = CorSigUncompressData((PCCOR_SIGNATURE&) ptr);
+ while(numSizes > 0)
+ {
+ CorSigUncompressData((PCCOR_SIGNATURE&) ptr);
+ --numSizes;
+ }
+ unsigned numLowBounds = CorSigUncompressData((PCCOR_SIGNATURE&) ptr);
+ while(numLowBounds > 0)
+ {
+ CorSigUncompressData((PCCOR_SIGNATURE&) ptr);
+ --numLowBounds;
+ }
+ }
+ }
+ break;
+
+ // Modifiers or depedant types
+ case ELEMENT_TYPE_PINNED :
+ case ELEMENT_TYPE_PTR :
+ case ELEMENT_TYPE_BYREF :
+ case ELEMENT_TYPE_SZARRAY :
+ // tail recursion optimization
+ // ptr = skipType(ptr, fFixupType);
+ // break
+ goto AGAIN;
+
+ case ELEMENT_TYPE_VAR:
+ case ELEMENT_TYPE_MVAR:
+ CorSigUncompressData((PCCOR_SIGNATURE&) ptr); // bound
+ break;
+
+ case ELEMENT_TYPE_FNPTR:
+ {
+ CorSigUncompressData((PCCOR_SIGNATURE&) ptr); // calling convention
+ unsigned argCnt = CorSigUncompressData((PCCOR_SIGNATURE&) ptr); // arg count
+ ptr = skipType(ptr); // return type
+ while(argCnt > 0)
+ {
+ ptr = skipType(ptr);
+ --argCnt;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_GENERICINST:
+ {
+ ptr = skipType(ptr); // type constructor
+ unsigned argCnt = CorSigUncompressData((PCCOR_SIGNATURE&)ptr); // arg count
+ while(argCnt > 0) {
+ ptr = skipType(ptr);
+ --argCnt;
+ }
+ }
+ break;
+
+ default:
+ case ELEMENT_TYPE_END :
+ _ASSERTE(!"Unknown Type");
+ break;
+ }
+ return(ptr);
+}
+
+
+#ifdef _PREFAST_
+#pragma warning(push)
+#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
+#endif
+BYTE* PrettyPrintCABlobValue(PCCOR_SIGNATURE &typePtr,
+ BYTE* dataPtr,
+ BYTE* dataEnd,
+ CQuickBytes* out,
+ IMDInternalImport *pIMDI,
+ void* GUICookie)
+{
+ char str[64];
+ char appendix[64];
+ int typ;
+ BOOL Reiterate;
+ BOOL CloseParenthesis;
+ unsigned numElements = 1;
+ unsigned n,Lstr;
+ unsigned underType;
+ mdToken tk;
+
+ appendix[0] = 0;
+ do {
+ if(dataPtr >= dataEnd)
+ {
+ _ASSERTE(!"CA blob too short");
+ return FALSE;
+ }
+ Reiterate = FALSE;
+ CloseParenthesis = TRUE;
+ switch(typ = *typePtr++) {
+ case ELEMENT_TYPE_VOID :
+ return NULL;
+ case ELEMENT_TYPE_BOOLEAN :
+ appendStr(out,KEYWORD("bool"));
+ appendStr(out,appendix);
+ appendStr(out,"(");
+ for(n=0; n < numElements; n++)
+ {
+ if(n) appendStr(out," ");
+ appendStr(out,(*dataPtr)? KEYWORD("true"):KEYWORD("false"));
+ dataPtr++;
+ }
+ break;
+ case ELEMENT_TYPE_CHAR :
+ appendStr(out,KEYWORD("char"));
+ appendStr(out,appendix);
+ appendStr(out,"(");
+ for(n=0; n < numElements; n++)
+ {
+ if(n) appendStr(out," ");
+ sprintf_s(str,64,"0x%4.4X",(WORD)GET_UNALIGNED_VAL16(dataPtr));
+ appendStr(out,str);
+ dataPtr += 2;
+ }
+ break;
+ case ELEMENT_TYPE_I1 :
+ appendStr(out,KEYWORD("int8"));
+ appendStr(out,appendix);
+ appendStr(out,"(");
+ for(n=0; n < numElements; n++)
+ {
+ if(n) appendStr(out," ");
+ sprintf_s(str,64,"%d",*((char*)dataPtr));
+ appendStr(out,str);
+ dataPtr ++;
+ }
+ break;
+ case ELEMENT_TYPE_U1 :
+ appendStr(out,KEYWORD("uint8"));
+ appendStr(out,appendix);
+ appendStr(out,"(");
+ for(n=0; n < numElements; n++)
+ {
+ if(n) appendStr(out," ");
+ sprintf_s(str,64,"%d",*dataPtr);
+ appendStr(out,str);
+ dataPtr ++;
+ }
+ break;
+ case ELEMENT_TYPE_I2 :
+ appendStr(out,KEYWORD("int16"));
+ appendStr(out,appendix);
+ appendStr(out,"(");
+ for(n=0; n < numElements; n++)
+ {
+ if(n) appendStr(out," ");
+ sprintf_s(str,64,"%d",GET_UNALIGNED_VAL16(dataPtr));
+ appendStr(out,str);
+ dataPtr +=2;
+ }
+ break;
+ case ELEMENT_TYPE_U2 :
+ appendStr(out,KEYWORD("uint16"));
+ appendStr(out,appendix);
+ appendStr(out,"(");
+ for(n=0; n < numElements; n++)
+ {
+ if(n) appendStr(out," ");
+ sprintf_s(str,64,"%d",(WORD)GET_UNALIGNED_VAL16(dataPtr));
+ appendStr(out,str);
+ dataPtr +=2;
+ }
+ break;
+ case ELEMENT_TYPE_I4 :
+ appendStr(out,KEYWORD("int32"));
+ appendStr(out,appendix);
+ appendStr(out,"(");
+ for(n=0; n < numElements; n++)
+ {
+ if(n) appendStr(out," ");
+ sprintf_s(str,64,"%d",GET_UNALIGNED_VAL32(dataPtr));
+ appendStr(out,str);
+ dataPtr +=4;
+ }
+ break;
+ case ELEMENT_TYPE_U4 :
+ appendStr(out,KEYWORD("uint32"));
+ appendStr(out,appendix);
+ appendStr(out,"(");
+ for(n=0; n < numElements; n++)
+ {
+ if(n) appendStr(out," ");
+ sprintf_s(str,64,"%d",(unsigned)GET_UNALIGNED_VAL32(dataPtr));
+ appendStr(out,str);
+ dataPtr +=4;
+ }
+ break;
+ case ELEMENT_TYPE_I8 :
+ appendStr(out,KEYWORD("int64"));
+ appendStr(out,appendix);
+ appendStr(out,"(");
+ for(n=0; n < numElements; n++)
+ {
+ if(n) appendStr(out," ");
+ sprintf_s(str,64,"%I64d",GET_UNALIGNED_VAL64(dataPtr));
+ appendStr(out,str);
+ dataPtr +=8;
+ }
+ break;
+ case ELEMENT_TYPE_U8 :
+ appendStr(out,KEYWORD("uint64"));
+ appendStr(out,appendix);
+ appendStr(out,"(");
+ for(n=0; n < numElements; n++)
+ {
+ if(n) appendStr(out," ");
+ sprintf_s(str,64,"%I64d",(ULONGLONG)GET_UNALIGNED_VAL64(dataPtr));
+ appendStr(out,str);
+ dataPtr +=8;
+ }
+ break;
+ case ELEMENT_TYPE_R4 :
+ appendStr(out,KEYWORD("float32"));
+ appendStr(out,appendix);
+ appendStr(out,"(");
+ for(n=0; n < numElements; n++)
+ {
+ if(n) appendStr(out," ");
+ _gcvt_s(str,64,*((float*)dataPtr), 8);
+ float df = (float)atof(str);
+ // Must compare as underlying bytes, not floating point otherwise optmizier will
+ // try to enregister and comapre 80-bit precision number with 32-bit precision number!!!!
+ if((*(ULONG*)&df != (ULONG)GET_UNALIGNED_VAL32(dataPtr))||IsSpecialNumber(str))
+ sprintf_s(str, 64,"0x%08X",(ULONG)GET_UNALIGNED_VAL32(dataPtr));
+ appendStr(out,str);
+ dataPtr +=4;
+ }
+ break;
+
+ case ELEMENT_TYPE_R8 :
+ appendStr(out,KEYWORD("float64"));
+ appendStr(out,appendix);
+ appendStr(out,"(");
+ for(n=0; n < numElements; n++)
+ {
+ if(n) appendStr(out," ");
+ char *pch;
+ _gcvt_s(str,64,*((double*)dataPtr), 17);
+ double df = strtod(str, &pch);
+ // Must compare as underlying bytes, not floating point otherwise optmizier will
+ // try to enregister and comapre 80-bit precision number with 64-bit precision number!!!!
+ if((*(ULONGLONG*)&df != (ULONGLONG)GET_UNALIGNED_VAL64(dataPtr))||IsSpecialNumber(str))
+ sprintf_s(str, 64, "0x%I64X",(ULONGLONG)GET_UNALIGNED_VAL64(dataPtr));
+ appendStr(out,str);
+ dataPtr +=8;
+ }
+ break;
+ case ELEMENT_TYPE_U :
+ case ELEMENT_TYPE_I :
+ return NULL;
+
+ case ELEMENT_TYPE_OBJECT :
+ case SERIALIZATION_TYPE_TAGGED_OBJECT:
+ appendStr(out,KEYWORD("object"));
+ appendStr(out,appendix);
+ appendStr(out,"(");
+ for(n=0; n < numElements; n++)
+ {
+ BYTE* dataPtr1 = skipType(dataPtr);
+ if(n) appendStr(out," ");
+
+ dataPtr = PrettyPrintCABlobValue((PCCOR_SIGNATURE&)dataPtr, dataPtr1, dataEnd, out, pIMDI,GUICookie);
+ if (dataPtr == NULL) return NULL;
+ }
+ break;
+ case ELEMENT_TYPE_STRING :
+ appendStr(out,KEYWORD("string"));
+ appendStr(out,appendix);
+ appendStr(out,"(");
+ for(n=0; n < numElements; n++)
+ {
+ if(n) appendStr(out," ");
+ if(*dataPtr == 0xFF)
+ {
+ appendStr(out,KEYWORD("nullref"));
+ Lstr = 1;
+ }
+ else
+ {
+ appendStr(out,"'");
+ Lstr = CorSigUncompressData((PCCOR_SIGNATURE&)dataPtr);
+ if(dataPtr + Lstr > dataEnd) return NULL;
+ appendStr(out,UnquotedProperName((char*)dataPtr,Lstr));
+ appendStr(out,"'");
+ }
+ dataPtr += Lstr;
+ }
+ break;
+ case ELEMENT_TYPE_CLASS :
+ typePtr += CorSigUncompressToken(typePtr, &tk); //skip the following token
+ case SERIALIZATION_TYPE_TYPE :
+ appendStr(out,KEYWORD("type"));
+ appendStr(out,appendix);
+ appendStr(out,"(");
+ for(n=0; n < numElements; n++)
+ {
+ if(n) appendStr(out," ");
+ if(*dataPtr == 0xFF)
+ {
+ appendStr(out,KEYWORD("nullref"));
+ Lstr = 1;
+ }
+ else
+ {
+ Lstr = CorSigUncompressData((PCCOR_SIGNATURE&)dataPtr);
+ if(dataPtr + Lstr > dataEnd) return NULL;
+ tk = ResolveReflectionNotation(dataPtr,Lstr,pIMDI,GUICookie);
+ if(IsNilToken(tk))
+ {
+ appendStr(out,KEYWORD("class "));
+ appendStr(out,"'");
+ appendStr(out,UnquotedProperName((char*)dataPtr,Lstr));
+ appendStr(out,"'");
+ }
+ else
+ {
+ PrettyPrintClass(out, tk, pIMDI);
+ }
+ }
+ dataPtr += Lstr;
+ }
+ break;
+
+
+ case ELEMENT_TYPE_VALUETYPE :
+ typePtr += CorSigUncompressToken(typePtr, &tk);
+ _ASSERTE(pIMDI->IsValidToken(tk));
+ goto GetUTSize;
+
+ case SERIALIZATION_TYPE_ENUM :
+ Lstr = CorSigUncompressData((PCCOR_SIGNATURE&)typePtr);
+ tk = ResolveReflectionNotation((BYTE*)typePtr,Lstr,pIMDI,GUICookie);
+ /*
+ if(IsNilToken(tk))
+ {
+ _ASSERTE(!"Failed to resolve Reflection notation for S_T_ENUM");
+ return NULL;
+ }
+ */
+ typePtr += Lstr;
+
+ GetUTSize:
+ underType = UnderlyingTypeOfEnum(tk, pIMDI);
+ if(underType == 0)
+ {
+ // try to figure out the underlying type by its size
+ switch(dataEnd - dataPtr)
+ {
+ case 1: // bool
+ underType = ELEMENT_TYPE_BOOLEAN;
+ break;
+ case 2: // int16
+ underType = ELEMENT_TYPE_I2;
+ break;
+ case 4: // int32
+ underType = ELEMENT_TYPE_I4;
+ break;
+ case 8: // int64
+ underType = ELEMENT_TYPE_I8;
+ break;
+ default:
+ return NULL;
+ }
+ //_ASSERTE(!"Failed to find underlying type for S_T_ENUM");
+ }
+ {
+ PCCOR_SIGNATURE ps = (PCCOR_SIGNATURE)&underType;
+ dataPtr = PrettyPrintCABlobValue(ps, dataPtr, dataEnd, out, pIMDI,GUICookie);
+ }
+ CloseParenthesis = FALSE;
+ break;
+
+
+ case ELEMENT_TYPE_SZARRAY :
+ numElements *= (unsigned)GET_UNALIGNED_VAL32(dataPtr);
+ Reiterate = TRUE;
+ sprintf_s(appendix,64,"[%d]",numElements);
+ if(numElements == 0xFFFFFFFF)
+ numElements = 0;
+ dataPtr += 4;
+ break;
+
+ case ELEMENT_TYPE_ARRAY :
+ case ELEMENT_TYPE_VAR :
+ case ELEMENT_TYPE_MVAR :
+ case ELEMENT_TYPE_FNPTR :
+ case ELEMENT_TYPE_GENERICINST :
+ case ELEMENT_TYPE_TYPEDBYREF :
+
+#ifdef LOGGING
+ case ELEMENT_TYPE_INTERNAL :
+#endif // LOGGING
+ return NULL;
+
+
+ // Modifiers or depedent types
+ case ELEMENT_TYPE_CMOD_OPT :
+ case ELEMENT_TYPE_CMOD_REQD :
+ case ELEMENT_TYPE_PINNED :
+ Reiterate = TRUE;
+ break;
+
+ case ELEMENT_TYPE_PTR :
+ case ELEMENT_TYPE_BYREF :
+ return NULL;
+
+ default:
+ case ELEMENT_TYPE_SENTINEL :
+ case ELEMENT_TYPE_END :
+ _ASSERTE(!"Unknown Type");
+ return NULL;
+ } // end switch
+ } while(Reiterate);
+ if(CloseParenthesis) appendStr(out,")");
+ return dataPtr;
+}
+#ifdef _PREFAST_
+#pragma warning(pop)
+#endif
+
+BOOL PrettyPrintCustomAttributeNVPairs(unsigned nPairs, BYTE* dataPtr, BYTE* dataEnd, CQuickBytes* out, void* GUICookie)
+{
+ IMDInternalImport *pIMDI = g_pImport; // ptr to IMDInternalImport class with ComSig
+ while(dataPtr < dataEnd)
+ {
+ // field or property?
+ switch(*dataPtr)
+ {
+ case SERIALIZATION_TYPE_FIELD:
+ appendStr(out,KEYWORD("field "));
+ break;
+ case SERIALIZATION_TYPE_PROPERTY:
+ appendStr(out,KEYWORD("property "));
+ break;
+ default:
+ _ASSERTE(!"Invalid code of name/val pair in CA blob");
+ return FALSE;
+ }
+ dataPtr++;
+ if(dataPtr >= dataEnd)
+ {
+ _ASSERTE(!"CA blob too short");
+ return FALSE;
+ }
+ // type of the field/property
+ PCCOR_SIGNATURE dataTypePtr = (PCCOR_SIGNATURE)dataPtr;
+ const char* szAppend = "";
+ if(*dataPtr == ELEMENT_TYPE_SZARRAY) // Only SZARRAY modifier can occur in ser.type
+ {
+ szAppend = "[]";
+ dataPtr++;
+ }
+ if(*dataPtr == SERIALIZATION_TYPE_TYPE)
+ {
+ appendStr(out,KEYWORD("type"));
+ dataPtr++;
+ }
+ else if(*dataPtr == SERIALIZATION_TYPE_TAGGED_OBJECT)
+ {
+ appendStr(out,KEYWORD("object"));
+ dataPtr++;
+ }
+ else if(*dataPtr == SERIALIZATION_TYPE_ENUM)
+ {
+ appendStr(out,KEYWORD("enum "));
+ dataPtr++;
+ unsigned Lstr = CorSigUncompressData((PCCOR_SIGNATURE&)dataPtr);
+ if(dataPtr + Lstr > dataEnd) return FALSE;
+ mdToken tk = ResolveReflectionNotation(dataPtr,Lstr,pIMDI,GUICookie);
+ if(IsNilToken(tk))
+ {
+ appendStr(out,KEYWORD("class "));
+ appendStr(out,"'");
+ appendStr(out,UnquotedProperName((char*)dataPtr,Lstr));
+ appendStr(out,"'");
+ }
+ else
+ {
+ PrettyPrintClass(out, tk, pIMDI);
+ }
+ dataPtr += Lstr;
+ }
+ else
+ {
+ szAppend = "";
+ dataPtr = (BYTE*)PrettyPrintType(dataTypePtr, out, pIMDI);
+ }
+ if(*szAppend != 0)
+ appendStr(out,szAppend);
+ if(dataPtr >= dataEnd)
+ {
+ _ASSERTE(!"CA blob too short");
+ return FALSE;
+ }
+ // name of the field/property
+ unsigned Lstr = CorSigUncompressData((PCCOR_SIGNATURE&)dataPtr);
+ if(dataPtr + Lstr > dataEnd) return FALSE;
+ appendStr(out," '");
+ appendStr(out,UnquotedProperName((char*)dataPtr,Lstr));
+ appendStr(out,"' = ");
+ dataPtr += Lstr;
+ if(dataPtr >= dataEnd)
+ {
+ _ASSERTE(!"CA blob too short");
+ return FALSE;
+ }
+ // value of the field/property
+ dataPtr = PrettyPrintCABlobValue(dataTypePtr, dataPtr, dataEnd, out, pIMDI,GUICookie);
+ if(NULL == dataPtr) return FALSE;
+ appendStr(out,"\n");
+
+ nPairs--;
+ }
+ _ASSERTE(nPairs == 0);
+ return TRUE;
+}
+BOOL PrettyPrintCustomAttributeBlob(mdToken tkType, BYTE* pBlob, ULONG ulLen, void* GUICookie, __inout __nullterminated char* szString)
+{
+ HRESULT hr;
+ char* initszptr = szString + strlen(szString);
+ PCCOR_SIGNATURE typePtr; // type to convert,
+ ULONG typeLen; // the lenght of 'typePtr'
+ CHECK_LOCAL_STATIC_VAR(static CQuickBytes out); // where to put the pretty printed string
+
+ IMDInternalImport *pIMDI = g_pImport; // ptr to IMDInternalImport class with ComSig
+ unsigned numArgs = 0;
+ unsigned numTyArgs = 0;
+ PCCOR_SIGNATURE typeEnd;
+ unsigned callConv;
+ BYTE* dataPtr = pBlob;
+ BYTE* dataEnd = dataPtr + ulLen;
+ WORD wNumNVPairs = 0;
+ unsigned numElements = 0;
+
+ if(TypeFromToken(tkType) == mdtMemberRef)
+ {
+ const char *szName_Ignore;
+ if (FAILED(pIMDI->GetNameAndSigOfMemberRef(tkType,&typePtr,&typeLen, &szName_Ignore)))
+ {
+ return FALSE;
+ }
+ }
+ else if(TypeFromToken(tkType) == mdtMethodDef)
+ {
+ if (FAILED(pIMDI->GetSigOfMethodDef(tkType, &typeLen, &typePtr)))
+ {
+ return FALSE;
+ }
+ }
+ else
+ return FALSE;
+ typeEnd = typePtr + typeLen;
+
+ callConv = CorSigUncompressData(typePtr);
+
+ if (callConv & IMAGE_CEE_CS_CALLCONV_GENERIC)
+ {
+ numTyArgs = CorSigUncompressData(typePtr);
+ return FALSE; // leave generic instantiations for later
+ }
+ numElements = numArgs = CorSigUncompressData(typePtr);
+ out.Shrink(0);
+ if (!isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_GENERICINST))
+ {
+ // skip return type
+ typePtr = PrettyPrintType(typePtr, &out, pIMDI);
+ out.Shrink(0);
+ }
+ appendStr(&out," = {");
+ dataPtr += 2; // skip blob prolog 0x0001
+ // dump the arguments
+ while(typePtr < typeEnd)
+ {
+ if (*typePtr == ELEMENT_TYPE_SENTINEL)
+ {
+ typePtr++;
+ }
+ else
+ {
+ if (numArgs <= 0)
+ break;
+ dataPtr = PrettyPrintCABlobValue(typePtr, dataPtr, dataEnd-2, &out, pIMDI,GUICookie);
+ if(NULL == dataPtr) return FALSE;
+ appendStr(&out,"\n");
+ --numArgs;
+ }
+ }
+ _ASSERTE(numArgs == 0);
+ wNumNVPairs = (WORD)GET_UNALIGNED_VAL16(dataPtr);
+ dataPtr+=2;
+ numElements += wNumNVPairs;
+ // arguments done, now to field/property name-val pairs
+
+ if(!PrettyPrintCustomAttributeNVPairs((unsigned) wNumNVPairs, dataPtr, dataEnd, &out, GUICookie))
+ return FALSE;
+
+ {
+ char* sz = asString(&out);
+ char* ch = sz;
+ char* szbl;
+ while((ch = strchr(ch,'\n')))
+ {
+ *ch = 0;
+ ch++;
+ }
+ // if the string is too long already, begin on next line
+ if((initszptr - szString) > 80)
+ {
+ printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"%s ",g_szAsmCodeIndent);
+ initszptr = &szString[strlen(szString)];
+ }
+ sprintf_s(initszptr,SZSTRING_REMAINING_SIZE(initszptr), "%s", sz);
+ initszptr += 4; // to compensate for " = {"
+ szbl = szString + strlen(g_szAsmCodeIndent);
+ for(unsigned n = 1; n < numElements; n++)
+ {
+ printLine(GUICookie, szString);
+ sz = sz + strlen(sz) + 1;
+ for(ch = szbl; ch < initszptr; ch++) *ch = ' ';
+ sprintf_s(initszptr,SZSTRING_REMAINING_SIZE(initszptr), "%s", sz);
+ }
+ }
+ strcat_s(initszptr, SZSTRING_REMAINING_SIZE(initszptr),"}");
+ if(g_fShowBytes)
+ {
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," // ");
+ sprintf_s(szString,SZSTRING_SIZE,"%s = ( ",g_szAsmCodeIndent);
+ DumpByteArray(szString,pBlob,ulLen,GUICookie);
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-8] = 0;
+ }
+ return TRUE;
+}
+
+void DumpCustomAttributeProps(mdToken tkCA, mdToken tkType, mdToken tkOwner, BYTE* pBlob, ULONG ulLen, void *GUICookie, bool bWithOwner)
+{
+ HRESULT hr;
+ char* szptr = &szString[0];
+ BOOL fCommentItOut = FALSE;
+ if((TypeFromToken(tkType) == mdtMemberRef)||(TypeFromToken(tkType) == mdtMethodDef))
+ {
+ mdToken tkParent;
+ const char * pszClassName = NULL;
+ const char * pszNamespace = NULL;
+ if (TypeFromToken(tkType) == mdtMemberRef)
+ {
+ if (FAILED(g_pImport->GetParentOfMemberRef(tkType, &tkParent)))
+ {
+ szptr += sprintf_s(szptr, SZSTRING_REMAINING_SIZE(szptr), "Invalid MemberRef %08X record ", tkType);
+ return;
+ }
+ }
+ else
+ {
+ if (FAILED(g_pImport->GetParentToken(tkType, &tkParent)))
+ {
+ szptr += sprintf_s(szptr, SZSTRING_REMAINING_SIZE(szptr), "Invalid token %08X ", tkType);
+ return;
+ }
+ }
+
+ REGISTER_REF(tkOwner,tkType); // owner of the CA references the class amd method
+ REGISTER_REF(tkOwner,tkParent);
+
+ if (TypeFromToken(tkParent) == mdtTypeDef)
+ {
+ if (FAILED(g_pImport->GetNameOfTypeDef(tkParent, &pszClassName, &pszNamespace)))
+ {
+ szptr += sprintf_s(szptr, SZSTRING_REMAINING_SIZE(szptr), "Invalid TypeDef %08X record ", tkParent);
+ return;
+ }
+ }
+ else if (TypeFromToken(tkParent) == mdtTypeRef)
+ {
+ if (FAILED(g_pImport->GetNameOfTypeRef(tkParent, &pszNamespace, &pszClassName)))
+ {
+ szptr += sprintf_s(szptr, SZSTRING_REMAINING_SIZE(szptr), "Invalid TypeRef %08X record ", tkParent);
+ return;
+ }
+ }
+ if(pszClassName && pszNamespace
+ && (strcmp(pszNamespace,"System.Diagnostics") == 0)
+ && (strcmp(pszClassName,"DebuggableAttribute") == 0)) fCommentItOut = TRUE;
+
+
+ }
+ if(fCommentItOut)
+ {
+ printLine(GUICookie,COMMENT((char*)0)); // start multiline comment
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_AUTOCA),g_szAsmCodeIndent);
+ printLine(GUICookie, szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH,"// ");
+ }
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".custom"));
+ if(bWithOwner)
+ {
+ if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),tkCA);
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(");
+ switch(TypeFromToken(tkOwner))
+ {
+ case mdtTypeDef :
+ case mdtTypeRef :
+ case mdtTypeSpec:
+ PrettyPrintToken(szString, tkOwner, g_pImport,GUICookie,0);
+ break;
+
+ case mdtMemberRef:
+ {
+ PCCOR_SIGNATURE typePtr;
+ const char* pszMemberName;
+ ULONG cComSig;
+
+ if (FAILED(g_pImport->GetNameAndSigOfMemberRef(
+ tkOwner,
+ &typePtr,
+ &cComSig,
+ &pszMemberName)))
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"ERROR ");
+ break;
+ }
+ unsigned callConv = CorSigUncompressData(typePtr);
+
+ if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD))
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("field "));
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("method "));
+ PrettyPrintToken(szString, tkOwner, g_pImport,GUICookie,0);
+ }
+ break;
+
+ case mdtMethodDef:
+ szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), KEYWORD("method "));
+ PrettyPrintToken(szString, tkOwner, g_pImport,GUICookie,0);
+ break;
+
+ default :
+ strcat_s(szptr, SZSTRING_REMAINING_SIZE(szptr),ERRORMSG("UNKNOWN_OWNER"));
+ break;
+ }
+ szptr = &szString[strlen(szString)];
+ if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),tkOwner);
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),") ");
+ }
+ else
+ {
+ if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X:%08X*/ "),tkCA,tkType);
+ }
+ switch(TypeFromToken(tkType))
+ {
+ case mdtTypeDef :
+ case mdtTypeRef :
+ case mdtMemberRef:
+ case mdtMethodDef:
+ PrettyPrintToken(szString, tkType, g_pImport,GUICookie,0);
+ break;
+
+ default :
+ strcat_s(szString, SZSTRING_SIZE,ERRORMSG("UNNAMED_CUSTOM_ATTR"));
+ break;
+ }
+ szptr = &szString[strlen(szString)];
+
+ if(pBlob && ulLen)
+ {
+ if(!g_fCAVerbal || !PrettyPrintCustomAttributeBlob(tkType, pBlob, ulLen, GUICookie, szString))
+ {
+ sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = ( ");
+ DumpByteArray(szString,pBlob,ulLen,GUICookie);
+ }
+ }
+ printLine(GUICookie, szString);
+ if(fCommentItOut)
+ {
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-4] = 0;
+ printLine(GUICookie,COMMENT((char*)-1)); // end multiline comment
+ }
+}
+
+void DumpCustomAttribute(mdCustomAttribute tkCA, void *GUICookie, bool bWithOwner)
+{
+ mdToken tkType;
+ BYTE* pBlob=NULL;
+ ULONG ulLen=0;
+ mdToken tkOwner;
+ static mdToken tkMod = 0xFFFFFFFF;
+
+ _ASSERTE((TypeFromToken(tkCA)==mdtCustomAttribute)&&(RidFromToken(tkCA)>0));
+ _ASSERTE(RidFromToken(tkCA) <= g_uNCA);
+ if(tkMod == 0xFFFFFFFF) tkMod = g_pImport->GetModuleFromScope();
+
+ // can't use InternalImport here: need the tkOwner
+ if (FAILED(g_pPubImport->GetCustomAttributeProps( // S_OK or error.
+ tkCA, // [IN] CustomValue token.
+ &tkOwner, // [OUT, OPTIONAL] Object token.
+ &tkType, // [OUT, OPTIONAL] Put TypeDef/TypeRef token here.
+ (const void **)&pBlob, // [OUT, OPTIONAL] Put pointer to data here.
+ &ulLen))) // [OUT, OPTIONAL] Put size of date here.
+ {
+ return;
+ }
+
+ if(!RidFromToken(tkOwner)) return;
+
+ DWORD i;
+ for(i = 0; i < g_NumTypedefs; i++)
+ {
+ TypeDefDescr* pTDD = &((*g_typedefs)[i]);
+ if(TypeFromToken(pTDD->tkTypeSpec) == mdtCustomAttribute)
+ {
+ mdToken tkTypeTD;
+ mdToken tkOwnerTD;
+ BYTE* pBlobTD=NULL;
+ ULONG uLenTD=0;
+ tkTypeTD = GET_UNALIGNED_VAL32(pTDD->psig);
+ if(tkTypeTD != tkType) continue;
+
+ tkOwnerTD = GET_UNALIGNED_VAL32(pTDD->psig + sizeof(mdToken));
+ if(pTDD->cb > 2*sizeof(mdToken))
+ {
+ pBlobTD = (BYTE*)pTDD->psig + 2*sizeof(mdToken);
+ uLenTD = pTDD->cb - 2*sizeof(mdToken);
+ }
+ if(uLenTD != ulLen) continue;
+ if(memcmp(pBlobTD,pBlob,ulLen) != 0) continue;
+ char* szptr = &szString[0];
+ szString[0] = 0;
+ szptr += sprintf_s(szString,SZSTRING_SIZE,"%s%s", g_szAsmCodeIndent,JUMPPT(ProperName(pTDD->szName),pTDD->tkSelf));
+ if(g_fDumpTokens)
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),tkCA);
+ printLine(GUICookie,szString);
+ break;
+ }
+ }
+ if(i >= g_NumTypedefs)
+ DumpCustomAttributeProps(tkCA,tkType,tkOwner,pBlob,ulLen,GUICookie,bWithOwner);
+ _ASSERTE(g_rchCA);
+ _ASSERTE(RidFromToken(tkCA) <= g_uNCA);
+ g_rchCA[RidFromToken(tkCA)] = 1;
+}
+
+void DumpCustomAttributes(mdToken tkOwner, void *GUICookie)
+{
+ if (g_fShowCA)
+ {
+ HENUMInternal hEnum;
+ mdCustomAttribute tkCA;
+
+ if (FAILED(g_pImport->EnumInit(mdtCustomAttribute, tkOwner,&hEnum)))
+ {
+ return;
+ }
+ while(g_pImport->EnumNext(&hEnum,&tkCA) && RidFromToken(tkCA))
+ {
+ DumpCustomAttribute(tkCA,GUICookie,false);
+ }
+ g_pImport->EnumClose( &hEnum);
+ }
+}
+
+void DumpDefaultValue(mdToken tok, __inout __nullterminated char* szString, void* GUICookie)
+{
+ MDDefaultValue MDDV;
+ char* szptr = &szString[strlen(szString)];
+
+ if (FAILED(g_pImport->GetDefaultValue(tok, &MDDV)))
+ {
+ szptr += sprintf_s(szptr, SZSTRING_REMAINING_SIZE(szptr), ERRORMSG(" /* Invalid default value for %08X: */"), tok);
+ return;
+ }
+ switch(MDDV.m_bType)
+ {
+ case ELEMENT_TYPE_VOID:
+ strcat_s(szString, SZSTRING_SIZE," /* NO CORRESPONDING RECORD IN CONSTANTS TABLE */");
+ break;
+ case ELEMENT_TYPE_I1:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(0x%02X)",KEYWORD("int8"),MDDV.m_byteValue);
+ break;
+ case ELEMENT_TYPE_U1:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(0x%02X)",KEYWORD("uint8"),MDDV.m_byteValue);
+ break;
+ case ELEMENT_TYPE_I2:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(0x%04X)",KEYWORD("int16"),MDDV.m_usValue);
+ break;
+ case ELEMENT_TYPE_U2:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(0x%04X)",KEYWORD("uint16"),MDDV.m_usValue);
+ break;
+ case ELEMENT_TYPE_I4:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(0x%08X)",KEYWORD("int32"),MDDV.m_ulValue);
+ break;
+ case ELEMENT_TYPE_U4:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(0x%08X)",KEYWORD("uint32"),MDDV.m_ulValue);
+ break;
+ case ELEMENT_TYPE_CHAR:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(0x%04X)",KEYWORD("char"),MDDV.m_usValue);
+ break;
+ case ELEMENT_TYPE_BOOLEAN:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s",KEYWORD("bool"));
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(%s)", KEYWORD((char *)(MDDV.m_byteValue ? "true" : "false")));
+ break;
+ case ELEMENT_TYPE_I8:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(0x%I64X)",KEYWORD("int64"),MDDV.m_ullValue);
+ break;
+ case ELEMENT_TYPE_U8:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(0x%I64X)",KEYWORD("uint64"),MDDV.m_ullValue);
+ break;
+ case ELEMENT_TYPE_R4:
+ {
+ char szf[32];
+ _gcvt_s(szf,32,MDDV.m_fltValue, 8);
+ float df = (float)atof(szf);
+ // Must compare as underlying bytes, not floating point otherwise optmizier will
+ // try to enregister and comapre 80-bit precision number with 32-bit precision number!!!!
+ if((*(ULONG*)&df == MDDV.m_ulValue)&&!IsSpecialNumber(szf))
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(%s)",KEYWORD("float32"),szf);
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), " = %s(0x%08X)",KEYWORD("float32"),MDDV.m_ulValue);
+
+ }
+ break;
+ case ELEMENT_TYPE_R8:
+ {
+ char szf[32], *pch;
+ _gcvt_s(szf,32,MDDV.m_dblValue, 17);
+ double df = strtod(szf, &pch); //atof(szf);
+ szf[31]=0;
+ // Must compare as underlying bytes, not floating point otherwise optmizier will
+ // try to enregister and comapre 80-bit precision number with 64-bit precision number!!!!
+ if((*(ULONGLONG*)&df == MDDV.m_ullValue)&&!IsSpecialNumber(szf))
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(%s)",KEYWORD("float64"),szf);
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), " = %s(0x%I64X) // %s",KEYWORD("float64"),MDDV.m_ullValue,szf);
+ }
+ break;
+
+ case ELEMENT_TYPE_STRING:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = ");
+ PAL_CPP_TRY {
+ szptr = DumpUnicodeString(GUICookie,szString,(WCHAR*)MDDV.m_wzValue,MDDV.m_cbSize/sizeof(WCHAR));
+ } PAL_CPP_CATCH_ALL {
+ strcat_s(szString, SZSTRING_SIZE,ERRORMSG("INVALID DATA ADDRESS"));
+ } PAL_CPP_ENDTRY;
+ break;
+
+ case ELEMENT_TYPE_CLASS:
+ if(MDDV.m_wzValue==NULL)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s",KEYWORD("nullref"));
+ break;
+ }
+ //else fall thru to default case, to report the error
+
+ default:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(" /* ILLEGAL CONSTANT type:0x%02X, size:%d bytes, blob: "),MDDV.m_bType,MDDV.m_cbSize);
+ if(MDDV.m_wzValue)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(");
+ PAL_CPP_TRY {
+ DumpByteArray(szString,(BYTE*)MDDV.m_wzValue,MDDV.m_cbSize,GUICookie);
+ } PAL_CPP_CATCH_ALL {
+ szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(" Invalid blob at 0x%08X)"), MDDV.m_wzValue);
+ } PAL_CPP_ENDTRY
+ }
+ else
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"NULL");
+ }
+ strcat_s(szString, SZSTRING_REMAINING_SIZE(szptr), " */");
+ break;
+ }
+}
+
+void DumpParams(ParamDescriptor* pPD, ULONG ulParams, void* GUICookie)
+{
+ if(pPD)
+ {
+ for(ULONG i = ulParams; i<2*ulParams+1; i++) // pPD[ulParams] is return value
+ {
+ ULONG j = i % (ulParams+1);
+ if(RidFromToken(pPD[j].tok))
+ {
+ HENUMInternal hEnum;
+ mdCustomAttribute tkCA;
+ ULONG ulCAs= 0;
+
+ if(g_fShowCA)
+ {
+ if (FAILED(g_pImport->EnumInit(mdtCustomAttribute, pPD[j].tok, &hEnum)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "%sERROR: MetaData error enumerating CustomAttribute for %08X", g_szAsmCodeIndent, pPD[j].tok);
+ printLine(GUICookie, szString);
+ continue;
+ }
+ ulCAs = g_pImport->EnumGetCount(&hEnum);
+ }
+ if(ulCAs || IsPdHasDefault(pPD[j].attr))
+ {
+ char *szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s [%d]",g_szAsmCodeIndent,KEYWORD(".param"),i-ulParams);
+ if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),pPD[j].tok);
+ if(IsPdHasDefault(pPD[j].attr)) DumpDefaultValue(pPD[j].tok, szString, GUICookie);
+ printLine(GUICookie, szString);
+ if(ulCAs)
+ {
+ while(g_pImport->EnumNext(&hEnum,&tkCA) && RidFromToken(tkCA))
+ {
+ DumpCustomAttribute(tkCA,GUICookie,false);
+ }
+ }
+ }
+ if(g_fShowCA) g_pImport->EnumClose( &hEnum);
+ }
+ }
+ }
+}
+
+BOOL DumpPermissionSetBlob(void* GUICookie,__inout __nullterminated char* szString, BYTE* pvPermission, ULONG cbPermission)
+{
+ if(*pvPermission == '.')
+ {
+ CQuickBytes out;
+ pvPermission++;
+ char* szptr_init = &szString[strlen(szString)];
+ char* szptr = szptr_init;
+ appendStr(&out," = {");
+ unsigned nAttrs = CorSigUncompressData((PCCOR_SIGNATURE&)pvPermission);
+ for(unsigned iAttr = 0; iAttr < nAttrs; iAttr++)
+ {
+ unsigned L = CorSigUncompressData((PCCOR_SIGNATURE&)pvPermission); // class name length
+ mdToken tkAttr = ResolveReflectionNotation(pvPermission,L,g_pImport,GUICookie);
+ if(IsNilToken(tkAttr))
+ {
+ appendStr(&out,KEYWORD("class "));
+ appendStr(&out,"'");
+ appendStr(&out,UnquotedProperName((char*)pvPermission,L));
+ appendStr(&out,"'");
+ }
+ else
+ {
+ PrettyPrintClass(&out, tkAttr, g_pImport);
+ }
+ pvPermission += L;
+ appendStr(&out," = {");
+ // dump blob
+ L = CorSigUncompressData((PCCOR_SIGNATURE&)pvPermission); // blob length
+ if(L > 0)
+ {
+ BYTE* pvEnd = pvPermission+L;
+ L = CorSigUncompressData((PCCOR_SIGNATURE&)pvPermission); // number of props
+ if(L > 0)
+ {
+ if(!PrettyPrintCustomAttributeNVPairs(L, pvPermission, pvEnd, &out, GUICookie))
+ return FALSE;
+ out.Shrink(out.Size()-1);
+ }
+ pvPermission = pvEnd;
+ }
+ appendStr(&out, iAttr == nAttrs-1 ? "}" : "}, ");
+ }
+ appendStr(&out, "}");
+ char* sz = asString(&out);
+ while(char* pc = strstr(sz,"}, "))
+ {
+ *(pc+2) = 0;
+ strcpy_s(szptr,SZSTRING_REMAINING_SIZE(szptr), sz);
+ printLine(GUICookie,szString);
+ sz = pc+3;
+ if(szptr == szptr_init) szptr += 4; // to compensate for = {
+ for(pc = szString; pc < szptr; pc++) *pc = ' ';
+ }
+ strcpy_s(szptr, SZSTRING_REMAINING_SIZE(szptr),sz);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void DumpPermissions(mdToken tkOwner, void* GUICookie)
+{
+ HCORENUM hEnum = NULL;
+ static mdPermission rPerm[16384];
+ ULONG count;
+ HRESULT hr;
+ //static char szString[4096];
+
+ // can't use internal import here: EnumInit not impl. for mdtPrmission
+ while (SUCCEEDED(hr = g_pPubImport->EnumPermissionSets( &hEnum,
+ tkOwner, 0, rPerm, 16384, &count)) &&
+ count > 0)
+ {
+ for (ULONG i = 0; i < count; i++)
+ {
+ DWORD dwAction;
+ const BYTE *pvPermission=NULL;
+ ULONG cbPermission=0;
+ const char *szAction;
+ char *szptr;
+
+ szptr = &szString[0];
+ if(SUCCEEDED(hr = g_pPubImport->GetPermissionSetProps( rPerm[i], &dwAction,
+ (const void**)&pvPermission, &cbPermission)))
+ {
+ szptr += sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".permissionset"));
+ switch(dwAction)
+ {
+ case dclActionNil: szAction = ""; break;
+ case dclRequest: szAction = KEYWORD("request"); break;
+ case dclDemand: szAction = KEYWORD("demand"); break;
+ case dclAssert: szAction = KEYWORD("assert"); break;
+ case dclDeny: szAction = KEYWORD("deny"); break;
+ case dclPermitOnly: szAction = KEYWORD("permitonly"); break;
+ case dclLinktimeCheck: szAction = KEYWORD("linkcheck"); break;
+ case dclInheritanceCheck: szAction = KEYWORD("inheritcheck"); break;
+ case dclRequestMinimum: szAction = KEYWORD("reqmin"); break;
+ case dclRequestOptional: szAction = KEYWORD("reqopt"); break;
+ case dclRequestRefuse: szAction = KEYWORD("reqrefuse"); break;
+ case dclPrejitGrant: szAction = KEYWORD("prejitgrant"); break;
+ case dclPrejitDenied: szAction = KEYWORD("prejitdeny"); break;
+ case dclNonCasDemand: szAction = KEYWORD("noncasdemand"); break;
+ case dclNonCasLinkDemand: szAction = KEYWORD("noncaslinkdemand"); break;
+ case dclNonCasInheritance: szAction = KEYWORD("noncasinheritance"); break;
+ default: szAction = ERRORMSG("<UNKNOWN_ACTION>"); break;
+ }
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),szAction);
+ if(pvPermission && cbPermission)
+ {
+ printLine(GUICookie, szString);
+ sprintf_s(szString,SZSTRING_SIZE,"%s ",g_szAsmCodeIndent);
+ if(!DumpPermissionSetBlob(GUICookie,szString,(BYTE*)pvPermission,cbPermission))
+ {
+ strcat_s(szString,SZSTRING_SIZE,KEYWORD("bytearray"));
+ strcat_s(szString,SZSTRING_SIZE," (");
+ DumpByteArray(szString, pvPermission, cbPermission, GUICookie);
+ }
+ printLine(GUICookie,szString);
+ }
+ else // i.e. if pvPermission == NULL or cbPermission == NULL
+ {
+ sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = ()");
+ printLine(GUICookie,szString);
+ }
+ DumpCustomAttributes(rPerm[i],GUICookie);
+ }// end if(GetPermissionProps)
+ } // end for(all permissions)
+ }//end while(EnumPermissionSets)
+ g_pPubImport->CloseEnum( hEnum);
+}
+
+void PrettyPrintMethodSig(__inout __nullterminated char* szString, unsigned* puStringLen, CQuickBytes* pqbMemberSig, PCCOR_SIGNATURE pComSig, ULONG cComSig,
+ __inout __nullterminated char* buff, __in_opt __nullterminated char* szArgPrefix, void* GUICookie)
+{
+ unsigned uMaxWidth = 40;
+ if(g_fDumpHTML || g_fDumpRTF) uMaxWidth = 240;
+ if(*buff && (strlen(szString) > (size_t)uMaxWidth))
+ {
+ printLine(GUICookie,szString);
+ strcpy_s(szString,SZSTRING_SIZE,g_szAsmCodeIndent);
+ strcat_s(szString,SZSTRING_SIZE," "); // to align with ".method "
+ }
+ appendStr(pqbMemberSig, szString);
+ {
+ char* pszTailSig = (char*)PrettyPrintSig(pComSig, cComSig, buff, pqbMemberSig, g_pImport, szArgPrefix);
+ if(*buff)
+ {
+ size_t L = strlen(pszTailSig);
+ char* newbuff = new char[strlen(buff)+3];
+ sprintf_s(newbuff,strlen(buff)+3," %s(", buff);
+ char* pszOffset = strstr(pszTailSig,newbuff);
+ if(pszOffset)
+ {
+ char* pszTailSigRemainder = new char[L+1];
+ if(pszOffset - pszTailSig > (int)uMaxWidth)
+ {
+ char* pszOffset2 = strstr(pszTailSig," marshal(");
+ if(pszOffset2 && (pszOffset2 < pszOffset))
+ {
+ *pszOffset2 = 0;
+ strcpy_s(pszTailSigRemainder,L,pszOffset2+1);
+ printLine(GUICookie,pszTailSig);
+ strcpy_s(pszTailSig,L,g_szAsmCodeIndent);
+ strcat_s(pszTailSig,L," "); // to align with ".method "
+ strcat_s(pszTailSig,L,pszTailSigRemainder);
+ pszOffset = strstr(pszTailSig,newbuff);
+ }
+ *pszOffset = 0 ;
+ strcpy_s(pszTailSigRemainder,L,pszOffset+1);
+ printLine(GUICookie,pszTailSig);
+ strcpy_s(pszTailSig,L,g_szAsmCodeIndent);
+ strcat_s(pszTailSig,L," "); // to align with ".method "
+ strcat_s(pszTailSig,L,pszTailSigRemainder);
+ pszOffset = strstr(pszTailSig,newbuff);
+ }
+ size_t i, j, k, l, indent = pszOffset - pszTailSig + strlen(buff) + 2;
+ char chAfterComma;
+ char *pComma = pszTailSig+strlen(buff), *pch;
+ while((pComma = strchr(pComma,',')))
+ {
+ for(pch = pszTailSig, i=0, j = 0, k=0, l=0; pch < pComma; pch++)
+ {
+ if(*pch == '\\') pch++;
+ else
+ {
+ if(*pch == '\'') j=1-j;
+ else if(*pch == '\"') k=1-k;
+ else if(j==0)
+ {
+ if(*pch == '[') i++;
+ else if(*pch == ']') i--;
+ else if(strncmp(pch,LTN(),strlen(LTN()))==0) l++;
+ else if(strncmp(pch,GTN(),strlen(GTN()))==0) l--;
+ }
+ }
+ }
+ pComma++;
+ if((i==0)&&(j==0)&&(k==0)&&(l==0))// no brackets/quotes or all opened/closed
+ {
+ chAfterComma = *pComma;
+ strcpy_s(pszTailSigRemainder,L,pComma);
+ *pComma = 0;
+ printLine(GUICookie,pszTailSig);
+ *pComma = chAfterComma;
+ for(i=0; i<indent; i++) pszTailSig[i] = ' ';
+ strcpy_s(&pszTailSig[indent],L-indent,pszTailSigRemainder);
+ pComma = pszTailSig;
+ }
+ }
+ if(*puStringLen < (unsigned)strlen(pszTailSig)+128)
+ {
+ //free(szString);
+ *puStringLen = (unsigned)strlen(pszTailSig)+128; // need additional space for "il managed" etc.
+ //szString = (char*)malloc(*puStringLen);
+ }
+ VDELETE(pszTailSigRemainder);
+ }
+ strcpy_s(szString,SZSTRING_SIZE,pszTailSig);
+ VDELETE(newbuff);
+ }
+ else // it's for GUI, don't split it into several lines
+ {
+ size_t L = strlen(szString);
+ if(L < 2048)
+ {
+ L = 2048-L;
+ strncpy_s(szString,SZSTRING_SIZE,pszTailSig,L);
+ }
+ }
+ }
+}
+// helper to avoid mixing of SEH and stack objects with destructors
+BOOL DisassembleWrapper(IMDInternalImport *pImport, BYTE *ILHeader,
+ void *GUICookie, mdToken FuncToken, ParamDescriptor* pszArgname, ULONG ulArgs)
+{
+ BOOL fRet = FALSE;
+ //char szString[4096];
+
+ PAL_CPP_TRY
+ {
+ fRet = Disassemble(pImport, ILHeader, GUICookie, FuncToken, pszArgname, ulArgs);
+ }
+ PAL_CPP_CATCH_ALL
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_DASMERR),g_szAsmCodeIndent);
+ printLine(GUICookie, szString);
+ }
+ PAL_CPP_ENDTRY
+
+ return fRet;
+}
+
+BOOL PrettyPrintGP( // prints name of generic param, or returns FALSE
+ mdToken tkOwner, // Class, method or 0
+ CQuickBytes *out, // where to put the pretty printed generic param
+ int n) // Index of generic param
+{
+ BOOL ret = FALSE;
+ if(tkOwner && ((TypeFromToken(tkOwner)==mdtTypeDef)||(TypeFromToken(tkOwner)==mdtMethodDef)))
+ {
+ DWORD NumTyPars;
+ HENUMInternal hEnumTyPar;
+
+ if(SUCCEEDED(g_pImport->EnumInit(mdtGenericParam,tkOwner,&hEnumTyPar)))
+ {
+ NumTyPars = g_pImport->EnumGetCount(&hEnumTyPar);
+ if(NumTyPars > (DWORD)n)
+ {
+ // need this for name dup check
+ LPCSTR *pszName = new LPCSTR[NumTyPars];
+ if(pszName != NULL)
+ {
+ ULONG ulSequence;
+ DWORD ix,nx;
+ mdToken tk;
+ for(ix = 0, nx = 0xFFFFFFFF; ix < NumTyPars; ix++)
+ {
+ if(g_pImport->EnumNext(&hEnumTyPar,&tk))
+ {
+ if(SUCCEEDED(g_pImport->GetGenericParamProps(tk,&ulSequence,NULL,NULL,NULL,&pszName[ix])))
+ {
+ if(ulSequence == (ULONG)n)
+ nx = ix;
+ }
+ }
+ }
+ // if there are dup names, use !0 or !!0
+ if(nx != 0xFFFFFFFF)
+ {
+ for(ix = 0; ix < nx; ix++)
+ {
+ if(strcmp(pszName[ix],pszName[nx]) == 0)
+ break;
+ }
+ if(ix >= nx)
+ {
+ for(ix = nx+1; ix < NumTyPars; ix++)
+ {
+ if(strcmp(pszName[ix],pszName[nx]) == 0)
+ break;
+ }
+ if(ix >= NumTyPars)
+ {
+ appendStr(out, ProperName((char*)(pszName[nx])));
+ ret = TRUE;
+ }
+ }
+ } // end if(tkTyPar != 0)
+ delete [] pszName;
+ } // end if(pszName != NULL)
+ } // end if(NumTyPars > (DWORD)n)
+ } // end if(SUCCEEDED(g_pImport->EnumInit(mdtGenericParam,tkOwner,&hEnumTyPar)))
+ g_pImport->EnumClose(&hEnumTyPar);
+ } // end if(tkOwner)
+ return ret;
+}
+
+// Pretty-print formal type parameters for a class or method
+char *DumpGenericPars(__inout_ecount(SZSTRING_SIZE) char* szString, mdToken tok, void* GUICookie/*=NULL*/, BOOL fSplit/*=FALSE*/)
+{
+ WCHAR *wzArgName = wzUniBuf;
+ ULONG chName;
+ mdToken tkConstr[2048];
+
+ DWORD NumTyPars;
+ DWORD NumConstrs;
+ mdGenericParam tkTyPar;
+ DWORD attr;
+ HCORENUM hEnumTyPar = NULL;
+ HCORENUM hEnumTyParConstr = NULL;
+ char* szptr = &szString[strlen(szString)];
+ char* szbegin;
+ unsigned i;
+
+ if (FAILED(g_pPubImport->EnumGenericParams(&hEnumTyPar, tok, &tkTyPar, 1, &NumTyPars)))
+ return NULL;
+ if (NumTyPars > 0)
+ {
+ szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),LTN());
+ szbegin = szptr;
+
+ for (i = 1; NumTyPars != 0; i++)
+ {
+ g_pPubImport->GetGenericParamProps(tkTyPar, NULL, &attr, NULL, NULL, wzArgName, UNIBUF_SIZE/2, &chName);
+ //if(wcslen(wzArgName) >= MAX_CLASSNAME_LENGTH)
+ // wzArgName[MAX_CLASSNAME_LENGTH-1] = 0;
+ hEnumTyParConstr = NULL;
+ if (FAILED(g_pPubImport->EnumGenericParamConstraints(&hEnumTyParConstr, tkTyPar, tkConstr, 2048, &NumConstrs)))
+ {
+ g_pPubImport->CloseEnum(hEnumTyPar);
+ return NULL;
+ }
+ *szptr = 0;
+ CHECK_REMAINING_SIZE;
+ switch (attr & gpVarianceMask)
+ {
+ case gpCovariant : szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "+ "); break;
+ case gpContravariant : szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "- "); break;
+ }
+ CHECK_REMAINING_SIZE;
+ if ((attr & gpReferenceTypeConstraint) != 0)
+ szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "class ");
+ CHECK_REMAINING_SIZE;
+ if ((attr & gpNotNullableValueTypeConstraint) != 0)
+ szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "valuetype ");
+ CHECK_REMAINING_SIZE;
+ if ((attr & gpDefaultConstructorConstraint) != 0)
+ szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), ".ctor ");
+ CHECK_REMAINING_SIZE;
+ if (NumConstrs)
+ {
+ CQuickBytes out;
+ mdToken tkConstrType,tkOwner;
+ szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(");
+ DWORD ix;
+ for (ix=0; ix<NumConstrs; ix++)
+ {
+ if (FAILED(g_pPubImport->GetGenericParamConstraintProps(tkConstr[ix], &tkOwner, &tkConstrType)))
+ return NULL;
+
+ if(ix) szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),", ");
+ CHECK_REMAINING_SIZE;
+ out.Shrink(0);
+ szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s",PrettyPrintClass(&out,tkConstrType,g_pImport));
+ CHECK_REMAINING_SIZE;
+ }
+ if(ix < NumConstrs) break;
+ szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),") ");
+ CHECK_REMAINING_SIZE;
+ }
+ // re-get name, wzUniBuf may not contain it any more
+ g_pPubImport->GetGenericParamProps(tkTyPar, NULL, &attr, NULL, NULL, wzArgName, UNIBUF_SIZE/2, &chName);
+ //if(wcslen(wzArgName) >= MAX_CLASSNAME_LENGTH)
+ // wzArgName[MAX_CLASSNAME_LENGTH-1] = 0;
+ if (chName)
+ {
+ char* sz = (char*)(&wzUniBuf[UNIBUF_SIZE/2]);
+ WszWideCharToMultiByte(CP_UTF8,0,wzArgName,-1,sz,UNIBUF_SIZE,NULL,NULL);
+ szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s",ProperName(sz));
+ }
+ CHECK_REMAINING_SIZE;
+ if (FAILED(g_pPubImport->EnumGenericParams(&hEnumTyPar, tok, &tkTyPar, 1, &NumTyPars)))
+ return NULL;
+ if (NumTyPars != 0)
+ {
+ *szptr++ = ',';
+
+ if(fSplit && (i == 4))
+ {
+ *szptr = 0;
+ printLine(GUICookie,szString);
+ i = 0; // mind i++ at the end of the loop
+ for(szptr = szString; szptr < szbegin; szptr++) *szptr = ' ';
+ }
+ }
+ } // end for (i = 1; NumTyPars != 0; i++)
+ if(NumTyPars != 0) // all type parameters can't fit in szString, error
+ {
+ strcpy_s(szptr,4,"...");
+ szptr += 3;
+ }
+ else
+ szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),GTN());
+ } // end if (NumTyPars > 0)
+ *szptr = 0;
+ if(hEnumTyPar) g_pPubImport->CloseEnum(hEnumTyPar);
+ return szptr;
+}
+
+void DumpGenericParsCA(mdToken tok, void* GUICookie/*=NULL*/)
+{
+ DWORD NumTyPars;
+ mdGenericParam tkTyPar;
+ HCORENUM hEnumTyPar = NULL;
+ unsigned i;
+ WCHAR *wzArgName = wzUniBuf;
+ ULONG chName;
+ DWORD attr;
+
+ if(g_fShowCA)
+ {
+ for(i=0; SUCCEEDED(g_pPubImport->EnumGenericParams(&hEnumTyPar, tok, &tkTyPar, 1, &NumTyPars))
+ &&(NumTyPars > 0); i++)
+ {
+ HENUMInternal hEnum;
+ mdCustomAttribute tkCA;
+ ULONG ulCAs= 0;
+
+ if (FAILED(g_pImport->EnumInit(mdtCustomAttribute, tkTyPar, &hEnum)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "%sERROR: MetaData error enumerating CustomAttribute for %08X", g_szAsmCodeIndent, tkTyPar);
+ printLine(GUICookie, szString);
+ return;
+ }
+ ulCAs = g_pImport->EnumGetCount(&hEnum);
+ if(ulCAs)
+ {
+ char *szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".param type"));
+ if(SUCCEEDED(g_pPubImport->GetGenericParamProps(tkTyPar, NULL, &attr, NULL, NULL, wzArgName, UNIBUF_SIZE/2, &chName))
+ &&(chName > 0))
+ {
+ //if(wcslen(wzArgName) >= MAX_CLASSNAME_LENGTH)
+ // wzArgName[MAX_CLASSNAME_LENGTH-1] = 0;
+ char* sz = (char*)(&wzUniBuf[UNIBUF_SIZE/2]);
+ WszWideCharToMultiByte(CP_UTF8,0,wzArgName,-1,sz,UNIBUF_SIZE,NULL,NULL);
+ szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s ",ProperName(sz));
+ }
+ else
+ szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"[%d] ",i+1);
+ if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),tkTyPar);
+ printLine(GUICookie, szString);
+ while(g_pImport->EnumNext(&hEnum,&tkCA) && RidFromToken(tkCA))
+ {
+ DumpCustomAttribute(tkCA,GUICookie,false);
+ }
+ }
+ g_pImport->EnumClose( &hEnum);
+ } //end for(i=0;...
+ } //end if(g_fShowCA)
+}
+
+// Sets *pbOverridingTypeSpec to TRUE if we are overriding a method declared by a type spec.
+// In that case the syntax is slightly different (there are additional 'method' keywords).
+// Refer to Expert .NET 2.0 IL Assembler page 242.
+void PrettyPrintOverrideDecl(ULONG i, __inout __nullterminated char* szString, void* GUICookie, mdToken tkOverrider,
+ BOOL *pbOverridingTypeSpec)
+{
+ HRESULT hr;
+ const char * pszMemberName;
+ mdToken tkDecl,tkDeclParent=0;
+ char szBadToken[256];
+ char pszTailSigDefault[] = "";
+ char* pszTailSig = pszTailSigDefault;
+ CQuickBytes qbInstSig;
+ char* szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".override"));
+ tkDecl = (*g_pmi_list)[i].tkDecl;
+
+ *pbOverridingTypeSpec = FALSE;
+
+ if(g_pImport->IsValidToken(tkDecl))
+ {
+ if(SUCCEEDED(g_pImport->GetParentToken(tkDecl,&tkDeclParent)))
+ {
+ if(g_pImport->IsValidToken(tkDeclParent))
+ {
+ if(TypeFromToken(tkDeclParent) == mdtMethodDef) //get the parent's parent
+ {
+ mdTypeRef cr1;
+ if(FAILED(g_pImport->GetParentToken(tkDeclParent,&cr1))) cr1 = mdTypeRefNil;
+ tkDeclParent = cr1;
+ }
+ if(RidFromToken(tkDeclParent))
+ {
+ if(TypeFromToken(tkDeclParent)==mdtTypeSpec)
+ {
+ szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), " %s ",KEYWORD("method"));
+ PrettyPrintToken(szString,tkDecl,g_pImport,GUICookie,tkOverrider);
+
+ *pbOverridingTypeSpec = TRUE;
+ return;
+ }
+ PrettyPrintToken(szString, tkDeclParent, g_pImport,GUICookie,tkOverrider);
+ strcat_s(szString, SZSTRING_SIZE,"::");
+ szptr = &szString[strlen(szString)];
+ }
+ }
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s",ERRORMSG("INVALID OVERRIDDEN METHOD'S PARENT TOKEN"));
+ }
+ if(TypeFromToken(tkDecl) == mdtMethodSpec)
+ {
+ mdToken meth=0;
+ PCCOR_SIGNATURE pSig=NULL;
+ ULONG cSig=0;
+ if (FAILED(g_pImport->GetMethodSpecProps(tkDecl, &meth, &pSig, &cSig)))
+ {
+ meth = mdTokenNil;
+ pSig = NULL;
+ cSig = 0;
+ }
+
+ if (pSig && cSig)
+ {
+ qbInstSig.Shrink(0);
+ pszTailSig = (char*)PrettyPrintSig(pSig, cSig, "", &qbInstSig, g_pImport, NULL);
+ }
+ tkDecl = meth;
+ }
+ if(TypeFromToken(tkDecl) == mdtMethodDef)
+ {
+ if (FAILED(g_pImport->GetNameOfMethodDef(tkDecl, &pszMemberName)))
+ {
+ sprintf_s(szBadToken,256,ERRORMSG("INVALID RECORD: 0x%8.8X"),tkDecl);
+ pszMemberName = (const char *)szBadToken;
+ }
+ }
+ else if(TypeFromToken(tkDecl) == mdtMemberRef)
+ {
+ PCCOR_SIGNATURE pComSig;
+ ULONG cComSig;
+
+ if (FAILED(g_pImport->GetNameAndSigOfMemberRef(
+ tkDecl,
+ &pComSig,
+ &cComSig,
+ &pszMemberName)))
+ {
+ sprintf_s(szBadToken,256,ERRORMSG("INVALID RECORD: 0x%8.8X"),tkDecl);
+ pszMemberName = (const char *)szBadToken;
+ }
+ }
+ else
+ {
+ sprintf_s(szBadToken,256,ERRORMSG("INVALID TOKEN: 0x%8.8X"),tkDecl);
+ pszMemberName = (const char*)szBadToken;
+ }
+ MAKE_NAME_IF_NONE(pszMemberName,tkDecl);
+ }
+ else
+ {
+ sprintf_s(szBadToken,256,ERRORMSG("INVALID TOKEN: 0x%8.8X"),tkDecl);
+ pszMemberName = (const char*)szBadToken;
+ }
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s%s",ProperName((char*)pszMemberName),pszTailSig);
+
+ if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT(" /*%08X::%08X*/ "),tkDeclParent,(*g_pmi_list)[i].tkDecl);
+}
+
+#ifdef _PREFAST_
+#pragma warning(push)
+#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
+#endif
+BOOL DumpMethod(mdToken FuncToken, const char *pszClassName, DWORD dwEntryPointToken,void *GUICookie,BOOL DumpBody)
+{
+ HRESULT hr;
+ const char *pszMemberName = NULL;//[MAX_MEMBER_LENGTH];
+ const char *pszMemberSig = NULL;
+ DWORD dwAttrs = 0;
+ DWORD dwImplAttrs;
+ DWORD dwOffset;
+ DWORD dwTargetRVA;
+ CQuickBytes qbMemberSig;
+ PCCOR_SIGNATURE pComSig = NULL;
+ ULONG cComSig;
+ char *buff = NULL;//[MAX_MEMBER_LENGTH];
+ ParamDescriptor* pszArgname = NULL;
+ ULONG ulArgs=0;
+ unsigned retParamIx = 0;
+ unsigned uStringLen = SZSTRING_SIZE;
+ char szArgPrefix[MAX_PREFIX_SIZE];
+ char* szptr = NULL;
+ mdToken tkMVarOwner = g_tkMVarOwner;
+
+ if (FAILED(g_pImport->GetMethodDefProps(FuncToken, &dwAttrs)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "%sERROR: MethodDef %08X has wrong record", g_szAsmCodeIndent, FuncToken);
+ printError(GUICookie, ERRORMSG(szString));
+ return FALSE;
+ }
+ if (g_fLimitedVisibility)
+ {
+ if(g_fHidePub && IsMdPublic(dwAttrs)) return FALSE;
+ if(g_fHidePriv && IsMdPrivate(dwAttrs)) return FALSE;
+ if(g_fHideFam && IsMdFamily(dwAttrs)) return FALSE;
+ if(g_fHideAsm && IsMdAssem(dwAttrs)) return FALSE;
+ if(g_fHideFOA && IsMdFamORAssem(dwAttrs)) return FALSE;
+ if(g_fHideFAA && IsMdFamANDAssem(dwAttrs)) return FALSE;
+ if(g_fHidePrivScope && IsMdPrivateScope(dwAttrs)) return FALSE;
+ }
+ if (FAILED(g_pImport->GetMethodImplProps(FuncToken, &dwOffset, &dwImplAttrs)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "%sERROR: Invalid MethodImpl %08X record", g_szAsmCodeIndent, FuncToken);
+ printError(GUICookie, ERRORMSG(szString));
+ return FALSE;
+ }
+ if (FAILED(g_pImport->GetNameOfMethodDef(FuncToken, &pszMemberName)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "%sERROR: MethodDef %08X has wrong record", g_szAsmCodeIndent, FuncToken);
+ printError(GUICookie, ERRORMSG(szString));
+ return FALSE;
+ }
+ MAKE_NAME_IF_NONE(pszMemberName,FuncToken);
+ if (FAILED(g_pImport->GetSigOfMethodDef(FuncToken, &cComSig, &pComSig)))
+ {
+ pComSig = NULL;
+ }
+
+ if (cComSig == NULL)
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "%sERROR: method '%s' has no signature", g_szAsmCodeIndent, pszMemberName);
+ printError(GUICookie, ERRORMSG(szString));
+ return FALSE;
+ }
+ bool bRet = FALSE;
+
+ PAL_CPP_TRY {
+ if((*pComSig & IMAGE_CEE_CS_CALLCONV_MASK) > IMAGE_CEE_CS_CALLCONV_VARARG)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%sERROR: signature of method '%s' has invalid calling convention 0x%2.2X",g_szAsmCodeIndent,pszMemberName,*pComSig);
+ printError(GUICookie,ERRORMSG(szString));
+ bRet = TRUE;
+ goto lDone;
+ }
+
+ g_tkMVarOwner = FuncToken;
+ szString[0] = 0;
+ DumpGenericPars(szString,FuncToken); //,NULL,FALSE);
+ pszMemberSig = PrettyPrintSig(pComSig, cComSig, szString, &qbMemberSig, g_pImport,NULL);
+lDone: ;
+ } PAL_CPP_CATCH_ALL {
+ printError(GUICookie,"INVALID DATA ADDRESS");
+ bRet = TRUE;
+ } PAL_CPP_ENDTRY;
+
+ if (bRet)
+ {
+ g_tkMVarOwner = tkMVarOwner;
+ return FALSE;
+ }
+
+ if (g_Mode == MODE_DUMP_CLASS_METHOD || g_Mode == MODE_DUMP_CLASS_METHOD_SIG)
+ {
+ if (strcmp(pszMemberName, g_pszMethodToDump) != 0) return FALSE;
+
+ if (g_Mode == MODE_DUMP_CLASS_METHOD_SIG)
+ {
+ // we want plain signature without token values
+ const char *pszPlainSig;
+ if (g_fDumpTokens)
+ {
+ // temporarily disable token dumping
+ g_fDumpTokens = FALSE;
+
+ PAL_CPP_TRY
+ {
+ CQuickBytes qbTempSig;
+ pszPlainSig = PrettyPrintSig(pComSig, cComSig, "", &qbTempSig, g_pImport, NULL);
+ }
+ PAL_CPP_CATCH_ALL
+ {
+ pszPlainSig = "";
+ }
+ PAL_CPP_ENDTRY;
+
+ g_fDumpTokens = TRUE;
+ }
+ else
+ {
+ pszPlainSig = pszMemberSig;
+ }
+
+ if (strcmp(pszPlainSig, g_pszSigToDump) != 0) return FALSE;
+ }
+ }
+
+ if(!DumpBody)
+ {
+ printLine(GUICookie,(char*)pszMemberSig);
+ g_tkMVarOwner = tkMVarOwner;
+ return TRUE;
+ }
+
+ szptr = &szString[0];
+ szString[0] = 0;
+ if(DumpBody) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s%s ",g_szAsmCodeIndent,ANCHORPT(KEYWORD(".method"),FuncToken));
+ else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s ",ANCHORPT(KEYWORD(".method"),FuncToken));
+
+ if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),FuncToken);
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)0));
+ if(IsMdPublic(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"public ");
+ if(IsMdPrivate(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"private ");
+ if(IsMdFamily(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"family ");
+ if(IsMdAssem(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"assembly ");
+ if(IsMdFamANDAssem(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"famandassem ");
+ if(IsMdFamORAssem(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"famorassem ");
+ if(IsMdPrivateScope(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"privatescope ");
+ if(IsMdHideBySig(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"hidebysig ");
+ if(IsMdNewSlot(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"newslot ");
+ if(IsMdSpecialName(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"specialname ");
+ if(IsMdRTSpecialName(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"rtspecialname ");
+ if (IsMdStatic(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"static ");
+ if (IsMdAbstract(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"abstract ");
+ if (dwAttrs & 0x00000200) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"strict ");
+ if (IsMdVirtual(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"virtual ");
+ if (IsMdFinal(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"final ");
+ if (IsMdUnmanagedExport(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"unmanagedexp ");
+ if(IsMdRequireSecObject(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"reqsecobj ");
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)-1));
+ if (IsMdPinvokeImpl(dwAttrs))
+ {
+ DWORD dwMappingFlags;
+ const char *szImportName;
+ mdModuleRef mrImportDLL;
+
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s(",KEYWORD("pinvokeimpl"));
+ if(FAILED(g_pImport->GetPinvokeMap(FuncToken,&dwMappingFlags,
+ &szImportName,&mrImportDLL))) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/* No map */"));
+ else
+ szptr=DumpPinvokeMap(dwMappingFlags, (strcmp(szImportName,pszMemberName)? szImportName : NULL),
+ mrImportDLL,szString,GUICookie);
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),") ");
+ }
+ // A little hack to get the formatting we need for Assem.
+ buff = new char[SZSTRING_SIZE];
+ if(buff==NULL)
+ {
+ printError(GUICookie,"Out of memory");
+ g_tkMVarOwner = tkMVarOwner;
+ return FALSE;
+ }
+ g_fThisIsInstanceMethod = !IsMdStatic(dwAttrs);
+ {
+ const char *psz = NULL;
+ if(IsMdPrivateScope(dwAttrs))
+ sprintf_s(buff,SZSTRING_SIZE,"%s$PST%08X", pszMemberName,FuncToken );
+ else
+ strcpy_s(buff,SZSTRING_SIZE, pszMemberName );
+
+ psz = ProperName(buff);
+ if(psz != buff)
+ {
+ strcpy_s(buff,SZSTRING_SIZE,psz);
+ }
+ }
+
+ DumpGenericPars(buff, FuncToken); //, NULL, FALSE);
+
+ qbMemberSig.Shrink(0);
+ // Get the argument names, if any
+ strcpy_s(szArgPrefix,MAX_PREFIX_SIZE,(g_fThisIsInstanceMethod ? "A1": "A0"));
+ {
+ PCCOR_SIGNATURE typePtr = pComSig;
+ unsigned ulCallConv = CorSigUncompressData(typePtr); // get the calling convention out of the way
+ if (ulCallConv & IMAGE_CEE_CS_CALLCONV_GENERIC)
+ CorSigUncompressData(typePtr); // get the num of generic args out of the way
+ unsigned numArgs = CorSigUncompressData(typePtr)+1;
+ HENUMInternal hArgEnum;
+ mdParamDef tkArg;
+ if (FAILED(g_pImport->EnumInit(mdtParamDef,FuncToken,&hArgEnum)))
+ {
+ printError(GUICookie, "Invalid MetaDataFormat");
+ g_tkMVarOwner = tkMVarOwner;
+ return FALSE;
+ }
+ ulArgs = g_pImport->EnumGetCount(&hArgEnum);
+ retParamIx = numArgs-1;
+ if (ulArgs < numArgs) ulArgs = numArgs;
+ if (ulArgs != 0)
+ {
+ pszArgname = new ParamDescriptor[ulArgs+2];
+ memset(pszArgname,0,(ulArgs+2)*sizeof(ParamDescriptor));
+ LPCSTR szName;
+ ULONG ulSequence, ix;
+ USHORT wSequence;
+ DWORD dwAttr;
+ ULONG j;
+ for (j=0; g_pImport->EnumNext(&hArgEnum,&tkArg) && RidFromToken(tkArg); j++)
+ {
+ if (FAILED(g_pImport->GetParamDefProps(tkArg, &wSequence, &dwAttr, &szName)))
+ {
+ char sz[256];
+ sprintf_s(sz, COUNTOF(sz), RstrUTF(IDS_E_INVALIDRECORD), tkArg);
+ printError(GUICookie, sz);
+ continue;
+ }
+ ulSequence = wSequence;
+
+ if (ulSequence > ulArgs+1)
+ {
+ char sz[256];
+ sprintf_s(sz,256,RstrUTF(IDS_E_PARAMSEQNO),j,ulSequence,ulSequence);
+ printError(GUICookie,sz);
+ }
+ else
+ {
+ ix = retParamIx;
+ if (ulSequence != 0)
+ {
+ ix = ulSequence-1;
+ if (*szName != 0)
+ {
+ pszArgname[ix].name = new char[strlen(szName)+1];
+ strcpy_s(pszArgname[ix].name,strlen(szName)+1,szName);
+ }
+ }
+ pszArgname[ix].attr = dwAttr;
+ pszArgname[ix].tok = tkArg;
+ }
+ }// end for( along the params)
+ for (j=0; j <numArgs; j++)
+ {
+ if(pszArgname[j].name == NULL) // we haven't got the name!
+ {
+ pszArgname[j].name = new char[16];
+ *pszArgname[j].name = 0;
+ }
+ if(*pszArgname[j].name == 0) // we haven't got the name!
+ {
+ sprintf_s(pszArgname[j].name,16,"A_%d",g_fThisIsInstanceMethod ? j+1 : j);
+ }
+ }// end for( along the argnames)
+ sprintf_s(szArgPrefix,MAX_PREFIX_SIZE,"@%Id0",(size_t)pszArgname);
+ } //end if (ulArgs)
+ g_pImport->EnumClose(&hArgEnum);
+ }
+ g_tkRefUser = FuncToken;
+ PrettyPrintMethodSig(szString, &uStringLen, &qbMemberSig, pComSig, cComSig,
+ buff, szArgPrefix, GUICookie);
+ g_tkRefUser = 0;
+ szptr = &szString[strlen(szString)];
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)0));
+ if(IsMiNative(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," native");
+ if(IsMiIL(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," cil");
+ if(IsMiOPTIL(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," optil");
+ if(IsMiRuntime(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," runtime");
+ if(IsMiUnmanaged(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," unmanaged");
+ if(IsMiManaged(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," managed");
+ if(IsMiPreserveSig(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," preservesig");
+ if(IsMiForwardRef(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," forwardref");
+ if(IsMiInternalCall(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," internalcall");
+ if(IsMiSynchronized(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," synchronized");
+ if(IsMiNoInlining(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," noinlining");
+ if(IsMiAggressiveInlining(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," aggressiveinlining");
+ if(IsMiNoOptimization(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," nooptimization");
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)-1));
+ printLine(GUICookie, szString);
+ VDELETE(buff);
+
+ if(!DumpBody)
+ {
+ g_tkMVarOwner = tkMVarOwner;
+ return TRUE;
+ }
+
+ if(g_fShowBytes)
+ {
+ if (FAILED(g_pImport->GetSigOfMethodDef(FuncToken, &cComSig, &pComSig)))
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%sERROR: method %08X has wrong record",g_szAsmCodeIndent,FuncToken);
+ printError(GUICookie,ERRORMSG(szString));
+ return FALSE;
+ }
+ const char* szt = "SIG:";
+ for(ULONG i=0; i<cComSig;)
+ {
+ szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s// %s", g_szAsmCodeIndent, szt);
+ while(i<cComSig)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %02X",pComSig[i]);
+ i++;
+ if((i & 0x1F)==0) break; // print only 32 per line
+ }
+ printLine(GUICookie, COMMENT(szString));
+ szt = " ";
+ }
+ }
+
+ szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s", g_szAsmCodeIndent,SCOPE());
+ printLine(GUICookie, szString);
+ szptr = &szString[0];
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+
+ // We have recoreded the entry point token from the CLR Header. Check to see if this
+ // method is the entry point.
+ if(FuncToken == static_cast<mdToken>(dwEntryPointToken))
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s", g_szAsmCodeIndent,KEYWORD(".entrypoint"));
+ printLine(GUICookie, szString);
+ }
+ DumpCustomAttributes(FuncToken,GUICookie);
+ DumpGenericParsCA(FuncToken,GUICookie);
+ DumpParams(pszArgname, retParamIx, GUICookie);
+ DumpPermissions(FuncToken,GUICookie);
+ // Check if the method represents entry in VTable fixups and in EATable
+ {
+ ULONG j;
+ for(j=0; j<g_nVTableRef; j++)
+ {
+ if((*g_prVTableRef)[j].tkTok == FuncToken)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s %d : %d",
+ g_szAsmCodeIndent,KEYWORD(".vtentry"),(*g_prVTableRef)[j].wEntry+1,(*g_prVTableRef)[j].wSlot+1);
+ printLine(GUICookie, szString);
+ break;
+ }
+ }
+ for(j=0; j<g_nEATableRef; j++)
+ {
+ if((*g_prEATableRef)[j].tkTok == FuncToken)
+ {
+ szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s [%d] ",
+ g_szAsmCodeIndent,KEYWORD(".export"),j+g_nEATableBase);
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s %s",
+ KEYWORD("as"), ProperName((*g_prEATableRef)[j].pszName));
+ printLine(GUICookie, szString);
+ break;
+ }
+ }
+ }
+ // Dump method impls of this method:
+ for(ULONG i = 0; i < g_NumMI; i++)
+ {
+ if((*g_pmi_list)[i].tkBody == FuncToken)
+ {
+ BOOL bOverridingTypeSpec;
+ PrettyPrintOverrideDecl(i,szString,GUICookie,FuncToken,&bOverridingTypeSpec);
+ printLine(GUICookie,szString);
+ }
+ }
+ dwTargetRVA = dwOffset;
+ if (IsMdPinvokeImpl(dwAttrs))
+ {
+ if(dwOffset)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%s// Embedded native code",g_szAsmCodeIndent);
+ printLine(GUICookie, COMMENT(szString));
+ goto ItsMiNative;
+ }
+ if(g_szAsmCodeIndent[0]) g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
+ printLine(GUICookie, szString);
+ g_tkMVarOwner = tkMVarOwner;
+ return TRUE;
+ }
+
+ if(IsMiManaged(dwImplAttrs))
+ {
+ if(IsMiIL(dwImplAttrs) || IsMiOPTIL(dwImplAttrs))
+ {
+ if(g_fShowBytes)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_METHBEG), g_szAsmCodeIndent,dwTargetRVA);
+ printLine(GUICookie, COMMENT(szString));
+ }
+ szString[0] = 0;
+ if (dwTargetRVA != 0)
+ {
+ void* newTarget;
+ if(g_pPELoader->getVAforRVA(dwTargetRVA,&newTarget))
+ {
+ DisassembleWrapper(g_pImport, (unsigned char*)newTarget, GUICookie, FuncToken,pszArgname, ulArgs);
+ }
+ else
+ {
+ sprintf_s(szString,SZSTRING_SIZE, "INVALID METHOD ADDRESS: 0x%8.8X (RVA: 0x%8.8X)",(size_t)newTarget,dwTargetRVA);
+ printError(GUICookie,szString);
+ }
+ }
+ }
+ else if(IsMiNative(dwImplAttrs))
+ {
+ItsMiNative:
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_DASMNATIVE), g_szAsmCodeIndent);
+ printLine(GUICookie, COMMENT(szString));
+
+ sprintf_s(szString,SZSTRING_SIZE,"%s// Managed TargetRVA = 0x%8.8X", g_szAsmCodeIndent, dwTargetRVA);
+ printLine(GUICookie, COMMENT(szString));
+ }
+ }
+ else if(IsMiUnmanaged(dwImplAttrs)&&IsMiNative(dwImplAttrs))
+ {
+ _ASSERTE(IsMiNative(dwImplAttrs));
+ sprintf_s(szString,SZSTRING_SIZE,"%s// Unmanaged TargetRVA = 0x%8.8X", g_szAsmCodeIndent, dwTargetRVA);
+ printLine(GUICookie, COMMENT(szString));
+ }
+ else if(IsMiRuntime(dwImplAttrs))
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_METHODRT), g_szAsmCodeIndent);
+ printLine(GUICookie, COMMENT(szString));
+ }
+#ifdef _DEBUG
+ else _ASSERTE(!"Bad dwImplAttrs");
+#endif
+
+ if(g_szAsmCodeIndent[0]) g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ {
+ szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,UNSCOPE());
+ if(pszClassName)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("// end of method %s::"), ProperName((char*)pszClassName));
+ strcpy_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT(ProperName((char*)pszMemberName)));
+ }
+ else
+ sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("// end of global method %s"), ProperName((char*)pszMemberName));
+ }
+ printLine(GUICookie, szString);
+ szString[0] = 0;
+ printLine(GUICookie, szString);
+
+ if(pszArgname)
+ {
+ for(ULONG i=0; i < ulArgs; i++)
+ {
+ if(pszArgname[i].name) VDELETE(pszArgname[i].name);
+ }
+ VDELETE(pszArgname);
+ }
+ g_tkMVarOwner = tkMVarOwner;
+ return TRUE;
+}
+#ifdef _PREFAST_
+#pragma warning(pop)
+#endif
+
+BOOL DumpField(mdToken FuncToken, const char *pszClassName,void *GUICookie, BOOL DumpBody)
+{
+ char *pszMemberName = NULL;//[MAX_MEMBER_LENGTH];
+ DWORD dwAttrs = 0;
+ CQuickBytes qbMemberSig;
+ PCCOR_SIGNATURE pComSig = NULL;
+ ULONG cComSig;
+ const char *szStr = NULL;//[1024];
+ char* szptr;
+
+ const char *psz;
+ if (FAILED(g_pImport->GetNameOfFieldDef(FuncToken, &psz)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, "%sERROR: FieldDef %08X has no signature", g_szAsmCodeIndent, FuncToken);
+ printError(GUICookie, sz);
+ return FALSE;
+ }
+ MAKE_NAME_IF_NONE(psz,FuncToken);
+
+ if (FAILED(g_pImport->GetFieldDefProps(FuncToken, &dwAttrs)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, "%sERROR: FieldDef %08X record error", g_szAsmCodeIndent, FuncToken);
+ printError(GUICookie, sz);
+ return FALSE;
+ }
+ if (g_fLimitedVisibility)
+ {
+ if(g_fHidePub && IsFdPublic(dwAttrs)) return FALSE;
+ if(g_fHidePriv && IsFdPrivate(dwAttrs)) return FALSE;
+ if(g_fHideFam && IsFdFamily(dwAttrs)) return FALSE;
+ if(g_fHideAsm && IsFdAssembly(dwAttrs)) return FALSE;
+ if(g_fHideFOA && IsFdFamORAssem(dwAttrs)) return FALSE;
+ if(g_fHideFAA && IsFdFamANDAssem(dwAttrs)) return FALSE;
+ if(g_fHidePrivScope && IsFdPrivateScope(dwAttrs)) return FALSE;
+ }
+
+ {
+ const char* psz1 = NULL;
+ if(IsFdPrivateScope(dwAttrs))
+ {
+ pszMemberName = new char[strlen(psz)+15];
+ sprintf_s(pszMemberName,strlen(psz)+15,"%s$PST%08X", psz,FuncToken );
+ }
+ else
+ {
+ pszMemberName = new char[strlen(psz)+3];
+ strcpy_s(pszMemberName, strlen(psz)+3, psz );
+ }
+ psz1 = ProperName(pszMemberName);
+ VDELETE(pszMemberName);
+ pszMemberName = new char[strlen(psz1)+1];
+ strcpy_s(pszMemberName,strlen(psz1)+1,psz1);
+ }
+ if (FAILED(g_pImport->GetSigOfFieldDef(FuncToken, &cComSig, &pComSig)))
+ {
+ pComSig = NULL;
+ }
+ if (cComSig == NULL)
+ {
+ char sz[2048];
+ sprintf_s(sz,2048,"%sERROR: field '%s' has no signature",g_szAsmCodeIndent,pszMemberName);
+ VDELETE(pszMemberName);
+ printError(GUICookie,sz);
+ return FALSE;
+ }
+ g_tkRefUser = FuncToken;
+
+ bool bRet = FALSE;
+ PAL_CPP_TRY {
+ szStr = PrettyPrintSig(pComSig, cComSig, (DumpBody ? pszMemberName : ""), &qbMemberSig, g_pImport,NULL);
+ }
+ PAL_CPP_CATCH_ALL
+ {
+ printError(GUICookie,"INVALID ADDRESS IN FIELD SIGNATURE");
+ bRet = TRUE;
+ } PAL_CPP_ENDTRY;
+
+ if (bRet)
+ return FALSE;
+
+ g_tkRefUser = 0;
+
+ if (g_Mode == MODE_DUMP_CLASS_METHOD || g_Mode == MODE_DUMP_CLASS_METHOD_SIG)
+ {
+ if (strcmp(pszMemberName, g_pszMethodToDump) != 0)
+ {
+ VDELETE(pszMemberName);
+ return FALSE;
+ }
+
+ if (g_Mode == MODE_DUMP_CLASS_METHOD_SIG)
+ {
+ // we want plain signature without token values and without the field name
+ BOOL fDumpTokens = g_fDumpTokens;
+ g_fDumpTokens = FALSE;
+
+ const char *pszPlainSig;
+ PAL_CPP_TRY
+ {
+ CQuickBytes qbTempSig;
+ pszPlainSig = PrettyPrintSig(pComSig, cComSig, "", &qbTempSig, g_pImport, NULL);
+ }
+ PAL_CPP_CATCH_ALL
+ {
+ pszPlainSig = "";
+ }
+ PAL_CPP_ENDTRY;
+
+ g_fDumpTokens = fDumpTokens;
+
+ if (strcmp(pszPlainSig, g_pszSigToDump) != 0)
+ {
+ VDELETE(pszMemberName);
+ return FALSE;
+ }
+ }
+ }
+ VDELETE(pszMemberName);
+
+ szptr = &szString[0];
+ if(DumpBody)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ", g_szAsmCodeIndent,ANCHORPT(KEYWORD(".field"),FuncToken));
+ if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),FuncToken);
+ }
+
+ // put offset (if any)
+ for(ULONG i=0; i < g_cFieldOffsets; i++)
+ {
+ if(g_rFieldOffset[i].ridOfField == FuncToken)
+ {
+ if(g_rFieldOffset[i].ulOffset != 0xFFFFFFFF) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"[%d] ",g_rFieldOffset[i].ulOffset);
+ break;
+ }
+ }
+
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)0));
+ if(IsFdPublic(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"public ");
+ if(IsFdPrivate(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"private ");
+ if(IsFdStatic(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"static ");
+ if(IsFdFamily(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"family ");
+ if(IsFdAssembly(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"assembly ");
+ if(IsFdFamANDAssem(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"famandassem ");
+ if(IsFdFamORAssem(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"famorassem ");
+ if(IsFdPrivateScope(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"privatescope ");
+ if(IsFdInitOnly(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"initonly ");
+ if(IsFdLiteral(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"literal ");
+ if(IsFdNotSerialized(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"notserialized ");
+ if(IsFdSpecialName(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"specialname ");
+ if(IsFdRTSpecialName(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"rtspecialname ");
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)-1));
+ if (IsFdPinvokeImpl(dwAttrs))
+ {
+ DWORD dwMappingFlags;
+ const char *szImportName;
+ mdModuleRef mrImportDLL;
+
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s(",KEYWORD("pinvokeimpl"));
+ if(FAILED(g_pImport->GetPinvokeMap(FuncToken,&dwMappingFlags,
+ &szImportName,&mrImportDLL))) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/* No map */"));
+ else
+ szptr = DumpPinvokeMap(dwMappingFlags, (strcmp(szImportName,psz)? szImportName : NULL),
+ mrImportDLL, szString,GUICookie);
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),") ");
+ }
+ szptr = DumpMarshaling(g_pImport,szString,SZSTRING_SIZE,FuncToken);
+
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s",szStr);
+
+ if (IsFdHasFieldRVA(dwAttrs)) // Do we have an RVA associated with this?
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), KEYWORD(" at "));
+
+ ULONG fieldRVA;
+ if (SUCCEEDED(g_pImport->GetFieldRVA(FuncToken, &fieldRVA)))
+ {
+ szptr = DumpDataPtr(&szString[strlen(szString)], fieldRVA, SizeOfField(FuncToken,g_pImport));
+ }
+ else
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),RstrUTF(IDS_E_NORVA));
+ }
+ }
+
+ // dump default value (if any):
+ if(IsFdHasDefault(dwAttrs) && DumpBody) DumpDefaultValue(FuncToken,szString,GUICookie);
+ printLine(GUICookie, szString);
+
+ if(DumpBody)
+ {
+ DumpCustomAttributes(FuncToken,GUICookie);
+ DumpPermissions(FuncToken,GUICookie);
+ }
+
+ return TRUE;
+
+}
+
+BOOL DumpEvent(mdToken FuncToken, const char *pszClassName, DWORD dwClassAttrs, void *GUICookie, BOOL DumpBody)
+{
+ DWORD dwAttrs;
+ mdToken tkEventType;
+ LPCSTR psz;
+ HENUMInternal hAssoc;
+ ASSOCIATE_RECORD rAssoc[128];
+ CQuickBytes qbMemberSig;
+ ULONG nAssoc;
+ char* szptr;
+
+ if (FAILED(g_pImport->GetEventProps(FuncToken,&psz,&dwAttrs,&tkEventType)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, "%sERROR: Invalid Event %08X record", g_szAsmCodeIndent, FuncToken);
+ printError(GUICookie, sz);
+ return FALSE;
+ }
+ MAKE_NAME_IF_NONE(psz,FuncToken);
+ if (g_Mode == MODE_DUMP_CLASS_METHOD || g_Mode == MODE_DUMP_CLASS_METHOD_SIG)
+ {
+ if (strcmp(psz, g_pszMethodToDump) != 0) return FALSE;
+ }
+
+ if (FAILED(g_pImport->EnumAssociateInit(FuncToken,&hAssoc)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, "%sERROR: MetaData error enumerating Associate for %08X", g_szAsmCodeIndent, FuncToken);
+ printError(GUICookie, sz);
+ return FALSE;
+ }
+
+ if ((nAssoc = hAssoc.m_ulCount))
+ {
+ memset(rAssoc,0,sizeof(rAssoc));
+ if (FAILED(g_pImport->GetAllAssociates(&hAssoc,rAssoc,nAssoc)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, "%sERROR: MetaData error enumerating all Associates", g_szAsmCodeIndent);
+ printError(GUICookie, sz);
+ return FALSE;
+ }
+
+ if (g_fLimitedVisibility)
+ {
+ unsigned i;
+ for (i=0; i < nAssoc;i++)
+ {
+ if ((TypeFromToken(rAssoc[i].m_memberdef) == mdtMethodDef) && g_pImport->IsValidToken(rAssoc[i].m_memberdef))
+ {
+ DWORD dwMethodAttrs;
+ if (FAILED(g_pImport->GetMethodDefProps(rAssoc[i].m_memberdef, &dwMethodAttrs)))
+ {
+ continue;
+ }
+ if(g_fHidePub && IsMdPublic(dwMethodAttrs)) continue;
+ if(g_fHidePriv && IsMdPrivate(dwMethodAttrs)) continue;
+ if(g_fHideFam && IsMdFamily(dwMethodAttrs)) continue;
+ if(g_fHideAsm && IsMdAssem(dwMethodAttrs)) continue;
+ if(g_fHideFOA && IsMdFamORAssem(dwMethodAttrs)) continue;
+ if(g_fHideFAA && IsMdFamANDAssem(dwMethodAttrs)) continue;
+ if(g_fHidePrivScope && IsMdPrivateScope(dwMethodAttrs)) continue;
+ break;
+ }
+ }
+ if (i >= nAssoc) return FALSE;
+ }
+ }
+
+ szptr = &szString[0];
+ if (DumpBody)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ", g_szAsmCodeIndent,KEYWORD(".event"));
+ if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),FuncToken);
+ }
+ else
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s : ",ProperName((char*)psz));
+ }
+
+ if(IsEvSpecialName(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("specialname "));
+ if(IsEvRTSpecialName(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("rtspecialname "));
+
+ if(RidFromToken(tkEventType)&&g_pImport->IsValidToken(tkEventType))
+ {
+ switch(TypeFromToken(tkEventType))
+ {
+ case mdtTypeRef:
+ case mdtTypeDef:
+ case mdtTypeSpec:
+ {
+ PrettyPrintToken(szString, tkEventType, g_pImport,GUICookie,0);
+ szptr = &szString[strlen(szString)];
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if(!DumpBody)
+ {
+ printLine(GUICookie,szString);
+ return TRUE;
+ }
+
+
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %s", ProperName((char*)psz));
+ printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+
+ DumpCustomAttributes(FuncToken,GUICookie);
+ DumpPermissions(FuncToken,GUICookie);
+
+ if(nAssoc)
+ {
+ for(unsigned i=0; i < nAssoc;i++)
+ {
+ mdToken tk = rAssoc[i].m_memberdef;
+ DWORD sem = rAssoc[i].m_dwSemantics;
+
+ szptr = &szString[0];
+ if(IsMsAddOn(sem)) szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".addon"));
+ else if(IsMsRemoveOn(sem)) szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".removeon"));
+ else if(IsMsFire(sem)) szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".fire"));
+ else if(IsMsOther(sem)) szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".other"));
+ else szptr+=sprintf_s(szptr,SZSTRING_SIZE,ERRORMSG("UNKNOWN SEMANTICS: 0x%X "),sem);
+
+ if(g_pImport->IsValidToken(tk))
+ PrettyPrintToken(szString, tk, g_pImport,GUICookie,0);
+ else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG("INVALID TOKEN 0x%8.8X"),tk);
+ printLine(GUICookie,szString);
+ }
+ }
+ if(g_szAsmCodeIndent[0]) g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,UNSCOPE());
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("// end of event %s::"),ProperName((char*)pszClassName));
+ strcpy_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT(ProperName((char*)psz)));
+ printLine(GUICookie,szString);
+ return TRUE;
+
+}
+
+BOOL DumpProp(mdToken FuncToken, const char *pszClassName, DWORD dwClassAttrs, void *GUICookie, BOOL DumpBody)
+{
+ DWORD dwAttrs;
+ LPCSTR psz;
+ HENUMInternal hAssoc;
+ ASSOCIATE_RECORD rAssoc[128];
+ CQuickBytes qbMemberSig;
+ PCCOR_SIGNATURE pComSig;
+ ULONG cComSig, nAssoc;
+ unsigned uStringLen = SZSTRING_SIZE;
+ char* szptr;
+
+ if (FAILED(g_pImport->GetPropertyProps(FuncToken,&psz,&dwAttrs,&pComSig,&cComSig)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, "%sERROR: Invalid Property %08X record", g_szAsmCodeIndent, FuncToken);
+ printError(GUICookie, sz);
+ return FALSE;
+ }
+ MAKE_NAME_IF_NONE(psz,FuncToken);
+ if(cComSig == 0)
+ {
+ char sz[2048];
+ sprintf_s(sz,2048,"%sERROR: property '%s' has no signature",g_szAsmCodeIndent,psz);
+ printError(GUICookie,sz);
+ return FALSE;
+ }
+
+ if (g_Mode == MODE_DUMP_CLASS_METHOD || g_Mode == MODE_DUMP_CLASS_METHOD_SIG)
+ {
+ if (strcmp(psz, g_pszMethodToDump) != 0) return FALSE;
+ }
+
+ if (FAILED(g_pImport->EnumAssociateInit(FuncToken,&hAssoc)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, "%sERROR: MetaData error enumerating Associate for %08X", g_szAsmCodeIndent, FuncToken);
+ printError(GUICookie, sz);
+ return FALSE;
+ }
+ if ((nAssoc = hAssoc.m_ulCount) != 0)
+ {
+ memset(rAssoc,0,sizeof(rAssoc));
+ if (FAILED(g_pImport->GetAllAssociates(&hAssoc,rAssoc,nAssoc)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, "%sERROR: MetaData error enumerating all Associates", g_szAsmCodeIndent);
+ printError(GUICookie, sz);
+ return FALSE;
+ }
+
+ if (g_fLimitedVisibility)
+ {
+ unsigned i;
+ for (i=0; i < nAssoc;i++)
+ {
+ if ((TypeFromToken(rAssoc[i].m_memberdef) == mdtMethodDef) && g_pImport->IsValidToken(rAssoc[i].m_memberdef))
+ {
+ DWORD dwMethodAttrs;
+ if (FAILED(g_pImport->GetMethodDefProps(rAssoc[i].m_memberdef, &dwMethodAttrs)))
+ {
+ continue;
+ }
+ if(g_fHidePub && IsMdPublic(dwMethodAttrs)) continue;
+ if(g_fHidePriv && IsMdPrivate(dwMethodAttrs)) continue;
+ if(g_fHideFam && IsMdFamily(dwMethodAttrs)) continue;
+ if(g_fHideAsm && IsMdAssem(dwMethodAttrs)) continue;
+ if(g_fHideFOA && IsMdFamORAssem(dwMethodAttrs)) continue;
+ if(g_fHideFAA && IsMdFamANDAssem(dwMethodAttrs)) continue;
+ if(g_fHidePrivScope && IsMdPrivateScope(dwMethodAttrs)) continue;
+ break;
+ }
+ }
+ if( i >= nAssoc) return FALSE;
+ }
+ }
+
+ szptr = &szString[0];
+ if (DumpBody)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ", g_szAsmCodeIndent,KEYWORD(".property"));
+ if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),FuncToken);
+ }
+ else
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s : ",ProperName((char*)psz));
+ }
+
+ if(IsPrSpecialName(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("specialname "));
+ if(IsPrRTSpecialName(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("rtspecialname "));
+
+ {
+ char pchDefault[] = "";
+ char *pch = pchDefault;
+ if(DumpBody)
+ {
+ pch = szptr+1;
+ strcpy_s(pch,SZSTRING_REMAINING_SIZE(pch),ProperName((char*)psz));
+ }
+ qbMemberSig.Shrink(0);
+ PrettyPrintMethodSig(szString, &uStringLen, &qbMemberSig, pComSig, cComSig,
+ pch, NULL, GUICookie);
+ if(IsPrHasDefault(dwAttrs) && DumpBody) DumpDefaultValue(FuncToken,szString,GUICookie);
+ }
+ printLine(GUICookie,szString);
+
+ if(DumpBody)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+
+ DumpCustomAttributes(FuncToken,GUICookie);
+ DumpPermissions(FuncToken,GUICookie);
+
+ if(nAssoc)
+ {
+ for(unsigned i=0; i < nAssoc;i++)
+ {
+ mdToken tk = rAssoc[i].m_memberdef;
+ DWORD sem = rAssoc[i].m_dwSemantics;
+
+ szptr = &szString[0];
+ if(IsMsSetter(sem)) szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".set"));
+ else if(IsMsGetter(sem)) szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".get"));
+ else if(IsMsOther(sem)) szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".other"));
+ else szptr+=sprintf_s(szptr,SZSTRING_SIZE,ERRORMSG("UNKNOWN SEMANTICS: 0x%X "),sem);
+
+ if(g_pImport->IsValidToken(tk))
+ PrettyPrintToken(szString, tk, g_pImport,GUICookie,0);
+ else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG("INVALID TOKEN 0x%8.8X"),tk);
+ printLine(GUICookie,szString);
+ }
+ }
+ if(g_szAsmCodeIndent[0]) g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,UNSCOPE());
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("// end of property %s::"),ProperName((char*)pszClassName));
+ strcpy_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT(ProperName((char*)psz)));
+ printLine(GUICookie,szString);
+ } // end if(DumpBody)
+ return TRUE;
+
+}
+
+BOOL DumpMembers(mdTypeDef cl, const char *pszClassNamespace, const char *pszClassName,
+ DWORD dwClassAttrs, DWORD dwEntryPointToken, void* GUICookie)
+{
+ HRESULT hr;
+ mdToken *pMemberList = NULL;
+ DWORD NumMembers, NumFields,NumMethods,NumEvents,NumProps;
+ DWORD i;
+ HENUMInternal hEnumMethod;
+ HENUMInternal hEnumField;
+ HENUMInternal hEnumEvent;
+ HENUMInternal hEnumProp;
+ CQuickBytes qbMemberSig;
+ BOOL ret;
+
+ // Get the total count of methods + fields
+ hr = g_pImport->EnumInit(mdtMethodDef, cl, &hEnumMethod);
+ if (FAILED(hr))
+ {
+FailedToEnum:
+ printLine(GUICookie,RstrUTF(IDS_E_MEMBRENUM));
+ ret = FALSE;
+ goto CloseHandlesAndReturn;
+ }
+ NumMembers = NumMethods = g_pImport->EnumGetCount(&hEnumMethod);
+
+
+ if (FAILED(g_pImport->EnumInit(mdtFieldDef, cl, &hEnumField))) goto FailedToEnum;
+ NumFields = g_pImport->EnumGetCount(&hEnumField);
+ NumMembers += NumFields;
+
+ if (FAILED(g_pImport->EnumInit(mdtEvent, cl, &hEnumEvent))) goto FailedToEnum;
+ NumEvents = g_pImport->EnumGetCount(&hEnumEvent);
+ NumMembers += NumEvents;
+
+ if (FAILED(g_pImport->EnumInit(mdtProperty, cl, &hEnumProp))) goto FailedToEnum;
+ NumProps = g_pImport->EnumGetCount(&hEnumProp);
+ NumMembers += NumProps;
+ ret = TRUE;
+
+ if(NumMembers)
+ {
+ pMemberList = new (nothrow) mdToken[NumMembers];
+ if(pMemberList == NULL) ret = FALSE;
+ }
+ if ((NumMembers == 0)||(pMemberList == NULL)) goto CloseHandlesAndReturn;
+
+ for (i = 0; g_pImport->EnumNext(&hEnumField, &pMemberList[i]); i++);
+ for (; g_pImport->EnumNext(&hEnumMethod, &pMemberList[i]); i++);
+ for (; g_pImport->EnumNext(&hEnumEvent, &pMemberList[i]); i++);
+ for (; g_pImport->EnumNext(&hEnumProp, &pMemberList[i]); i++);
+ _ASSERTE(i == NumMembers);
+
+ for (i = 0; i < NumMembers; i++)
+ {
+ mdToken tk = pMemberList[i];
+ if(g_pImport->IsValidToken(tk))
+ {
+ switch (TypeFromToken(tk))
+ {
+ case mdtFieldDef:
+ ret = DumpField(pMemberList[i], pszClassName, GUICookie,TRUE);
+ break;
+
+ case mdtMethodDef:
+ ret = DumpMethod(pMemberList[i], pszClassName, dwEntryPointToken,GUICookie,TRUE);
+ break;
+
+ case mdtEvent:
+ ret = DumpEvent(pMemberList[i], pszClassName, dwClassAttrs,GUICookie,TRUE);
+ break;
+
+ case mdtProperty:
+ ret = DumpProp(pMemberList[i], pszClassName, dwClassAttrs,GUICookie,TRUE);
+ break;
+
+ default:
+ {
+ char szStr[4096];
+ sprintf_s(szStr,4096,RstrUTF(IDS_E_ODDMEMBER),pMemberList[i],pszClassName);
+ printLine(GUICookie,szStr);
+ }
+ ret = FALSE;
+ break;
+ } // end switch
+ }
+ else
+ {
+ char szStr[256];
+ sprintf_s(szStr,256,ERRORMSG("INVALID MEMBER TOKEN: 0x%8.8X"),tk);
+ printLine(GUICookie,szStr);
+ ret= FALSE;
+ }
+ if(ret && (g_Mode == MODE_DUMP_CLASS_METHOD_SIG)) break;
+ } // end for
+ ret = TRUE;
+
+CloseHandlesAndReturn:
+ g_pImport->EnumClose(&hEnumMethod);
+ g_pImport->EnumClose(&hEnumField);
+ g_pImport->EnumClose(&hEnumEvent);
+ g_pImport->EnumClose(&hEnumProp);
+ if(pMemberList) delete[] pMemberList;
+ return ret;
+}
+BOOL GetClassLayout(mdTypeDef cl, ULONG* pulPackSize, ULONG* pulClassSize)
+{ // Dump class layout
+ HENUMInternal hEnumField;
+ BOOL ret = FALSE;
+
+ if(g_rFieldOffset)
+ VDELETE(g_rFieldOffset);
+ g_cFieldOffsets = 0;
+ g_cFieldsMax = 0;
+
+ if(RidFromToken(cl)==0) return TRUE;
+
+ if (SUCCEEDED(g_pImport->EnumInit(mdtFieldDef, cl, &hEnumField)))
+ {
+ g_cFieldsMax = g_pImport->EnumGetCount(&hEnumField);
+ g_pImport->EnumClose(&hEnumField);
+ }
+
+ if(SUCCEEDED(g_pImport->GetClassPackSize(cl,pulPackSize))) ret = TRUE;
+ else *pulPackSize = 0xFFFFFFFF;
+ if(SUCCEEDED(g_pImport->GetClassTotalSize(cl,pulClassSize))) ret = TRUE;
+ else *pulClassSize = 0xFFFFFFFF;
+
+ if(g_cFieldsMax)
+ {
+ MD_CLASS_LAYOUT Layout;
+ if(SUCCEEDED(g_pImport->GetClassLayoutInit(cl,&Layout)))
+ {
+ g_rFieldOffset = new COR_FIELD_OFFSET[g_cFieldsMax+1];
+ if(g_rFieldOffset)
+ {
+ COR_FIELD_OFFSET* pFO = g_rFieldOffset;
+ for(g_cFieldOffsets=0;
+ SUCCEEDED(g_pImport->GetClassLayoutNext(&Layout,&(pFO->ridOfField),&(pFO->ulOffset)))
+ &&RidFromToken(pFO->ridOfField);
+ g_cFieldOffsets++, pFO++) ret = TRUE;
+ }
+ }
+ }
+ return ret;
+}
+
+BOOL IsANestedInB(mdTypeDef A, mdTypeDef B)
+{
+ DWORD i;
+ for(i = 0; i < g_NumClasses; i++)
+ {
+ if(g_cl_list[i] == A)
+ {
+ A = g_cl_enclosing[i];
+ if(A == B) return TRUE;
+ if(A == mdTypeDefNil) return FALSE;
+ return IsANestedInB(A,B);
+ }
+ }
+ return FALSE;
+}
+mdTypeDef TopEncloser(mdTypeDef A)
+{
+ DWORD i;
+ for(i = 0; i < g_NumClasses; i++)
+ {
+ if(g_cl_list[i] == A)
+ {
+ if(g_cl_enclosing[i] == mdTypeDefNil) return A;
+ return TopEncloser(g_cl_enclosing[i]);
+ }
+ }
+ return A;
+}
+
+BOOL DumpClass(mdTypeDef cl, DWORD dwEntryPointToken, void* GUICookie, ULONG WhatToDump)
+// WhatToDump: 0-title,flags,extends,implements;
+// +1-pack,size and custom attrs;
+// +2-nested classes
+// +4-members
+{
+ char *pszClassName; // name associated with this CL
+ char *pszNamespace;
+ const char *pc1,*pc2;
+ DWORD dwClassAttrs;
+ mdTypeRef crExtends;
+ HRESULT hr;
+ mdInterfaceImpl ii;
+ DWORD NumInterfaces;
+ DWORD i;
+ HENUMInternal hEnumII; // enumerator for interface impl
+ //char *szString;
+ char* szptr;
+
+ mdToken tkVarOwner = g_tkVarOwner;
+ ULONG WhatToDumpOrig = WhatToDump;
+
+ if (FAILED(g_pImport->GetNameOfTypeDef(
+ cl,
+ &pc1, //&pszClassName,
+ &pc2))) //&pszNamespace
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), cl);
+ printError(GUICookie, sz);
+ g_tkVarOwner = tkVarOwner;
+ return FALSE;
+ }
+ MAKE_NAME_IF_NONE(pc1,cl);
+
+ if (g_Mode == MODE_DUMP_CLASS || g_Mode == MODE_DUMP_CLASS_METHOD || g_Mode == MODE_DUMP_CLASS_METHOD_SIG)
+ {
+ if(cl != g_tkClassToDump)
+ {
+ if(IsANestedInB(g_tkClassToDump,cl))
+ WhatToDump = 2; // nested classes only
+ else
+ return TRUE;
+ }
+ }
+
+ if (FAILED(g_pImport->GetTypeDefProps(
+ cl,
+ &dwClassAttrs,
+ &crExtends)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), cl);
+ printError(GUICookie, sz);
+ g_tkVarOwner = tkVarOwner;
+ return FALSE;
+ }
+
+ if(g_fLimitedVisibility)
+ {
+ if(g_fHidePub && (IsTdPublic(dwClassAttrs)||IsTdNestedPublic(dwClassAttrs))) return FALSE;
+ if(g_fHidePriv && (IsTdNotPublic(dwClassAttrs)||IsTdNestedPrivate(dwClassAttrs))) return FALSE;
+ if(g_fHideFam && IsTdNestedFamily(dwClassAttrs)) return FALSE;
+ if(g_fHideAsm && IsTdNestedAssembly(dwClassAttrs)) return FALSE;
+ if(g_fHideFOA && IsTdNestedFamORAssem(dwClassAttrs)) return FALSE;
+ if(g_fHideFAA && IsTdNestedFamANDAssem(dwClassAttrs)) return FALSE;
+ }
+
+ g_tkVarOwner = cl;
+
+ pszClassName = (char*)(pc1 ? pc1 : "");
+ pszNamespace = (char*)(pc2 ? pc2 : "");
+
+#if (0)
+
+ if((!IsTdNested(dwClassAttrs))&&(!(g_Mode & MODE_GUI))) // don't dump namespaces in GUI mode!
+ {
+ // take care of namespace, if any
+ if(strcmp(pszNamespace,g_szNamespace))
+ {
+ if(strlen(g_szNamespace))
+ {
+ if(g_szAsmCodeIndent[0]) g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,UNSCOPE());
+ sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("// end of namespace %s"),ProperName(g_szNamespace));
+ printLine(GUICookie,szString);
+ printLine(GUICookie,"");
+ }
+ strcpy_s(g_szNamespace,MAX_MEMBER_LENGTH,pszNamespace);
+ if(strlen(g_szNamespace))
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",
+ g_szAsmCodeIndent,KEYWORD(".namespace"), ProperName(g_szNamespace));
+ printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+ }
+ }
+ }
+
+#endif
+
+ szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".class"));
+ if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%8.8X*/ "),cl);
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)0));
+ if (IsTdInterface(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"interface ");
+ if (IsTdPublic(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"public ");
+ if (IsTdNotPublic(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"private ");
+ if (IsTdAbstract(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"abstract ");
+ if (IsTdAutoLayout(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"auto ");
+ if (IsTdSequentialLayout(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"sequential ");
+ if (IsTdExplicitLayout(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"explicit ");
+ if (IsTdAnsiClass(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"ansi ");
+ if (IsTdUnicodeClass(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"unicode ");
+ if (IsTdAutoClass(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"autochar ");
+ if (IsTdImport(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"import ");
+ if (IsTdWindowsRuntime(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"windowsruntime ");
+ if (IsTdSerializable(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"serializable ");
+ if (IsTdSealed(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"sealed ");
+ if (IsTdNestedPublic(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"nested public ");
+ if (IsTdNestedPrivate(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"nested private ");
+ if (IsTdNestedFamily(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"nested family ");
+ if (IsTdNestedAssembly(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"nested assembly ");
+ if (IsTdNestedFamANDAssem(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"nested famandassem ");
+ if (IsTdNestedFamORAssem(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"nested famorassem ");
+ if (IsTdBeforeFieldInit(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"beforefieldinit ");
+ if (IsTdSpecialName(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"specialname ");
+ if (IsTdRTSpecialName(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"rtspecialname ");
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)-1));
+ if(*pszNamespace != 0)
+ szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s.",ProperName(pszNamespace));
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),WhatToDump > 2 ? ANCHORPT(ProperName(pszClassName),cl) : JUMPPT(ProperName(pszClassName),cl));
+
+ szptr = DumpGenericPars(szString, cl, GUICookie,TRUE);
+ if (szptr == NULL)
+ {
+ g_tkVarOwner = tkVarOwner;
+ return FALSE;
+ }
+
+ printLine(GUICookie,szString);
+ if (!IsNilToken(crExtends))
+ {
+ CQuickBytes out;
+ szptr = szString;
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s %s ",g_szAsmCodeIndent,KEYWORD("extends"));
+ if(g_pImport->IsValidToken(crExtends))
+ PrettyPrintToken(szString, crExtends, g_pImport,GUICookie,cl);
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG("INVALID TOKEN: 0x%8.8X"),crExtends);
+ printLine(GUICookie,szString);
+ }
+
+ hr = g_pImport->EnumInit(
+ mdtInterfaceImpl,
+ cl,
+ &hEnumII);
+ if (FAILED(hr))
+ {
+ printError(GUICookie,RstrUTF(IDS_E_ENUMINIT));
+ g_tkVarOwner = tkVarOwner;
+ return FALSE;
+ }
+
+ NumInterfaces = g_pImport->EnumGetCount(&hEnumII);
+
+ if (NumInterfaces > 0)
+ {
+ CQuickBytes out;
+ mdTypeRef crInterface;
+ for (i=0; g_pImport->EnumNext(&hEnumII, &ii); i++)
+ {
+ szptr = szString;
+ if(i) szptr+=sprintf_s(szptr,SZSTRING_SIZE, "%s ",g_szAsmCodeIndent);
+ else szptr+=sprintf_s(szptr,SZSTRING_SIZE, "%s %s ",g_szAsmCodeIndent,KEYWORD("implements"));
+ if (FAILED(g_pImport->GetTypeOfInterfaceImpl(ii, &crInterface)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), ii);
+ printError(GUICookie, sz);
+ g_tkVarOwner = tkVarOwner;
+ return FALSE;
+ }
+ if(g_pImport->IsValidToken(crInterface))
+ PrettyPrintToken(szString, crInterface, g_pImport,GUICookie,cl);
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG("INVALID TOKEN: 0x%8.8X"),crInterface);
+ if(i < NumInterfaces-1) strcat_s(szString, SZSTRING_SIZE,",");
+ printLine(GUICookie,szString);
+ out.Shrink(0);
+ }
+ // The assertion will fire if the enumerator is bad
+ _ASSERTE(NumInterfaces == i);
+
+ g_pImport->EnumClose(&hEnumII);
+ }
+ if(WhatToDump == 0) // 0 = title only
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,SCOPE(),UNSCOPE());
+ printLine(GUICookie,szString);
+ g_tkVarOwner = tkVarOwner;
+ return TRUE;
+ }
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+
+ ULONG ulPackSize=0xFFFFFFFF,ulClassSize=0xFFFFFFFF;
+ if(WhatToDump & 1)
+ {
+ if(GetClassLayout(cl,&ulPackSize,&ulClassSize))
+ { // Dump class layout
+ if(ulPackSize != 0xFFFFFFFF)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s %d",g_szAsmCodeIndent,KEYWORD(".pack"),ulPackSize);
+ printLine(GUICookie,szString);
+ }
+ if(ulClassSize != 0xFFFFFFFF)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s %d",g_szAsmCodeIndent,KEYWORD(".size"),ulClassSize);
+ printLine(GUICookie,szString);
+ }
+ }
+ DumpCustomAttributes(cl,GUICookie);
+ // Dev11 #10745
+ // Dump InterfaceImpl custom attributes here
+ if (NumInterfaces > 0 && g_fShowCA)
+ {
+ hr = g_pImport->EnumInit(
+ mdtInterfaceImpl,
+ cl,
+ &hEnumII);
+ if (FAILED(hr))
+ {
+ printError(GUICookie,RstrUTF(IDS_E_ENUMINIT));
+ g_tkVarOwner = tkVarOwner;
+ return FALSE;
+ }
+
+ ASSERT_AND_CHECK(NumInterfaces == g_pImport->EnumGetCount(&hEnumII));
+ CQuickBytes out;
+ mdTypeRef crInterface;
+ for (i = 0; g_pImport->EnumNext(&hEnumII, &ii); i++)
+ {
+ HENUMInternal hEnum;
+ mdCustomAttribute tkCA;
+ bool fFirst = true;
+
+ if (FAILED(g_pImport->EnumInit(mdtCustomAttribute, ii,&hEnum)))
+ {
+ return FALSE;
+ }
+ while(g_pImport->EnumNext(&hEnum,&tkCA) && RidFromToken(tkCA))
+ {
+ if (fFirst)
+ {
+ // Print .interfaceImpl type {type} before the custom attribute list
+ szptr = szString;
+ szptr += sprintf_s(szptr, SZSTRING_SIZE, "%s.%s ", g_szAsmCodeIndent, KEYWORD("interfaceimpl type"));
+ if (FAILED(g_pImport->GetTypeOfInterfaceImpl(ii, &crInterface)))
+ {
+ char sz[2048];
+ sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), ii);
+ printError(GUICookie, sz);
+ g_tkVarOwner = tkVarOwner;
+ return FALSE;
+ }
+ if(g_pImport->IsValidToken(crInterface))
+ PrettyPrintToken(szString, crInterface, g_pImport,GUICookie,cl);
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG("INVALID TOKEN: 0x%8.8X"),crInterface);
+ printLine(GUICookie,szString);
+ out.Shrink(0);
+
+ szptr = szString;
+ fFirst = false;
+ }
+ DumpCustomAttribute(tkCA,GUICookie,false);
+ }
+ g_pImport->EnumClose( &hEnum);
+ }
+ // The assertion will fire if the enumerator is bad
+ _ASSERTE(NumInterfaces == i);
+
+ g_pImport->EnumClose(&hEnumII);
+ }
+ DumpGenericParsCA(cl,GUICookie);
+ DumpPermissions(cl,GUICookie);
+ }
+
+ // Dump method impls declared in this class whose implementing methods belong somewhere else:
+ if(WhatToDump & 1) // 1 - dump headers
+ {
+ for(i = 0; i < g_NumMI; i++)
+ {
+ if(((*g_pmi_list)[i].tkClass == cl)&&((*g_pmi_list)[i].tkBodyParent != cl))
+ {
+ BOOL bOverridingTypeSpec;
+ PrettyPrintOverrideDecl(i,szString,GUICookie,cl,&bOverridingTypeSpec);
+ strcat_s(szString, SZSTRING_SIZE,KEYWORD(" with "));
+
+ if (bOverridingTypeSpec)
+ {
+ // If PrettyPrintOverrideDecl printed the 'method' keyword, we need it here as well
+ // to satisfy the following grammar rule (simplified):
+ // _OVERRIDE METHOD_ ... DCOLON methodName ... WITH_ METHOD_ ... DCOLON methodName ...
+ strcat_s(szString, SZSTRING_SIZE,KEYWORD("method "));
+ }
+
+ PrettyPrintToken(szString, (*g_pmi_list)[i].tkBody, g_pImport,GUICookie,0);
+ printLine(GUICookie,szString);
+ }
+ }
+ }
+ if(WhatToDump & 2) // nested classes
+ {
+ BOOL fRegetClassLayout=FALSE;
+ DWORD dwMode = g_Mode;
+
+ if(g_Mode == MODE_DUMP_CLASS)
+ g_Mode = MODE_DUMP_ALL;
+
+ for(i = 0; i < g_NumClasses; i++)
+ {
+ if(g_cl_enclosing[i] == cl)
+ {
+ DumpClass(g_cl_list[i],dwEntryPointToken,GUICookie,WhatToDumpOrig);
+ if(g_fAbortDisassembly)
+ {
+ g_Mode = dwMode;
+ return FALSE;
+ }
+ fRegetClassLayout = TRUE;
+ }
+ }
+ if(fRegetClassLayout) GetClassLayout(cl,&ulPackSize,&ulClassSize);
+ g_Mode = dwMode;
+ }
+
+ if(WhatToDump & 4)
+ {
+ DumpMembers(cl, pszNamespace, pszClassName, dwClassAttrs, dwEntryPointToken,GUICookie);
+#ifndef FEATURE_CORECLR
+ if(!ProgressStep()) g_fAbortDisassembly = TRUE;
+#endif
+ }
+
+ if(g_szAsmCodeIndent[0]) g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ szptr = szString;
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s %s// end of class ",g_szAsmCodeIndent,UNSCOPE(),COMMENT((char*)0));
+ if(*pszNamespace != 0) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s.",ProperName(pszNamespace));
+ sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s%s", ProperName(pszClassName),COMMENT((char*)-1));
+ printLine(GUICookie,szString);
+ if(!(g_Mode & MODE_GUI))
+ {
+ printLine(GUICookie,"");
+ }
+ g_tkVarOwner = tkVarOwner;
+ return TRUE;
+}
+
+
+
+void DumpGlobalMethods(DWORD dwEntryPointToken)
+{
+ HENUMInternal hEnumMethod;
+ mdToken FuncToken;
+ DWORD i;
+ CQuickBytes qbMemberSig;
+
+ if (FAILED(g_pImport->EnumGlobalFunctionsInit(&hEnumMethod)))
+ return;
+
+ for (i = 0; g_pImport->EnumNext(&hEnumMethod, &FuncToken); i++)
+ {
+ if ((i == 0)&&(!(g_Mode & MODE_GUI)))
+ {
+ printLine(g_pFile,"");
+ printLine(g_pFile,COMMENT("// ================== GLOBAL METHODS ========================="));
+ printLine(g_pFile,"");
+ }
+ if(DumpMethod(FuncToken, NULL, dwEntryPointToken, g_pFile, TRUE)&&
+ (g_Mode == MODE_DUMP_CLASS_METHOD || g_Mode == MODE_DUMP_CLASS_METHOD_SIG)) break;
+
+#ifndef FEATURE_CORECLR
+ if(!ProgressStep())
+ {
+ g_fAbortDisassembly = TRUE;
+ break;
+ }
+#endif
+ }
+ g_pImport->EnumClose(&hEnumMethod);
+ if(i)
+ {
+ printLine(g_pFile,"");
+ printLine(g_pFile,COMMENT("// ============================================================="));
+ printLine(g_pFile,"");
+ }
+}
+
+void DumpGlobalFields()
+{
+ HENUMInternal hEnum;
+ mdToken FieldToken;
+ DWORD i;
+ CQuickBytes qbMemberSig;
+
+ if (FAILED(g_pImport->EnumGlobalFieldsInit(&hEnum)))
+ return;
+
+ for (i = 0; g_pImport->EnumNext(&hEnum, &FieldToken); i++)
+ {
+ if ((i == 0)&&(!(g_Mode & MODE_GUI)))
+ {
+ printLine(g_pFile,"");
+ printLine(g_pFile,COMMENT("// ================== GLOBAL FIELDS =========================="));
+ printLine(g_pFile,"");
+ }
+ if(DumpField(FieldToken, NULL, g_pFile, TRUE)&&
+ (g_Mode == MODE_DUMP_CLASS_METHOD || g_Mode == MODE_DUMP_CLASS_METHOD_SIG)) break;
+ }
+ g_pImport->EnumClose(&hEnum);
+ if(i)
+ {
+ printLine(g_pFile,"");
+ printLine(g_pFile,COMMENT("// ============================================================="));
+ printLine(g_pFile,"");
+ }
+}
+
+void DumpVTables(IMAGE_COR20_HEADER *CORHeader, void* GUICookie)
+{
+ IMAGE_COR_VTABLEFIXUP *pFixup,*pDummy;
+ DWORD iCount;
+ DWORD i;
+ USHORT iSlot;
+ char* szStr = &szString[0];
+
+ if (VAL32(CORHeader->VTableFixups.VirtualAddress) == 0) return;
+
+ if(g_Mode & MODE_GUI) szStr += 2; // no need for "//" in GUI mode
+
+ sprintf_s(szString,SZSTRING_SIZE,"// VTableFixup Directory:");
+ printLine(GUICookie,szStr);
+
+ // Pull back a pointer to the guy.
+ iCount = VAL32(CORHeader->VTableFixups.Size) / sizeof(IMAGE_COR_VTABLEFIXUP);
+ if ((g_pPELoader->getVAforRVA(VAL32(CORHeader->VTableFixups.VirtualAddress), (void **) &pFixup) == FALSE)
+ ||(g_pPELoader->getVAforRVA(VAL32(CORHeader->VTableFixups.VirtualAddress)+VAL32(CORHeader->VTableFixups.Size)-1, (void **) &pDummy) == FALSE))
+ {
+ printLine(GUICookie,RstrUTF(IDS_E_VTFUTABLE));
+ goto exit;
+ }
+
+ // Walk every v-table fixup entry and dump the slots.
+ for (i=0; i<iCount; i++)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"// IMAGE_COR_VTABLEFIXUP[%d]:", i);
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// RVA: 0x%08x", VAL32(pFixup->RVA));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Count: 0x%04x", VAL16(pFixup->Count));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Type: 0x%04x", VAL16(pFixup->Type));
+ printLine(GUICookie,szStr);
+
+ BYTE *pSlot;
+ if (g_pPELoader->getVAforRVA(VAL32(pFixup->RVA), (void **) &pSlot) == FALSE)
+ {
+ printLine(GUICookie,RstrUTF(IDS_E_BOGUSRVA));
+ goto NextEntry;
+ }
+
+ for (iSlot=0; iSlot<pFixup->Count; iSlot++)
+ {
+ mdMethodDef tkMethod = VAL32(*(DWORD *) pSlot);
+ if (pFixup->Type & VAL16(COR_VTABLE_32BIT))
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"// [0x%04x] (0x%08x)", iSlot, tkMethod);
+ pSlot += sizeof(DWORD);
+ }
+ else
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"// [0x%04x] (0x%16x)", iSlot, VAL64(*(unsigned __int64 *) pSlot));
+ pSlot += sizeof(unsigned __int64);
+ }
+ printLine(GUICookie,szStr);
+
+ ValidateToken(tkMethod, mdtMethodDef);
+ }
+
+ // Pointer to next fixup entry.
+NextEntry:
+ ++pFixup;
+ }
+
+exit:
+ printLine(GUICookie,"");
+}
+
+
+void DumpEATTable(IMAGE_COR20_HEADER *CORHeader, void* GUICookie)
+{
+ BYTE *pFixup,*pDummy;
+ DWORD iCount;
+ DWORD BufferRVA;
+ DWORD i;
+ char* szStr = &szString[0];
+ if(g_Mode & MODE_GUI) szStr += 2; // no need for "//" in GUI mode
+
+ sprintf_s(szString,SZSTRING_SIZE,"// Export Address Table Jumps:");
+ printLine(GUICookie,szStr);
+
+ if (VAL32(CORHeader->ExportAddressTableJumps.VirtualAddress) == 0)
+ {
+ printLine(GUICookie,RstrUTF(IDS_E_NODATA));
+ return;
+ }
+
+ // Pull back a pointer to the guy.
+ iCount = VAL32(CORHeader->ExportAddressTableJumps.Size) / IMAGE_COR_EATJ_THUNK_SIZE;
+ if ((g_pPELoader->getVAforRVA(VAL32(CORHeader->ExportAddressTableJumps.VirtualAddress), (void **) &pFixup) == FALSE)
+ ||(g_pPELoader->getVAforRVA(VAL32(CORHeader->ExportAddressTableJumps.VirtualAddress)+VAL32(CORHeader->ExportAddressTableJumps.Size)-1, (void **) &pDummy) == FALSE))
+ {
+ printLine(GUICookie,RstrUTF(IDS_E_EATJTABLE));
+ goto exit;
+ }
+
+ // Quick sanity check on the linker.
+ if (VAL32(CORHeader->ExportAddressTableJumps.Size) % IMAGE_COR_EATJ_THUNK_SIZE)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_EATJSIZE),
+ VAL32(CORHeader->ExportAddressTableJumps.Size), IMAGE_COR_EATJ_THUNK_SIZE);
+ printLine(GUICookie,szStr);
+ }
+
+ // Walk every v-table fixup entry and dump the slots.
+ BufferRVA = VAL32(CORHeader->ExportAddressTableJumps.VirtualAddress);
+ for (i=0; i<iCount; i++)
+ {
+ ULONG ReservedFlag = VAL32(*(ULONG *) (pFixup + sizeof(ULONG)));
+ sprintf_s(szString,SZSTRING_SIZE,"// Fixup Jump Entry [%d], at RVA 0x%08x:", i, BufferRVA);
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// RVA of slot: 0x%08x", VAL32(*(ULONG *) pFixup));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Reserved flag: 0x%08x", ReservedFlag);
+ printLine(GUICookie,szStr);
+ if (ReservedFlag != 0)
+ {
+ printLine(GUICookie,RstrUTF(IDS_E_RESFLAGS));
+ }
+
+ pFixup += IMAGE_COR_EATJ_THUNK_SIZE;
+ BufferRVA += IMAGE_COR_EATJ_THUNK_SIZE;
+ }
+
+exit:
+ printLine(GUICookie,"");
+}
+
+
+void DumpCodeManager(IMAGE_COR20_HEADER *CORHeader, void* GUICookie)
+{
+ char* szStr = &szString[0];
+ if(g_Mode & MODE_GUI) szStr += 2; // no need for "//" in GUI mode
+ sprintf_s(szString,SZSTRING_SIZE,"// Code Manager Table:");
+ printLine(GUICookie,szStr);
+ if (!VAL32(CORHeader->CodeManagerTable.Size))
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"// default");
+ printLine(GUICookie,szStr);
+ return;
+ }
+
+ const GUID *pcm;
+ if (g_pPELoader->getVAforRVA(VAL32(CORHeader->CodeManagerTable.VirtualAddress), (void **) &pcm) == FALSE)
+ {
+ printLine(GUICookie,RstrUTF(IDS_E_CODEMGRTBL));
+ return;
+ }
+
+ sprintf_s(szString,SZSTRING_SIZE,"// [index] ID");
+ printLine(GUICookie,szStr);
+ ULONG iCount = VAL32(CORHeader->CodeManagerTable.Size) / sizeof(GUID);
+ for (ULONG i=0; i<iCount; i++)
+ {
+ WCHAR rcguid[128];
+ GUID Guid = *pcm;
+ SwapGuid(&Guid);
+ StringFromGUID2(Guid, rcguid, NumItems(rcguid));
+ sprintf_s(szString,SZSTRING_SIZE,"// [0x%08x] %S", i, rcguid);
+ printLine(GUICookie,szStr);
+ pcm++;
+ }
+ printLine(GUICookie,"");
+}
+
+void DumpSectionHeaders(IMAGE_SECTION_HEADER* pSH, USHORT nSH, void* GUICookie)
+{
+ char* szStr = &szString[0];
+ char name[16];
+ if(g_Mode & MODE_GUI) szStr += 2; // no need for "//" in GUI mode
+ printLine(GUICookie,"");
+ strcpy_s(szString,SZSTRING_SIZE,"// Image sections:");
+ printLine(GUICookie,szStr);
+ for(USHORT iSH=0; iSH < nSH; iSH++,pSH++)
+ {
+ strncpy_s(name,16,(const char*)(pSH->Name),8);
+ name[8]=0;
+ sprintf_s(szString,SZSTRING_SIZE,"// %s",name);
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Virtual Size", pSH->Misc.VirtualSize);
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Virtual Address", pSH->VirtualAddress);
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Size of Raw Data", pSH->SizeOfRawData);
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Pointer to Raw Data", pSH->PointerToRawData);
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Pointer to Relocations", pSH->PointerToRelocations);
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Pointer to Linenumbers", pSH->PointerToLinenumbers);
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%04x Number of Relocations", pSH->NumberOfRelocations);
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%04x Number of Linenumbers", pSH->NumberOfLinenumbers);
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Characteristics", pSH->Characteristics);
+ printLine(GUICookie,szStr);
+ if((pSH->Characteristics & IMAGE_SCN_SCALE_INDEX))
+ {
+ strcpy_s(szString,SZSTRING_SIZE,"// SCALE_INDEX");
+ printLine(GUICookie,szStr);
+ }
+ if((pSH->Characteristics & IMAGE_SCN_CNT_CODE))
+ {
+ strcpy_s(szString,SZSTRING_SIZE,"// CNT_CODE");
+ printLine(GUICookie,szStr);
+ }
+ if((pSH->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA))
+ {
+ strcpy_s(szString,SZSTRING_SIZE,"// CNT_INITIALIZED_DATA");
+ printLine(GUICookie,szStr);
+ }
+ if((pSH->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA))
+ {
+ strcpy_s(szString,SZSTRING_SIZE,"// CNT_UNINITIALIZED_DATA");
+ printLine(GUICookie,szStr);
+ }
+ if((pSH->Characteristics & IMAGE_SCN_NO_DEFER_SPEC_EXC))
+ {
+ strcpy_s(szString,SZSTRING_SIZE,"// NO_DEFER_SPEC_EXC");
+ printLine(GUICookie,szStr);
+ }
+ if((pSH->Characteristics & IMAGE_SCN_LNK_NRELOC_OVFL))
+ {
+ strcpy_s(szString,SZSTRING_SIZE,"// LNK_NRELOC_OVFL");
+ printLine(GUICookie,szStr);
+ }
+ if((pSH->Characteristics & IMAGE_SCN_MEM_DISCARDABLE))
+ {
+ strcpy_s(szString,SZSTRING_SIZE,"// MEM_DISCARDABLE");
+ printLine(GUICookie,szStr);
+ }
+ if((pSH->Characteristics & IMAGE_SCN_MEM_NOT_CACHED))
+ {
+ strcpy_s(szString,SZSTRING_SIZE,"// MEM_NOT_CACHED");
+ printLine(GUICookie,szStr);
+ }
+ if((pSH->Characteristics & IMAGE_SCN_MEM_NOT_PAGED))
+ {
+ strcpy_s(szString,SZSTRING_SIZE,"// MEM_NOT_PAGED");
+ printLine(GUICookie,szStr);
+ }
+ if((pSH->Characteristics & IMAGE_SCN_MEM_SHARED))
+ {
+ strcpy_s(szString,SZSTRING_SIZE,"// MEM_SHARED");
+ printLine(GUICookie,szStr);
+ }
+ if((pSH->Characteristics & IMAGE_SCN_MEM_EXECUTE))
+ {
+ strcpy_s(szString,SZSTRING_SIZE,"// MEM_EXECUTE");
+ printLine(GUICookie,szStr);
+ }
+ if((pSH->Characteristics & IMAGE_SCN_MEM_READ))
+ {
+ strcpy_s(szString,SZSTRING_SIZE,"// MEM_READ");
+ printLine(GUICookie,szStr);
+ }
+ if((pSH->Characteristics & IMAGE_SCN_MEM_WRITE))
+ {
+ strcpy_s(szString,SZSTRING_SIZE,"// MEM_WRITE");
+ printLine(GUICookie,szStr);
+ }
+ printLine(GUICookie,"");
+ }
+}
+
+void DumpBaseReloc(const char *szName, IMAGE_DATA_DIRECTORY *pDir, void* GUICookie)
+{
+ char* szStr = &szString[0];
+ if(g_Mode & MODE_GUI) szStr += 2; // no need for "//" in GUI mode
+ sprintf_s(szString,SZSTRING_SIZE,"// %s", szName);
+ printLine(GUICookie,szStr);
+ if (!VAL32(pDir->Size))
+ {
+ printLine(GUICookie,RstrUTF(IDS_E_NODATA));
+ return;
+ }
+ char *pBegin, *pEnd;
+ DWORD *pdw, i, Nentries;
+ WORD *pw;
+ if (g_pPELoader->getVAforRVA(VAL32(pDir->VirtualAddress), (void **) &pBegin) == FALSE)
+ {
+ printLine(GUICookie,RstrUTF(IDS_E_IMPORTDATA));
+ return;
+ }
+ pEnd = pBegin + VAL32(pDir->Size);
+ for(pdw = (DWORD*)pBegin; pdw < (DWORD*)pEnd; )
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Page RVA", *pdw);
+ printLine(GUICookie,szStr);
+ pdw++;
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Block Size", *pdw);
+ printLine(GUICookie,szStr);
+ Nentries = (*pdw - 2*sizeof(DWORD)) / sizeof(WORD);
+ pdw++;
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Number of Entries", Nentries);
+ printLine(GUICookie,szStr);
+
+ for(i = 1, pw = (WORD*)pdw; i <= Nentries; i++, pw++)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"// Entry %d: Type 0x%x Offset 0x%08x", i, ((*pw)>>12), ((*pw)&0x0FFF));
+ printLine(GUICookie,szStr);
+ }
+ if((Nentries & 1)) pw++; // to make pdw DWORD-aligned
+ pdw = (DWORD*)pw;
+ printLine(GUICookie,"");
+ }
+}
+void DumpIAT(const char *szName, IMAGE_DATA_DIRECTORY *pDir, void* GUICookie)
+{
+ char* szStr = &szString[0];
+ if(g_Mode & MODE_GUI) szStr += 2; // no need for "//" in GUI mode
+ sprintf_s(szString,SZSTRING_SIZE,"// %s", szName);
+ printLine(GUICookie,szStr);
+ if (!VAL32(pDir->Size))
+ {
+ printLine(GUICookie,RstrUTF(IDS_E_NODATA));
+ return;
+ }
+
+ const char *szDLLName;
+ const IMAGE_IMPORT_DESCRIPTOR *pImportDesc;
+
+ if (g_pPELoader->getVAforRVA(VAL32(pDir->VirtualAddress), (void **) &pImportDesc) == FALSE)
+ {
+ printLine(GUICookie,RstrUTF(IDS_E_IMPORTDATA));
+ return;
+ }
+
+ const DWORD *pImportTableID;
+ while (VAL32(pImportDesc->FirstThunk))
+ {
+ if (g_pPELoader->getVAforRVA(VAL32(pImportDesc->Name), (void **) &szDLLName) == FALSE ||
+ g_pPELoader->getVAforRVA(VAL32(pImportDesc->FirstThunk), (void **) &pImportTableID) == FALSE)
+ {
+ printLine(GUICookie,RstrUTF(IDS_E_IMPORTDATA));
+ return;
+ }
+
+ sprintf_s(szString,SZSTRING_SIZE,"// DLL : %s", szDLLName);
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Import Address Table", VAL32(pImportDesc->FirstThunk));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Import Name Table", VAL32(pImportDesc->Name));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// %-8d Time Date Stamp", VAL32(pImportDesc->TimeDateStamp));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// %-8d Index of First Forwarder Reference", VAL32(pImportDesc->ForwarderChain));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"//");
+ printLine(GUICookie,szStr);
+
+ for ( ; VAL32(*pImportTableID); pImportTableID++)
+ {
+ if (VAL32(*pImportTableID) & 0x80000000)
+ sprintf_s(szString,SZSTRING_SIZE,"// by Ordinal %d", VAL32(*pImportTableID) & 0x7fffffff);
+ else
+ {
+ const IMAGE_IMPORT_BY_NAME *pName;
+ if(g_pPELoader->getVAforRVA(VAL32(*pImportTableID) & 0x7fffffff, (void **) &pName))
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%04x %s", VAL16(pName->Hint), pName->Name);
+ else
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x bad RVA of IMAGE_IMPORT_BY_NAME", VAL32(*pImportTableID));
+ }
+ printLine(GUICookie,szStr);
+ }
+ printLine(GUICookie,"");
+
+ // Next import descriptor.
+ pImportDesc++;
+ }
+}
+
+struct MDStreamHeader
+{
+ DWORD Reserved;
+ BYTE Major;
+ BYTE Minor;
+ BYTE Heaps;
+ BYTE Rid;
+ ULONGLONG MaskValid;
+ ULONGLONG Sorted;
+};
+
+void DumpMetadataHeader(const char *szName, IMAGE_DATA_DIRECTORY *pDir, void* GUICookie)
+{
+ char* szStr = &szString[0];
+ if(g_Mode & MODE_GUI) szStr += 2; // no need for "//" in GUI mode
+ printLine(GUICookie,"");
+ sprintf_s(szString,SZSTRING_SIZE,"// %s", szName);
+ printLine(GUICookie,szStr);
+ if (!VAL32(pDir->Size))
+ {
+ printLine(GUICookie,RstrUTF(IDS_E_NODATA));
+ return;
+ }
+
+ const STORAGESIGNATURE *pSSig;
+ char verstr[1024];
+
+ if (g_pPELoader->getVAforRVA(VAL32(pDir->VirtualAddress), (void **) &pSSig) == FALSE)
+ {
+ printLine(GUICookie,RstrUTF(IDS_E_IMPORTDATA));
+ return;
+ }
+ strcpy_s(szString,SZSTRING_SIZE,"// Storage Signature:");
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Signature", VAL32(pSSig->lSignature));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%04x Major Version", VAL16(pSSig->iMajorVer));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%04x Minor Version", VAL16(pSSig->iMinorVer));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Extra Data Offset", VAL32(pSSig->iExtraData));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Version String Length", VAL32(pSSig->iVersionString));
+ printLine(GUICookie,szStr);
+ memset(verstr,0,1024);
+ strncpy_s(verstr,1024,(const char*)(pSSig->pVersion),VAL32(pSSig->iVersionString));
+ sprintf_s(szString,SZSTRING_SIZE,"// '%s' Version String", verstr);
+ printLine(GUICookie,szStr);
+
+ size_t pb = (size_t)pSSig;
+ pb += (3*sizeof(DWORD)+2*sizeof(WORD)+VAL32(pSSig->iVersionString)+3)&~3;
+ PSTORAGEHEADER pSHdr = (PSTORAGEHEADER)pb;
+ strcpy_s(szString,SZSTRING_SIZE,"// Storage Header:");
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%02x Flags", pSHdr->fFlags);
+ printLine(GUICookie,szStr);
+ short nStr = VAL16(pSHdr->iStreams);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%04x Number of Streams", nStr);
+ if(nStr > 5)
+ {
+ strcat_s(szString, SZSTRING_SIZE, " -- BOGUS!");
+ nStr = 5;
+ }
+ printLine(GUICookie,szStr);
+
+ PSTORAGESTREAM pStr = (PSTORAGESTREAM)(pSHdr+1);
+ BYTE* pbMDstream = NULL;
+ size_t cbMDstream = 0;
+ for(short iStr = 1; iStr <= nStr; iStr++)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"// Stream %d:",iStr);
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Offset", VAL32(pStr->iOffset));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Size", VAL32(pStr->iSize));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// '%s' Name", pStr->rcName);
+ printLine(GUICookie,szStr);
+ if((strcmp(pStr->rcName,"#-")==0)||(strcmp(pStr->rcName,"#~")==0))
+ {
+ pbMDstream = (BYTE*)pSSig + VAL32(pStr->iOffset);
+ cbMDstream = VAL32(pStr->iSize);
+ }
+
+ pb = (size_t)pStr;
+ pb += (2*sizeof(DWORD)+strlen(pStr->rcName)+1+3)&~3;
+ pStr = (PSTORAGESTREAM)pb;
+ }
+ if((pbMDstream)&&(cbMDstream >= sizeof(MDStreamHeader)))
+ {
+ printLine(GUICookie,"");
+ strcpy_s(szString,SZSTRING_SIZE,"// Metadata Stream Header:");
+ printLine(GUICookie,szStr);
+
+ MDStreamHeader* pMDSH = (MDStreamHeader*)pbMDstream;
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Reserved", VAL32(pMDSH->Reserved));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%02x Major", pMDSH->Major);
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%02x Minor", pMDSH->Minor);
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%02x Heaps", pMDSH->Heaps);
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%02x Rid", pMDSH->Rid);
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%016I64x MaskValid", (ULONGLONG)GET_UNALIGNED_VAL64(&(pMDSH->MaskValid)));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%016I64x Sorted", (ULONGLONG)GET_UNALIGNED_VAL64(&(pMDSH->Sorted)));
+ printLine(GUICookie,szStr);
+ }
+}
+void DumpEntryPoint(DWORD dwAddrOfEntryPoint,DWORD dwEntryPointSize,void* GUICookie)
+{
+ BYTE* pB;
+ char* szStr = &szString[0];
+ char* szptr = szStr+2;
+ DWORD i;
+ if(g_Mode & MODE_GUI) szStr += 2; // no need for "//" in GUI mode
+ printLine(GUICookie,"");
+ strcpy_s(szString,SZSTRING_SIZE,"// Entry point code:");
+ printLine(GUICookie,szStr);
+ if (g_pPELoader->getVAforRVA(dwAddrOfEntryPoint, (void **) &pB) == FALSE)
+ {
+ printLine(GUICookie,"Bad RVA of entry point");
+ return;
+ }
+ if(dwEntryPointSize == 48) pB -= 32;
+ // on IA64, AddressOfEntryPoint points at PLabelDescriptor, not at the stub itself
+ for(i=0; i<dwEntryPointSize; i++)
+ {
+ szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%2.2X ",pB[i]);
+ }
+ printLine(GUICookie,szStr);
+}
+
+#define DUMP_DIRECTORY(szName, Directory) \
+ sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x [0x%08x] address [size] of " szName, \
+ VAL32(Directory.VirtualAddress), VAL32(Directory.Size)); \
+ printLine(GUICookie,szStr)
+
+#ifdef _PREFAST_
+#pragma warning(push)
+#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
+#endif
+void DumpHeader(IMAGE_COR20_HEADER *CORHeader, void* GUICookie)
+{
+ char* szStr = &szString[0];
+ if(g_Mode & MODE_GUI) szStr += 2; // no need for "//" in GUI mode
+ DWORD dwAddrOfEntryPoint=0, dwEntryPointSize=0;
+
+ PIMAGE_DOS_HEADER pDOSHeader = g_pPELoader->dosHeader();
+
+ strcpy_s(szString,SZSTRING_SIZE,"// ----- DOS Header:");
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Magic: 0x%04x", VAL16(pDOSHeader->e_magic));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Bytes on last page: 0x%04x", VAL16(pDOSHeader->e_cblp));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Pages in file: 0x%04x", VAL16(pDOSHeader->e_cp));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Relocations: 0x%04x", VAL16(pDOSHeader->e_crlc));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of header (paragraphs):0x%04x", VAL16(pDOSHeader->e_cparhdr));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Min extra paragraphs: 0x%04x", VAL16(pDOSHeader->e_minalloc));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Max extra paragraphs: 0x%04x", VAL16(pDOSHeader->e_maxalloc));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Initial (relative) SS: 0x%04x", VAL16(pDOSHeader->e_ss));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Initial SP: 0x%04x", VAL16(pDOSHeader->e_sp));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Checksum: 0x%04x", VAL16(pDOSHeader->e_csum));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Initial IP: 0x%04x", VAL16(pDOSHeader->e_ip));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Initial (relative) CS: 0x%04x", VAL16(pDOSHeader->e_ip));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// File addr. of reloc table: 0x%04x", VAL16(pDOSHeader->e_lfarlc));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Overlay number: 0x%04x", VAL16(pDOSHeader->e_ovno));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// OEM identifier: 0x%04x", VAL16(pDOSHeader->e_oemid));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// OEM info: 0x%04x", VAL16(pDOSHeader->e_oeminfo));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// File addr. of COFF header: 0x%04x", VAL16(pDOSHeader->e_lfanew));
+ printLine(GUICookie,szStr);
+
+ strcpy_s(szString,SZSTRING_SIZE,"// ----- COFF/PE Headers:");
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Signature: 0x%08x", VAL32(g_pPELoader->Signature()));
+ printLine(GUICookie,szStr);
+
+ strcpy_s(szString,SZSTRING_SIZE,"// ----- COFF Header:");
+ printLine(GUICookie,szStr);
+
+ PIMAGE_FILE_HEADER pCOFF = g_pPELoader->coffHeader();
+ sprintf_s(szString,SZSTRING_SIZE,"// Machine: 0x%04x", VAL16(pCOFF->Machine));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Number of sections: 0x%04x", VAL16(pCOFF->NumberOfSections));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Time-date stamp: 0x%08x", VAL32(pCOFF->TimeDateStamp));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Ptr to symbol table: 0x%08x", VAL32(pCOFF->PointerToSymbolTable));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Number of symbols: 0x%08x", VAL32(pCOFF->NumberOfSymbols));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of optional header: 0x%04x", VAL16(pCOFF->SizeOfOptionalHeader));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Characteristics: 0x%04x", VAL16(pCOFF->Characteristics));
+ printLine(GUICookie,szStr);
+
+
+ if (g_pPELoader->IsPE32())
+ {
+ IMAGE_NT_HEADERS32 *pNTHeader = g_pPELoader->ntHeaders32();
+ IMAGE_OPTIONAL_HEADER32 *pOptHeader = &pNTHeader->OptionalHeader;
+
+ strcpy_s(szString,SZSTRING_SIZE,"// ----- PE Optional Header (32 bit):");
+ printLine(GUICookie,szStr);
+
+ sprintf_s(szString,SZSTRING_SIZE,"// Magic: 0x%04x", VAL16(pOptHeader->Magic));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Major linker version: 0x%02x", VAL16(pOptHeader->MajorLinkerVersion));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Minor linker version: 0x%02x", VAL16(pOptHeader->MinorLinkerVersion));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of code: 0x%08x", VAL32(pOptHeader->SizeOfCode));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of init.data: 0x%08x", VAL32(pOptHeader->SizeOfInitializedData));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of uninit.data: 0x%08x", VAL32(pOptHeader->SizeOfUninitializedData));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Addr. of entry point: 0x%08x", VAL32(pOptHeader->AddressOfEntryPoint));
+ printLine(GUICookie,szStr);
+ dwAddrOfEntryPoint = VAL32(pOptHeader->AddressOfEntryPoint);
+ dwEntryPointSize = 6;
+ sprintf_s(szString,SZSTRING_SIZE,"// Base of code: 0x%08x", VAL32(pOptHeader->BaseOfCode));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Base of data: 0x%08x", VAL32(pOptHeader->BaseOfData));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Image base: 0x%08x", VAL32(pOptHeader->ImageBase));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Section alignment: 0x%08x", VAL32(pOptHeader->SectionAlignment));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// File alignment: 0x%08x", VAL32(pOptHeader->FileAlignment));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Major OS version: 0x%04x", VAL16(pOptHeader->MajorOperatingSystemVersion));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Minor OS version: 0x%04x", VAL16(pOptHeader->MinorOperatingSystemVersion));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Major image version: 0x%04x", VAL16(pOptHeader->MajorImageVersion));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Minor image version: 0x%04x", VAL16(pOptHeader->MinorImageVersion));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Major subsystem version: 0x%04x", VAL16(pOptHeader->MajorSubsystemVersion));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Minor subsystem version: 0x%04x", VAL16(pOptHeader->MinorSubsystemVersion));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of image: 0x%08x", VAL32(pOptHeader->SizeOfImage));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of headers: 0x%08x", VAL32(pOptHeader->SizeOfHeaders));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Checksum: 0x%08x", VAL32(pOptHeader->CheckSum));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Subsystem: 0x%04x", VAL16(pOptHeader->Subsystem));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// DLL characteristics: 0x%04x", VAL16(pOptHeader->DllCharacteristics));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of stack reserve: 0x%08x", VAL32(pOptHeader->SizeOfStackReserve));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of stack commit: 0x%08x", VAL32(pOptHeader->SizeOfStackCommit));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of heap reserve: 0x%08x", VAL32(pOptHeader->SizeOfHeapReserve));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of heap commit: 0x%08x", VAL32(pOptHeader->SizeOfHeapCommit));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Loader flags: 0x%08x", VAL32(pOptHeader->LoaderFlags));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Directories: 0x%08x", VAL32(pOptHeader->NumberOfRvaAndSizes));
+ printLine(GUICookie,szStr);
+ DUMP_DIRECTORY("Export Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]);
+ DUMP_DIRECTORY("Import Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]);
+ DUMP_DIRECTORY("Resource Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE]);
+ DUMP_DIRECTORY("Exception Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]);
+ DUMP_DIRECTORY("Security Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY]);
+ DUMP_DIRECTORY("Base Relocation Table: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]);
+ DUMP_DIRECTORY("Debug Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]);
+ DUMP_DIRECTORY("Architecture Specific: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_ARCHITECTURE]);
+ DUMP_DIRECTORY("Global Pointer: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR]);
+ DUMP_DIRECTORY("TLS Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS]);
+ DUMP_DIRECTORY("Load Config Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG]);
+ DUMP_DIRECTORY("Bound Import Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT]);
+ DUMP_DIRECTORY("Import Address Table: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT]);
+ DUMP_DIRECTORY("Delay Load IAT: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]);
+ DUMP_DIRECTORY("CLR Header: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR]);
+ printLine(GUICookie,"");
+
+ DumpSectionHeaders((IMAGE_SECTION_HEADER*)(pOptHeader+1),pNTHeader->FileHeader.NumberOfSections,GUICookie);
+ DumpBaseReloc("Base Relocation Table",&pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC],GUICookie);
+ DumpIAT("Import Address Table", &pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT],GUICookie);
+ DumpIAT("Delay Load Import Address Table", &pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT],GUICookie);
+ }
+ else
+ {
+ IMAGE_NT_HEADERS64 *pNTHeader = g_pPELoader->ntHeaders64();
+ IMAGE_OPTIONAL_HEADER64 *pOptHeader = &pNTHeader->OptionalHeader;
+
+ strcpy_s(szString,SZSTRING_SIZE,"// ----- PE Optional Header (64 bit):");
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Magic: 0x%04x", VAL16(pOptHeader->Magic));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Major linker version: 0x%02x", VAL16(pOptHeader->MajorLinkerVersion));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Minor linker version: 0x%02x", VAL16(pOptHeader->MinorLinkerVersion));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of code: 0x%08x", VAL32(pOptHeader->SizeOfCode));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of init.data: 0x%08x", VAL32(pOptHeader->SizeOfInitializedData));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of uninit.data: 0x%08x", VAL32(pOptHeader->SizeOfUninitializedData));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Addr. of entry point: 0x%08x", VAL32(pOptHeader->AddressOfEntryPoint));
+ printLine(GUICookie,szStr);
+ dwAddrOfEntryPoint = VAL32(pOptHeader->AddressOfEntryPoint);
+ dwEntryPointSize = (VAL16(pCOFF->Machine)==IMAGE_FILE_MACHINE_IA64) ? 48 : 12;
+ sprintf_s(szString,SZSTRING_SIZE,"// Base of code: 0x%08x", VAL32(pOptHeader->BaseOfCode));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Image base: 0x%016I64x", VAL64(pOptHeader->ImageBase));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Section alignment: 0x%08x", VAL32(pOptHeader->SectionAlignment));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// File alignment: 0x%08x", VAL32(pOptHeader->FileAlignment));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Major OS version: 0x%04x", VAL16(pOptHeader->MajorOperatingSystemVersion));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Minor OS version: 0x%04x", VAL16(pOptHeader->MinorOperatingSystemVersion));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Major image version: 0x%04x", VAL16(pOptHeader->MajorImageVersion));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Minor image version: 0x%04x", VAL16(pOptHeader->MinorImageVersion));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Major subsystem version: 0x%04x", VAL16(pOptHeader->MajorSubsystemVersion));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Minor subsystem version: 0x%04x", VAL16(pOptHeader->MinorSubsystemVersion));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of image: 0x%08x", VAL32(pOptHeader->SizeOfImage));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of headers: 0x%08x", VAL32(pOptHeader->SizeOfHeaders));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Checksum: 0x%08x", VAL32(pOptHeader->CheckSum));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Subsystem: 0x%04x", VAL16(pOptHeader->Subsystem));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// DLL characteristics: 0x%04x", VAL16(pOptHeader->DllCharacteristics));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of stack reserve: 0x%016I64x", VAL64(pOptHeader->SizeOfStackReserve));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of stack commit: 0x%016I64x", VAL64(pOptHeader->SizeOfStackCommit));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of heap reserve: 0x%016I64x", VAL64(pOptHeader->SizeOfHeapReserve));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Size of heap commit: 0x%016I64x", VAL64(pOptHeader->SizeOfHeapCommit));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Loader flags: 0x%08x", VAL32(pOptHeader->LoaderFlags));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Directories: 0x%08x", VAL32(pOptHeader->NumberOfRvaAndSizes));
+ printLine(GUICookie,szStr);
+
+ DUMP_DIRECTORY("Export Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]);
+ DUMP_DIRECTORY("Import Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]);
+ DUMP_DIRECTORY("Resource Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE]);
+ DUMP_DIRECTORY("Exception Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]);
+ DUMP_DIRECTORY("Security Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY]);
+ DUMP_DIRECTORY("Base Relocation Table: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]);
+ DUMP_DIRECTORY("Debug Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]);
+ DUMP_DIRECTORY("Architecture Specific: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_ARCHITECTURE]);
+ DUMP_DIRECTORY("Global Pointer: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR]);
+ DUMP_DIRECTORY("TLS Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS]);
+ DUMP_DIRECTORY("Load Config Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG]);
+ DUMP_DIRECTORY("Bound Import Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT]);
+ DUMP_DIRECTORY("Import Address Table: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT]);
+ DUMP_DIRECTORY("Delay Load IAT: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]);
+ DUMP_DIRECTORY("CLR Header: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR]);
+ printLine(GUICookie,"");
+
+ DumpSectionHeaders((IMAGE_SECTION_HEADER*)(pOptHeader+1),pNTHeader->FileHeader.NumberOfSections,GUICookie);
+ DumpBaseReloc("Base Relocation Table",&pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC],GUICookie);
+ DumpIAT("Import Address Table", &pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT],GUICookie);
+ DumpIAT("Delay Load Import Address Table", &pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT],GUICookie);
+ }
+ if(dwAddrOfEntryPoint != 0) DumpEntryPoint(dwAddrOfEntryPoint,dwEntryPointSize,GUICookie);
+ printLine(GUICookie,"");
+ printLine(GUICookie,"");
+ if (!CORHeader)
+ {
+ printLine(GUICookie,RstrUTF(IDS_E_COMIMAGE));
+ return;
+ }
+ strcpy_s(szString,SZSTRING_SIZE,"// ----- CLR Header:");
+ printLine(GUICookie,szStr);
+
+ sprintf_s(szString,SZSTRING_SIZE,"// Header size: 0x%08x", VAL32(CORHeader->cb));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Major runtime version: 0x%04x", VAL16(CORHeader->MajorRuntimeVersion));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Minor runtime version: 0x%04x", VAL16(CORHeader->MinorRuntimeVersion));
+ printLine(GUICookie,szStr);
+ // Metadata
+ DUMP_DIRECTORY("Metadata Directory: ", CORHeader->MetaData);
+ sprintf_s(szString,SZSTRING_SIZE,"// Flags: 0x%08x", VAL32(CORHeader->Flags));
+ printLine(GUICookie,szStr);
+ sprintf_s(szString,SZSTRING_SIZE,"// Entry point token: 0x%08x",
+ VAL32(IMAGE_COR20_HEADER_FIELD(*CORHeader, EntryPointToken)));
+ printLine(GUICookie,szStr);
+ // Binding
+ DUMP_DIRECTORY("Resources Directory: ", CORHeader->Resources);
+ DUMP_DIRECTORY("Strong Name Signature: ", CORHeader->StrongNameSignature);
+ DUMP_DIRECTORY("CodeManager Table: ", CORHeader->CodeManagerTable);
+
+ // Fixups
+ DUMP_DIRECTORY("VTableFixups Directory: ", CORHeader->VTableFixups);
+ DUMP_DIRECTORY("Export Address Table: ", CORHeader->ExportAddressTableJumps);
+
+ // Managed Native Code
+ DUMP_DIRECTORY("Precompile Header: ", CORHeader->ManagedNativeHeader);
+
+ DumpMetadataHeader("Metadata Header",&(CORHeader->MetaData),GUICookie);
+}
+#ifdef _PREFAST_
+#pragma warning(pop)
+#endif
+
+
+void DumpHeaderDetails(IMAGE_COR20_HEADER *CORHeader, void* GUICookie)
+{
+ printLine(GUICookie,"");
+ DumpCodeManager(CORHeader,GUICookie);
+ printLine(GUICookie,"");
+ DumpVTables(CORHeader,GUICookie);
+ printLine(GUICookie,"");
+ DumpEATTable(CORHeader,GUICookie);
+ printLine(GUICookie,"");
+}
+
+
+void WritePerfData(const char *KeyDesc, const char *KeyName, const char *UnitDesc, const char *UnitName, void* Value, BOOL IsInt)
+{
+
+ DWORD BytesWritten;
+
+ if(!g_fDumpToPerfWriter) return;
+
+ if (!g_PerfDataFilePtr)
+ {
+ if((g_PerfDataFilePtr = WszCreateFile(W("c:\\temp\\perfdata.dat"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL) ) == INVALID_HANDLE_VALUE)
+ {
+ printLine(NULL,"PefTimer::LogStoppedTime(): Unable to open the FullPath file. No performance data will be generated");
+ g_fDumpToPerfWriter = FALSE;
+ return;
+ }
+ WriteFile(g_PerfDataFilePtr,"ExecTime=0\r\n",13,&BytesWritten,NULL);
+ WriteFile(g_PerfDataFilePtr,"ExecUnit=bytes\r\n",17,&BytesWritten,NULL);
+ WriteFile(g_PerfDataFilePtr,"ExecUnitDescr=File Size\r\n",26,&BytesWritten,NULL);
+ WriteFile(g_PerfDataFilePtr,"ExeciDirection=False\r\n",23,&BytesWritten,NULL);
+ }
+
+ char ValueStr[10];
+ char TmpStr[201];
+
+ if (IsInt)
+ {
+ sprintf_s(ValueStr,10,"%d",(int)*(int*)Value);
+ }
+ else
+ {
+ sprintf_s(ValueStr,10,"%5.2f",(float)*(float*)Value);
+ }
+ sprintf_s(TmpStr, 201, "%s=%s\r\n", KeyName, ValueStr);
+ WriteFile(g_PerfDataFilePtr, TmpStr, (DWORD)strlen(TmpStr), &BytesWritten, NULL);
+
+ sprintf_s(TmpStr, 201, "%s Descr=%s\r\n", KeyName, KeyDesc);
+ WriteFile(g_PerfDataFilePtr, TmpStr, (DWORD)strlen(TmpStr), &BytesWritten, NULL);
+
+ sprintf_s(TmpStr, 201, "%s Unit=%s\r\n", KeyName, UnitName);
+ WriteFile(g_PerfDataFilePtr, TmpStr, (DWORD)strlen(TmpStr), &BytesWritten, NULL);
+
+ sprintf_s(TmpStr, 201, "%s Unit Descr=%s\r\n", KeyName, UnitDesc);
+ WriteFile(g_PerfDataFilePtr, TmpStr, (DWORD)strlen(TmpStr), &BytesWritten, NULL);
+
+ sprintf_s(TmpStr, 201, "%s IDirection=%s\r\n", KeyName, "False");
+ WriteFile(g_PerfDataFilePtr, TmpStr, (DWORD)strlen(TmpStr), &BytesWritten, NULL);
+}
+
+void WritePerfDataInt(const char *KeyDesc, const char *KeyName, const char *UnitDesc, const char *UnitName, int Value)
+{
+ WritePerfData(KeyDesc,KeyName,UnitDesc,UnitName, (void*)&Value, TRUE);
+}
+void WritePerfDataFloat(const char *KeyDesc, const char *KeyName, const char *UnitDesc, const char *UnitName, float Value)
+{
+ WritePerfData(KeyDesc,KeyName,UnitDesc,UnitName, (void*)&Value, FALSE);
+}
+
+
+IMetaDataTables *pITables = NULL;
+//ULONG sizeRec, count;
+//int size, size2;
+int metaSize = 0;
+__int64 fTableSeen;
+inline void TableSeen(unsigned long n) { fTableSeen |= (I64(1) << n); }
+inline int IsTableSeen(unsigned long n) { return (fTableSeen & (I64(1) << n)) ? 1 : 0;}
+inline void TableSeenReset() { fTableSeen = 0;}
+
+void DumpTable(unsigned long Table, const char *TableName, void* GUICookie)
+{
+ char *szStr = &szString[0];
+ const char **ppTableName = 0;
+ int size;
+ ULONG sizeRec, count;
+
+ if(g_Mode & MODE_GUI) szStr += 2; // no need for "//" in GUI mode
+
+ // Record that this table has been seen.
+ TableSeen(Table);
+
+ // If no name passed in, get from table info.
+ if (!TableName)
+ ppTableName = &TableName;
+
+ pITables->GetTableInfo(Table, &sizeRec, &count, NULL, NULL, ppTableName);
+ if(count > 0)
+ {
+ metaSize += size = count * sizeRec;
+ WritePerfDataInt(TableName,TableName,"count","count",count);
+ WritePerfDataInt(TableName,TableName,"bytes","bytes",size);
+ sprintf_s(szString,SZSTRING_SIZE,"// %-14s- %4d (%d bytes)", TableName, count, size);
+ printLine(GUICookie,szStr);
+ }
+}
+
+
+
+#ifdef _PREFAST_
+#pragma warning(push)
+#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
+#endif
+void DumpStatistics(IMAGE_COR20_HEADER *CORHeader, void* GUICookie)
+{
+ int fileSize, miscPESize, miscCOMPlusSize, methodHeaderSize, methodBodySize;
+ int methodBodies, fatHeaders, tinyHeaders, deprecatedHeaders;
+ int size, size2;
+ int fatSections, smallSections;
+ ULONG methodDefs;
+ ULONG i;
+ ULONG sizeRec, count;
+ char buf[MAX_MEMBER_LENGTH];
+ char* szStr = &szString[0];
+ if(g_Mode & MODE_GUI) szStr += 2; // no need for "//" in GUI mode
+
+ TableSeenReset();
+ metaSize = 0;
+
+ sprintf_s(szString,SZSTRING_SIZE,"// File size : %d", fileSize = SafeGetFileSize(g_pPELoader->getHFile(), NULL));
+ printLine(GUICookie,szStr);
+
+ WritePerfDataInt("FileSize","FileSize","standard byte","bytes",fileSize);
+
+ if (g_pPELoader->IsPE32())
+ {
+ size = VAL32(((IMAGE_DOS_HEADER*) g_pPELoader->getHModule())->e_lfanew) +
+ sizeof(IMAGE_NT_HEADERS32) - sizeof(IMAGE_OPTIONAL_HEADER32) +
+ VAL16(g_pPELoader->ntHeaders32()->FileHeader.SizeOfOptionalHeader) +
+ VAL16(g_pPELoader->ntHeaders32()->FileHeader.NumberOfSections) * sizeof(IMAGE_SECTION_HEADER);
+ size2 = (size + VAL32(g_pPELoader->ntHeaders32()->OptionalHeader.FileAlignment) - 1) & ~(VAL32(g_pPELoader->ntHeaders32()->OptionalHeader.FileAlignment) - 1);
+ }
+ else
+ {
+ size = VAL32(((IMAGE_DOS_HEADER*) g_pPELoader->getHModule())->e_lfanew) +
+ sizeof(IMAGE_NT_HEADERS64) - sizeof(IMAGE_OPTIONAL_HEADER64) +
+ VAL16(g_pPELoader->ntHeaders64()->FileHeader.SizeOfOptionalHeader) +
+ VAL16(g_pPELoader->ntHeaders64()->FileHeader.NumberOfSections) * sizeof(IMAGE_SECTION_HEADER);
+ size2 = (size + VAL32(g_pPELoader->ntHeaders64()->OptionalHeader.FileAlignment) - 1) & ~(VAL32(g_pPELoader->ntHeaders64()->OptionalHeader.FileAlignment) - 1);
+ }
+
+ DWORD sizeOfHeaders;
+
+ if (g_pPELoader->IsPE32())
+ {
+ sizeOfHeaders = VAL32(g_pPELoader->ntHeaders32()->OptionalHeader.SizeOfHeaders);
+
+ WritePerfDataInt("PE header size", "PE header size", "standard byte", "bytes", sizeOfHeaders);
+ WritePerfDataInt("PE header size used", "PE header size used", "standard byte", "bytes", size);
+ WritePerfDataFloat("PE header size", "PE header size", "percentage", "percentage", (float)((sizeOfHeaders * 100) / fileSize));
+ sprintf_s(szString,SZSTRING_SIZE,"// PE header size : %d (%d used) (%5.2f%%)",
+ sizeOfHeaders, size, (double) (sizeOfHeaders * 100) / fileSize);
+
+ printLine(GUICookie,szStr);
+ miscPESize = 0;
+
+ for (i=0; i < VAL32(g_pPELoader->ntHeaders32()->OptionalHeader.NumberOfRvaAndSizes); ++i)
+ {
+ // Skip the CLR header.
+ if (i != 15) miscPESize += (int) VAL32(g_pPELoader->ntHeaders32()->OptionalHeader.DataDirectory[i].Size);
+ }
+ }
+ else
+ {
+ sizeOfHeaders = VAL32(g_pPELoader->ntHeaders64()->OptionalHeader.SizeOfHeaders);
+
+ WritePerfDataInt("PE+ header size", "PE header size", "standard byte", "bytes", sizeOfHeaders);
+ WritePerfDataInt("PE+ header size used", "PE header size used", "standard byte", "bytes", size);
+ WritePerfDataFloat("PE+ header size", "PE header size", "percentage", "percentage", (float)((sizeOfHeaders * 100) / fileSize));
+
+ sprintf_s(szString,SZSTRING_SIZE,"// PE header size : %d (%d used) (%5.2f%%)",
+ sizeOfHeaders, size, (double) (sizeOfHeaders * 100) / fileSize);
+
+ printLine(GUICookie,szStr);
+ miscPESize = 0;
+
+ for (i=0; i < VAL32(g_pPELoader->ntHeaders64()->OptionalHeader.NumberOfRvaAndSizes); ++i)
+ {
+ // Skip the CLR header.
+ if (i != IMAGE_DIRECTORY_ENTRY_COMHEADER) miscPESize += (int) VAL32(g_pPELoader->ntHeaders64()->OptionalHeader.DataDirectory[i].Size);
+ }
+ }
+
+ WritePerfDataInt("PE additional info", "PE additional info", "standard byte", "bytes",miscPESize);
+ WritePerfDataFloat("PE additional info", "PE additional info", "percentage", "percent", (float) ((miscPESize * 100) / fileSize));
+
+ sprintf_s(buf, MAX_MEMBER_LENGTH, "PE additional info : %d", miscPESize);
+ sprintf_s(szString,SZSTRING_SIZE,"// %-40s (%5.2f%%)", buf, (double) (miscPESize * 100) / fileSize);
+ printLine(GUICookie,szStr);
+
+ WORD numberOfSections;
+ if (g_pPELoader->IsPE32())
+ {
+ numberOfSections = VAL16(g_pPELoader->ntHeaders32()->FileHeader.NumberOfSections);
+ }
+ else
+ {
+ numberOfSections = VAL16(g_pPELoader->ntHeaders64()->FileHeader.NumberOfSections);
+ }
+
+ WritePerfDataInt("Num.of PE sections", "Num.of PE sections", "Nbr of sections", "sections",numberOfSections);
+ sprintf_s(szString,SZSTRING_SIZE,"// Num.of PE sections : %d", numberOfSections);
+
+ printLine(GUICookie,szStr);
+
+ WritePerfDataInt("CLR header size", "CLR header size", "byte", "bytes",VAL32(CORHeader->cb));
+ WritePerfDataFloat("CLR header size", "CLR header size", "percentage", "percent",(float) ((VAL32(CORHeader->cb) * 100) / fileSize));
+
+ sprintf_s(buf, MAX_MEMBER_LENGTH, "CLR header size : %d", VAL32(CORHeader->cb));
+ sprintf_s(szString,SZSTRING_SIZE,"// %-40s (%5.2f%%)", buf, (double) (VAL32(CORHeader->cb) * 100) / fileSize);
+ printLine(GUICookie,szStr);
+
+ DWORD dwMetaSize = g_cbMetaData;
+ WritePerfDataInt("CLR meta-data size", "CLR meta-data size", "bytes", "bytes",dwMetaSize);
+ WritePerfDataFloat("CLR meta-data size", "CLR meta-data size", "percentage", "percent",(float) ((dwMetaSize * 100) / fileSize));
+
+ sprintf_s(buf, MAX_MEMBER_LENGTH, "CLR meta-data size : %d", dwMetaSize);
+ sprintf_s(szString,SZSTRING_SIZE,"// %-40s (%5.2f%%)", buf, (double) (dwMetaSize * 100) / fileSize);
+ printLine(GUICookie,szStr);
+
+ IMAGE_DATA_DIRECTORY *pFirst = &CORHeader->Resources;
+ ULONG32 iCount = (ULONG32)((BYTE *) &CORHeader->ManagedNativeHeader - (BYTE *) &CORHeader->Resources) / sizeof(IMAGE_DATA_DIRECTORY) + 1;
+ miscCOMPlusSize = 0;
+ for (ULONG32 iDir=0; iDir<iCount; iDir++)
+ {
+ miscCOMPlusSize += VAL32(pFirst->Size);
+ pFirst++;
+ }
+
+ WritePerfDataInt("CLR Additional info", "CLR Additional info", "bytes", "bytes",miscCOMPlusSize);
+ WritePerfDataFloat("CLR Additional info", "CLR Additional info", "percentage", "percent",(float) ((miscCOMPlusSize * 100) / fileSize));
+
+ sprintf_s(buf, MAX_MEMBER_LENGTH, "CLR additional info : %d", miscCOMPlusSize);
+ sprintf_s(szString,SZSTRING_SIZE,"// %-40s (%5.2f%%)", buf, (double) (miscCOMPlusSize * 100) / fileSize);
+ printLine(GUICookie,szStr);
+
+ // Go through each method def collecting some statistics.
+ methodHeaderSize = methodBodySize = 0;
+ methodBodies = fatHeaders = tinyHeaders = deprecatedHeaders = fatSections = smallSections = 0;
+ methodDefs = g_pImport->GetCountWithTokenKind(mdtMethodDef);
+ for (i=1; i <= methodDefs; ++i) {
+ ULONG rva;
+ DWORD flags;
+
+ if (FAILED(g_pImport->GetMethodImplProps(TokenFromRid(i, mdtMethodDef), &rva, &flags)))
+ {
+ continue;
+ }
+ if ((rva != 0)&&(IsMiIL(flags) || IsMiOPTIL(flags))) // We don't handle native yet.
+ {
+ ++methodBodies;
+
+ COR_ILMETHOD_FAT *pMethod;
+ g_pPELoader->getVAforRVA(rva, (void **) &pMethod);
+ if (pMethod->IsFat())
+ {
+ ++fatHeaders;
+
+ methodHeaderSize += pMethod->GetSize() * 4;
+ methodBodySize += pMethod->GetCodeSize();
+
+ // Add in the additional sections.
+ BYTE *sectsBegin = (BYTE *) (pMethod->GetCode() + pMethod->GetCodeSize());
+ const COR_ILMETHOD_SECT *pSect = pMethod->GetSect();
+ const COR_ILMETHOD_SECT *pOldSect;
+ if (pSect != NULL) {
+ // Keep skipping a pointer past each section.
+ do
+ {
+ pOldSect = pSect;
+ if (((COR_ILMETHOD_SECT_FAT *) pSect)->GetKind() & CorILMethod_Sect_FatFormat)
+ {
+ ++fatSections;
+ pSect = (COR_ILMETHOD_SECT *)((BYTE *) pSect + ((COR_ILMETHOD_SECT_FAT *) pSect)->GetDataSize());
+ }
+ else
+ {
+ ++smallSections;
+ pSect = (COR_ILMETHOD_SECT *)((BYTE *) pSect + ((COR_ILMETHOD_SECT_SMALL *) pSect)->DataSize);
+ }
+ pSect = (COR_ILMETHOD_SECT *) (((UINT_PTR) pSect + 3) & ~3);
+ }
+ while (pOldSect->More());
+
+ // Add on the section sizes.
+ methodHeaderSize += (int) ((BYTE *) pSect - sectsBegin);
+ }
+ }
+ else if (((COR_ILMETHOD_TINY *) pMethod)->IsTiny())
+ {
+ ++tinyHeaders;
+ methodHeaderSize += sizeof(COR_ILMETHOD_TINY);
+ methodBodySize += ((COR_ILMETHOD_TINY *) pMethod)->GetCodeSize();
+ }
+ else
+ {
+ _ASSERTE(!"Unrecognized header type");
+ }
+ }
+ }
+
+
+ WritePerfDataInt("CLR method headers", "CLR method headers", "bytes", "bytes",methodHeaderSize);
+ WritePerfDataFloat("CLR method headers", "CLR method headers", "percentage", "percent",(float) ((methodHeaderSize * 100) / fileSize));
+
+ sprintf_s(buf, MAX_MEMBER_LENGTH, "CLR method headers : %d", methodHeaderSize);
+ sprintf_s(szString,SZSTRING_SIZE,"// %-40s (%5.2f%%)", buf, (double) (methodHeaderSize * 100) / fileSize);
+ printLine(GUICookie,szStr);
+
+ WritePerfDataInt("Managed code", "Managed code", "bytes", "bytes",methodBodySize);
+ WritePerfDataFloat("Managed code", "Managed code", "percentage", "percent",(float) ((methodBodySize * 100) / fileSize));
+
+ sprintf_s(buf, MAX_MEMBER_LENGTH, "Managed code : %d", methodBodySize);
+ sprintf_s(szString,SZSTRING_SIZE,"// %-40s (%5.2f%%)", buf, (double) (methodBodySize * 100) / fileSize);
+ printLine(GUICookie,szStr);
+
+ if (g_pPELoader->IsPE32())
+ {
+ DWORD sizeOfInitializedData = VAL32(g_pPELoader->ntHeaders32()->OptionalHeader.SizeOfInitializedData);
+
+ WritePerfDataInt("Data", "Data", "bytes", "bytes",sizeOfInitializedData);
+ WritePerfDataFloat("Data", "Data", "percentage", "percent",(float) ((sizeOfInitializedData * 100) / fileSize));
+
+ sprintf_s(buf, MAX_MEMBER_LENGTH, "Data : %d", sizeOfInitializedData);
+ sprintf_s(szString,SZSTRING_SIZE,"// %-40s (%5.2f%%)", buf, (double) (sizeOfInitializedData * 100) / fileSize);
+ printLine(GUICookie,szStr);
+
+ size = fileSize - g_pPELoader->ntHeaders32()->OptionalHeader.SizeOfHeaders - miscPESize - CORHeader->cb -
+ g_cbMetaData - miscCOMPlusSize -
+ sizeOfInitializedData -
+ methodHeaderSize - methodBodySize;
+ }
+ else
+ {
+ DWORD sizeOfInitializedData = VAL32(g_pPELoader->ntHeaders64()->OptionalHeader.SizeOfInitializedData);
+
+ WritePerfDataInt("Data", "Data", "bytes", "bytes",sizeOfInitializedData);
+ WritePerfDataFloat("Data", "Data", "percentage", "percent",(float) ((sizeOfInitializedData * 100) / fileSize));
+
+ sprintf_s(buf, MAX_MEMBER_LENGTH, "Data : %d", sizeOfInitializedData);
+ sprintf_s(szString,SZSTRING_SIZE,"// %-40s (%5.2f%%)", buf, (double) (sizeOfInitializedData * 100) / fileSize);
+ printLine(GUICookie,szStr);
+
+ size = fileSize - g_pPELoader->ntHeaders64()->OptionalHeader.SizeOfHeaders - miscPESize - CORHeader->cb -
+ g_cbMetaData - miscCOMPlusSize -
+ sizeOfInitializedData -
+ methodHeaderSize - methodBodySize;
+ }
+
+ WritePerfDataInt("Unaccounted", "Unaccounted", "bytes", "bytes",size);
+ WritePerfDataFloat("Unaccounted", "Unaccounted", "percentage", "percent",(float) ((size * 100) / fileSize));
+
+ sprintf_s(buf, MAX_MEMBER_LENGTH, "Unaccounted : %d", size);
+ sprintf_s(szString,SZSTRING_SIZE,"// %-40s (%5.2f%%)", buf, (double) (size * 100) / fileSize);
+ printLine(GUICookie,szStr);
+
+
+ // Detail...
+ if (g_pPELoader->IsPE32())
+ {
+ numberOfSections = VAL16(g_pPELoader->ntHeaders32()->FileHeader.NumberOfSections);
+
+ WritePerfDataInt("Num.of PE sections", "Num.of PE sections", "bytes", "bytes",numberOfSections);
+ printLine(GUICookie,"");
+ sprintf_s(szString,SZSTRING_SIZE,"// Num.of PE sections : %d", numberOfSections);
+ printLine(GUICookie,szStr);
+
+ IMAGE_SECTION_HEADER *pSecHdr = IMAGE_FIRST_SECTION(g_pPELoader->ntHeaders32());
+
+ for (i=0; i < numberOfSections; ++i)
+ {
+ WritePerfDataInt((char*)pSecHdr->Name,(char*)pSecHdr->Name, "bytes", "bytes",VAL32(pSecHdr->SizeOfRawData));
+ sprintf_s(szString,SZSTRING_SIZE,"// %-8s - %d", pSecHdr->Name, VAL32(pSecHdr->SizeOfRawData));
+ printLine(GUICookie,szStr);
+ ++pSecHdr;
+ }
+ }
+ else
+ {
+ numberOfSections = VAL16(g_pPELoader->ntHeaders64()->FileHeader.NumberOfSections);
+
+ WritePerfDataInt("Num.of PE sections", "Num.of PE sections", "bytes", "bytes",numberOfSections);
+ printLine(GUICookie,"");
+ sprintf_s(szString,SZSTRING_SIZE,"// Num.of PE sections : %d", numberOfSections);
+ printLine(GUICookie,szStr);
+
+ IMAGE_SECTION_HEADER *pSecHdr = IMAGE_FIRST_SECTION(g_pPELoader->ntHeaders64());
+
+ for (i=0; i < numberOfSections; ++i)
+ {
+ WritePerfDataInt((char*)pSecHdr->Name,(char*)pSecHdr->Name, "bytes", "bytes",pSecHdr->SizeOfRawData);
+ sprintf_s(szString,SZSTRING_SIZE,"// %-8s - %d", pSecHdr->Name, pSecHdr->SizeOfRawData);
+ printLine(GUICookie,szStr);
+ ++pSecHdr;
+ }
+ }
+
+ if (FAILED(g_pPubImport->QueryInterface(IID_IMetaDataTables, (void**)&pITables)))
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"// Unable to get IMetaDataTables interface");
+ printLine(GUICookie,szStr);
+ return;
+ }
+
+ if (pITables == 0)
+ {
+ printLine(GUICookie,RstrUTF(IDS_E_MDDETAILS));
+ return;
+ }
+ else
+ {
+ DWORD Size = g_cbMetaData;
+ WritePerfDataInt("CLR meta-data size", "CLR meta-data size", "bytes", "bytes",Size);
+ printLine(GUICookie,"");
+ sprintf_s(szString,SZSTRING_SIZE,"// CLR meta-data size : %d", Size);
+ printLine(GUICookie,szStr);
+ metaSize = 0;
+
+ pITables->GetTableInfo(TBL_Module, &sizeRec, &count, NULL, NULL, NULL);
+ TableSeen(TBL_Module);
+ metaSize += size = count * sizeRec; \
+ WritePerfDataInt("Module (count)", "Module (count)", "count", "count",count);
+ WritePerfDataInt("Module (bytes)", "Module (bytes)", "bytes", "bytes",size);
+ sprintf_s(szString,SZSTRING_SIZE,"// %-14s- %4d (%d bytes)", "Module", count, size); \
+ printLine(GUICookie,szStr);
+
+ if ((count = g_pImport->GetCountWithTokenKind(mdtTypeDef)) > 0)
+ {
+ int flags, interfaces = 0, explicitLayout = 0;
+ for (i=1; i <= count; ++i)
+ {
+ if (FAILED(g_pImport->GetTypeDefProps(TokenFromRid(i, mdtTypeDef), (ULONG *) &flags, NULL)))
+ {
+ continue;
+ }
+ if (flags & tdInterface) ++interfaces;
+ if (flags & tdExplicitLayout) ++explicitLayout;
+ }
+ // Get count from table -- count reported by GetCount... doesn't include the "global" typedef.
+ pITables->GetTableInfo(TBL_TypeDef, &sizeRec, &count, NULL, NULL, NULL);
+ TableSeen(TBL_TypeDef);
+ metaSize += size = count * sizeRec;
+
+ WritePerfDataInt("TypeDef (count)", "TypeDef (count)", "count", "count", count);
+ WritePerfDataInt("TypeDef (bytes)", "TypeDef (bytes)", "bytes", "bytes", size);
+ WritePerfDataInt("interfaces", "interfaces", "count", "count", interfaces);
+ WritePerfDataInt("explicitLayout", "explicitLayout", "count", "count", explicitLayout);
+
+ sprintf_s(buf, MAX_MEMBER_LENGTH, " TypeDef - %4d (%d bytes)", count, size);
+ sprintf_s(szString,SZSTRING_SIZE,"// %-38s %d interfaces, %d explicit layout", buf, interfaces, explicitLayout);
+ printLine(GUICookie,szStr);
+ }
+ }
+
+ pITables->GetTableInfo(TBL_TypeRef, &sizeRec, &count, NULL, NULL, NULL);
+ TableSeen(TBL_TypeRef);
+ if (count > 0)
+ {
+ metaSize += size = count * sizeRec; \
+ WritePerfDataInt("TypeRef (count)", "TypeRef (count)", "count", "count", count);
+ WritePerfDataInt("TypeRef (bytes)", "TypeRef (bytes)", "bytes", "bytes", size);
+ sprintf_s(szString,SZSTRING_SIZE,"// %-14s- %4d (%d bytes)", "TypeRef", count, size); \
+ printLine(GUICookie,szStr);
+ }
+
+ if ((count = g_pImport->GetCountWithTokenKind(mdtMethodDef)) > 0)
+ {
+ int flags, abstract = 0, native = 0;
+ for (i=1; i <= count; ++i)
+ {
+ if (FAILED(g_pImport->GetMethodDefProps(TokenFromRid(i, mdtMethodDef), (DWORD *)&flags)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "// Invalid MethodDef %08X record", TokenFromRid(i, mdtMethodDef));
+ printLine(GUICookie, szStr);
+ return;
+ }
+ if (flags & mdAbstract) ++abstract;
+ }
+ pITables->GetTableInfo(TBL_Method, &sizeRec, NULL, NULL, NULL, NULL);
+ TableSeen(TBL_Method);
+ if (count > 0)
+ {
+ metaSize += size = count * sizeRec;
+
+ WritePerfDataInt("MethodDef (count)", "MethodDef (count)", "count", "count", count);
+ WritePerfDataInt("MethodDef (bytes)", "MethodDef (bytes)", "bytes", "bytes", size);
+ WritePerfDataInt("abstract", "abstract", "count", "count", abstract);
+ WritePerfDataInt("native", "native", "count", "count", native);
+ WritePerfDataInt("methodBodies", "methodBodies", "count", "count", methodBodies);
+
+ sprintf_s(buf, MAX_MEMBER_LENGTH, " MethodDef - %4d (%d bytes)", count, size);
+ sprintf_s(szString,SZSTRING_SIZE,"// %-38s %d abstract, %d native, %d bodies", buf, abstract, native, methodBodies);
+ printLine(GUICookie,szStr);
+ }
+ }
+
+ if ((count = g_pImport->GetCountWithTokenKind(mdtFieldDef)) > 0)
+ {
+ int flags, constants = 0;
+
+ for (i=1; i <= count; ++i)
+ {
+ if (FAILED(g_pImport->GetFieldDefProps(TokenFromRid(i, mdtFieldDef), (DWORD *)&flags)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "// Invalid FieldDef %08X record", TokenFromRid(i, mdtFieldDef));
+ printLine(GUICookie, szStr);
+ return;
+ }
+ if ((flags & (fdStatic|fdInitOnly)) == (fdStatic|fdInitOnly)) ++constants;
+ }
+ pITables->GetTableInfo(TBL_Field, &sizeRec, NULL, NULL, NULL, NULL);
+ metaSize += size = count * sizeRec;
+
+ WritePerfDataInt("FieldDef (count)", "FieldDef (count)", "count", "count", count);
+ WritePerfDataInt("FieldDef (bytes)", "FieldDef (bytes)", "bytes", "bytes", size);
+ WritePerfDataInt("constant", "constant", "count", "count", constants);
+
+ sprintf_s(buf, MAX_MEMBER_LENGTH, " FieldDef - %4d (%d bytes)", count, size);
+ sprintf_s(szString,SZSTRING_SIZE,"// %-38s %d constant", buf, constants);
+ printLine(GUICookie,szStr);
+ TableSeen(TBL_Field);
+ }
+
+ DumpTable(TBL_MemberRef, "MemberRef", GUICookie);
+ DumpTable(TBL_Param, "ParamDef", GUICookie);
+ DumpTable(TBL_MethodImpl, "MethodImpl", GUICookie);
+ DumpTable(TBL_Constant, "Constant", GUICookie);
+ DumpTable(TBL_CustomAttribute, "CustomAttribute", GUICookie);
+ DumpTable(TBL_FieldMarshal, "NativeType", GUICookie);
+ DumpTable(TBL_ClassLayout, "ClassLayout", GUICookie);
+ DumpTable(TBL_FieldLayout, "FieldLayout", GUICookie);
+ DumpTable(TBL_StandAloneSig, "StandAloneSig", GUICookie);
+ DumpTable(TBL_InterfaceImpl, "InterfaceImpl", GUICookie);
+ DumpTable(TBL_PropertyMap, "PropertyMap", GUICookie);
+ DumpTable(TBL_Property, "Property", GUICookie);
+ DumpTable(TBL_MethodSemantics, "MethodSemantic", GUICookie);
+ DumpTable(TBL_DeclSecurity, "Security", GUICookie);
+ DumpTable(TBL_TypeSpec, "TypeSpec", GUICookie);
+ DumpTable(TBL_ModuleRef, "ModuleRef", GUICookie);
+ DumpTable(TBL_Assembly, "Assembly", GUICookie);
+ DumpTable(TBL_AssemblyProcessor, "AssemblyProcessor", GUICookie);
+ DumpTable(TBL_AssemblyOS, "AssemblyOS", GUICookie);
+ DumpTable(TBL_AssemblyRef, "AssemblyRef", GUICookie);
+ DumpTable(TBL_AssemblyRefProcessor, "AssemblyRefProcessor", GUICookie);
+ DumpTable(TBL_AssemblyRefOS, "AssemblyRefOS", GUICookie);
+ DumpTable(TBL_File, "File", GUICookie);
+ DumpTable(TBL_ExportedType, "ExportedType", GUICookie);
+ DumpTable(TBL_ManifestResource, "ManifestResource", GUICookie);
+ DumpTable(TBL_NestedClass, "NestedClass", GUICookie);
+
+ // Rest of the tables.
+ pITables->GetNumTables(&count);
+ for (i=0; i<count; ++i)
+ {
+ if (!IsTableSeen(i))
+ DumpTable(i, NULL, GUICookie);
+ }
+
+ // String heap
+ pITables->GetStringHeapSize(&sizeRec);
+ if (sizeRec > 0)
+ {
+ metaSize += sizeRec;
+ WritePerfDataInt("Strings", "Strings", "bytes", "bytes",sizeRec);
+ sprintf_s(szString,SZSTRING_SIZE,"// Strings - %5d bytes", sizeRec);
+ printLine(GUICookie,szStr);
+ }
+ // Blob heap
+ pITables->GetBlobHeapSize(&sizeRec);
+ if (sizeRec > 0)
+ {
+ metaSize += sizeRec;
+ WritePerfDataInt("Blobs", "Blobs", "bytes", "bytes",sizeRec);
+ sprintf_s(szString,SZSTRING_SIZE,"// Blobs - %5d bytes", sizeRec);
+ printLine(GUICookie,szStr);
+ }
+ // User String Heap
+ pITables->GetUserStringHeapSize(&sizeRec);
+ if (sizeRec > 0)
+ {
+ metaSize += sizeRec;
+ WritePerfDataInt("UserStrings", "UserStrings", "bytes", "bytes",sizeRec);
+ sprintf_s(szString,SZSTRING_SIZE,"// UserStrings - %5d bytes", sizeRec);
+ printLine(GUICookie,szStr);
+ }
+ // Guid heap
+ pITables->GetGuidHeapSize(&sizeRec);
+ if (sizeRec > 0)
+ {
+ metaSize += sizeRec;
+ WritePerfDataInt("Guids", "Guids", "bytes", "bytes", sizeRec);
+ sprintf_s(szString,SZSTRING_SIZE,"// Guids - %5d bytes", sizeRec);
+ printLine(GUICookie,szStr);
+ }
+
+ if (g_cbMetaData - metaSize > 0)
+ {
+ WritePerfDataInt("Uncategorized", "Uncategorized", "bytes", "bytes",g_cbMetaData - metaSize);
+ sprintf_s(szString,SZSTRING_SIZE,"// Uncategorized - %5d bytes", g_cbMetaData - metaSize);
+ printLine(GUICookie,szStr);
+ }
+
+ if (miscCOMPlusSize != 0)
+ {
+ WritePerfDataInt("CLR additional info", "CLR additional info", "bytes", "bytes", miscCOMPlusSize);
+ sprintf_s(szString,SZSTRING_SIZE,"// CLR additional info : %d", miscCOMPlusSize);
+ printLine(GUICookie,"");
+ printLine(GUICookie,szStr);
+
+ if (CORHeader->CodeManagerTable.Size != 0)
+ {
+ WritePerfDataInt("CodeManagerTable", "CodeManagerTable", "bytes", "bytes", VAL32(CORHeader->CodeManagerTable.Size));
+ sprintf_s(szString,SZSTRING_SIZE,"// CodeManagerTable - %d", VAL32(CORHeader->CodeManagerTable.Size));
+ printLine(GUICookie,szStr);
+ }
+
+ if (CORHeader->VTableFixups.Size != 0)
+ {
+ WritePerfDataInt("VTableFixups", "VTableFixups", "bytes", "bytes", VAL32(CORHeader->VTableFixups.Size));
+ sprintf_s(szString,SZSTRING_SIZE,"// VTableFixups - %d", VAL32(CORHeader->VTableFixups.Size));
+ printLine(GUICookie,szStr);
+ }
+
+ if (CORHeader->Resources.Size != 0)
+ {
+ WritePerfDataInt("Resources", "Resources", "bytes", "bytes", VAL32(CORHeader->Resources.Size));
+ sprintf_s(szString,SZSTRING_SIZE,"// Resources - %d", VAL32(CORHeader->Resources.Size));
+ printLine(GUICookie,szStr);
+ }
+ }
+ WritePerfDataInt("CLR method headers", "CLR method headers", "count", "count", methodHeaderSize);
+ sprintf_s(szString,SZSTRING_SIZE,"// CLR method headers : %d", methodHeaderSize);
+ printLine(GUICookie,"");
+ printLine(GUICookie,szStr);
+ WritePerfDataInt("Num.of method bodies", "Num.of method bodies", "count", "count",methodBodies);
+ sprintf_s(szString,SZSTRING_SIZE,"// Num.of method bodies - %d", methodBodies);
+ printLine(GUICookie,szStr);
+ WritePerfDataInt("Num.of fat headers", "Num.of fat headers", "count", "count", fatHeaders);
+ sprintf_s(szString,SZSTRING_SIZE,"// Num.of fat headers - %d", fatHeaders);
+ printLine(GUICookie,szStr);
+ WritePerfDataInt("Num.of tiny headers", "Num.of tiny headers", "count", "count", tinyHeaders);
+ sprintf_s(szString,SZSTRING_SIZE,"// Num.of tiny headers - %d", tinyHeaders);
+ printLine(GUICookie,szStr);
+
+ if (deprecatedHeaders > 0) {
+ WritePerfDataInt("Num.of old headers", "Num.of old headers", "count", "count", deprecatedHeaders);
+ sprintf_s(szString,SZSTRING_SIZE,"// Num.of old headers - %d", deprecatedHeaders);
+ printLine(GUICookie,szStr);
+ }
+
+ if (fatSections != 0 || smallSections != 0) {
+ WritePerfDataInt("Num.of fat sections", "Num.of fat sections", "count", "count", fatSections);
+ sprintf_s(szString,SZSTRING_SIZE,"// Num.of fat sections - %d", fatSections);
+ printLine(GUICookie,szStr);
+
+ WritePerfDataInt("Num.of small section", "Num.of small section", "count", "count", smallSections);
+ sprintf_s(szString,SZSTRING_SIZE,"// Num.of small sections - %d", smallSections);
+ printLine(GUICookie,szStr);
+ }
+
+ WritePerfDataInt("Managed code", "Managed code", "bytes", "bytes", methodBodySize);
+ sprintf_s(szString,SZSTRING_SIZE,"// Managed code : %d", methodBodySize);
+ printLine(GUICookie,"");
+ printLine(GUICookie,szStr);
+
+ if (methodBodies != 0) {
+ WritePerfDataInt("Ave method size", "Ave method size", "bytes", "bytes", methodBodySize / methodBodies);
+ sprintf_s(szString,SZSTRING_SIZE,"// Ave method size - %d", methodBodySize / methodBodies);
+ printLine(GUICookie,szStr);
+ }
+
+ if (pITables)
+ pITables->Release();
+
+ if(g_fDumpToPerfWriter)
+ CloseHandle((char*) g_PerfDataFilePtr);
+}
+#ifdef _PREFAST_
+#pragma warning(pop)
+#endif
+
+void DumpHexbytes(__inout __nullterminated char* szptr,BYTE *pb, DWORD fromPtr, DWORD toPtr, DWORD limPtr)
+{
+ char sz[256];
+ int k = 0,i;
+ DWORD curPtr = 0;
+ bool printsz = FALSE;
+ BYTE zero = 0;
+ *szptr = 0;
+ for(i = 0,k = 0,curPtr=fromPtr; curPtr < toPtr; i++,k++,curPtr++,pb++)
+ {
+
+ if(k == 16)
+ {
+ if(printsz) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT(" // %s"),sz);
+ printLine(g_pFile,szString);
+ szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s ",g_szAsmCodeIndent);
+ k = 0;
+ printsz = FALSE;
+ }
+ if(curPtr >= limPtr) pb = &zero; // at limPtr and after, pad with 0
+ else
+ {
+ PAL_CPP_TRY
+ {
+ sz[k] = *pb; // check the ptr validity
+ }
+ PAL_CPP_CATCH_ALL
+ {
+ pb = &zero;
+ } PAL_CPP_ENDTRY;
+ }
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %2.2X", *pb);
+ if(isprint(*pb))
+ {
+ if(g_fDumpRTF)
+ {
+ if((*pb == '\\')||(*pb=='{')||(*pb=='}')) sz[k++]='\\';
+ sz[k] = *pb;
+ }
+ else if(g_fDumpHTML)
+ {
+ if(*pb == '<') { sz[k] = 0; strcat_s(sz,256-k,LTN()); k+=(int)(strlen(LTN())); }
+ else if(*pb == '>') { sz[k] = 0; strcat_s(sz,256-k,GTN()); k+=(int)(strlen(GTN())); }
+ }
+ else sz[k] = *pb;
+ printsz = TRUE;
+ }
+ else
+ {
+ sz[k] = '.';
+ }
+ sz[k+1] = 0;
+ }
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),") ");
+ if(printsz)
+ {
+ for(i = k; i < 16; i++) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," ");
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("// %s"),sz);
+ }
+ printLine(g_pFile,szString);
+}
+
+struct VTableEntry
+{
+ DWORD dwAddr;
+ WORD wCount;
+ WORD wType;
+};
+
+struct ExpDirTable
+{
+ DWORD dwFlags;
+ DWORD dwDateTime;
+ WORD wVMajor;
+ WORD wVMinor;
+ DWORD dwNameRVA;
+ DWORD dwOrdinalBase;
+ DWORD dwNumATEntries;
+ DWORD dwNumNamePtrs;
+ DWORD dwAddrTableRVA;
+ DWORD dwNamePtrRVA;
+ DWORD dwOrdTableRVA;
+};
+
+void DumpEATEntries(void* GUICookie,
+ IMAGE_NT_HEADERS32 *pNTHeader32, IMAGE_OPTIONAL_HEADER32 *pOptHeader32,
+ IMAGE_NT_HEADERS64 *pNTHeader64, IMAGE_OPTIONAL_HEADER64 *pOptHeader64)
+{
+ IMAGE_DATA_DIRECTORY *pExportDir = NULL;
+ IMAGE_SECTION_HEADER *pSecHdr = NULL;
+ DWORD i,j,N;
+ BOOL bpOpt = FALSE;
+
+ if (g_pPELoader->IsPE32())
+ {
+ pExportDir = pOptHeader32->DataDirectory;
+ pSecHdr = IMAGE_FIRST_SECTION(pNTHeader32);
+ N = VAL16(pNTHeader32->FileHeader.NumberOfSections);
+
+ if (pOptHeader32->NumberOfRvaAndSizes)
+ bpOpt = TRUE;
+ }
+ else
+ {
+ pExportDir = pOptHeader64->DataDirectory;
+ pSecHdr = IMAGE_FIRST_SECTION(pNTHeader64);
+ N = VAL16(pNTHeader64->FileHeader.NumberOfSections);
+
+ if (pOptHeader64->NumberOfRvaAndSizes)
+ bpOpt = TRUE;
+
+ }
+ if(bpOpt)
+ {
+ ExpDirTable *pExpTable = NULL;
+ if(pExportDir->Size)
+ {
+#ifdef _DEBUG
+ printLine(GUICookie,COMMENT((char*)0)); // start multiline comment
+ sprintf_s(szString,SZSTRING_SIZE,"// Export dir VA=%X size=%X ",VAL32(pExportDir->VirtualAddress),VAL32(pExportDir->Size));
+ printLine(GUICookie,szString);
+#endif
+ DWORD vaExpTable = VAL32(pExportDir->VirtualAddress);
+ for (i=0; i < N; i++,pSecHdr++)
+ {
+ if((vaExpTable >= VAL32(pSecHdr->VirtualAddress))&&
+ (vaExpTable < VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->Misc.VirtualSize)))
+ {
+ pExpTable = (ExpDirTable*)( g_pPELoader->base()
+ + VAL32(pSecHdr->PointerToRawData)
+ + vaExpTable - VAL32(pSecHdr->VirtualAddress));
+#ifdef _DEBUG
+ sprintf_s(szString,SZSTRING_SIZE,"// in section '%s': VA=%X Misc.VS=%X PRD=%X ",(char*)(pSecHdr->Name),
+ VAL32(pSecHdr->VirtualAddress),VAL32(pSecHdr->Misc.VirtualSize),VAL32(pSecHdr->PointerToRawData));
+ printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"// Export Directory Table:"); printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"// dwFlags = %X",VAL32(pExpTable->dwFlags)); printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"// dwDateTime = %X",VAL32(pExpTable->dwDateTime)); printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"// wVMajor = %X",VAL16(pExpTable->wVMajor)); printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"// wVMinor = %X",VAL16(pExpTable->wVMinor)); printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"// dwNameRVA = %X",VAL32(pExpTable->dwNameRVA)); printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"// dwOrdinalBase = %X",VAL32(pExpTable->dwOrdinalBase)); printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"// dwNumATEntries = %X",VAL32(pExpTable->dwNumATEntries)); printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"// dwNumNamePtrs = %X",VAL32(pExpTable->dwNumNamePtrs)); printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"// dwAddrTableRVA = %X",VAL32(pExpTable->dwAddrTableRVA)); printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"// dwNamePtrRVA = %X",VAL32(pExpTable->dwNamePtrRVA)); printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"// dwOrdTableRVA = %X",VAL32(pExpTable->dwOrdTableRVA)); printLine(GUICookie,szString);
+ if(pExpTable->dwNameRVA)
+ {
+ char* szName;
+ if(g_pPELoader->getVAforRVA(VAL32(pExpTable->dwNameRVA), (void **) &szName))
+ sprintf_s(szString,SZSTRING_SIZE,"// DLL Name: '%s'",szName);
+ else
+ sprintf_s(szString,SZSTRING_SIZE,"// DLL Name: BAD RVA: 0x%8.8X",VAL32(pExpTable->dwNameRVA));
+
+ printLine(GUICookie,szString);
+ }
+#endif
+ if(pExpTable->dwNumATEntries && pExpTable->dwAddrTableRVA)
+ {
+ DWORD* pExpAddr;
+ BYTE *pCont;
+ DWORD dwTokRVA;
+ mdToken* pTok;
+ g_pPELoader->getVAforRVA(VAL32(pExpTable->dwAddrTableRVA), (void **) &pExpAddr);
+#ifdef _DEBUG
+ sprintf_s(szString,SZSTRING_SIZE,"// Export Address Table:"); printLine(GUICookie,szString);
+#endif
+ g_nEATableRef = VAL32(pExpTable->dwNumATEntries);
+ if (g_prEATableRef == NULL)
+ {
+ g_prEATableRef = new DynamicArray<EATableRef>;
+ }
+
+ (*g_prEATableRef)[g_nEATableRef].tkTok = 0; // to avoid multiple reallocations of DynamicArray
+ for(j=0; j < VAL32(pExpTable->dwNumATEntries); j++,pExpAddr++)
+ {
+ g_pPELoader->getVAforRVA(VAL32(*pExpAddr), (void **) &pCont);
+#ifdef _DEBUG
+ sprintf_s(szString,SZSTRING_SIZE,"// [%d]: RVA=%X VA=%p(",j,VAL32(*pExpAddr),pCont);
+ DumpByteArray(szString,pCont,16,GUICookie);
+ printLine(GUICookie,szString);
+#endif
+ (*g_prEATableRef)[j].tkTok = 0;
+
+ if(g_pPELoader->IsPE32())
+ {
+ dwTokRVA = VAL32(*((DWORD*)(pCont+2))); // first two bytes - JumpIndirect (0x25FF)
+ dwTokRVA -= VAL32((DWORD)pOptHeader32->ImageBase);
+ }
+ else
+ {
+ ULONGLONG ullTokRVA;
+ if(pNTHeader64->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64)
+ ullTokRVA = VAL64(*((ULONGLONG*)(pCont+8)));
+ else
+ ullTokRVA = VAL64(*((ULONGLONG*)(pCont+2)));
+
+ dwTokRVA =(DWORD)(ullTokRVA - VAL64((DWORD)pOptHeader64->ImageBase));
+ }
+ if(g_pPELoader->getVAforRVA(dwTokRVA,(void**)&pTok))
+ (*g_prEATableRef)[j].tkTok = VAL32(*pTok);
+
+ (*g_prEATableRef)[j].pszName = NULL;
+
+ }
+ }
+ if(pExpTable->dwNumNamePtrs && pExpTable->dwNamePtrRVA && pExpTable->dwOrdTableRVA)
+ {
+ DWORD *pNamePtr;
+ WORD *pOrd;
+ char* szName;
+ g_pPELoader->getVAforRVA(VAL32(pExpTable->dwNamePtrRVA), (void **) &pNamePtr);
+ g_pPELoader->getVAforRVA(VAL32(pExpTable->dwOrdTableRVA), (void **) &pOrd);
+#ifdef _DEBUG
+ sprintf_s(szString,SZSTRING_SIZE,"// Export Names:"); printLine(GUICookie,szString);
+#endif
+ for(j=0; j < VAL32(pExpTable->dwNumATEntries); j++,pNamePtr++,pOrd++)
+ {
+ g_pPELoader->getVAforRVA(VAL32(*pNamePtr), (void **) &szName);
+#ifdef _DEBUG
+ sprintf_s(szString,SZSTRING_SIZE,"// [%d]: NamePtr=%X Ord=%X Name='%s'",j,VAL32(*pNamePtr),*pOrd,szName);
+ printLine(GUICookie,szString);
+#endif
+ (*g_prEATableRef)[VAL16(*pOrd)].pszName = szName;
+ }
+ }
+ g_nEATableBase = pExpTable->dwOrdinalBase;
+ break;
+ }
+ }
+#ifdef _DEBUG
+ printLine(GUICookie,COMMENT((char*)-1)); // end multiline comment
+#endif
+ }
+ }
+}
+// helper to avoid mixing of SEH and stack objects with destructors
+void DumpEATEntriesWrapper(void* GUICookie,
+ IMAGE_NT_HEADERS32 *pNTHeader32, IMAGE_OPTIONAL_HEADER32 *pOptHeader32,
+ IMAGE_NT_HEADERS64 *pNTHeader64, IMAGE_OPTIONAL_HEADER64 *pOptHeader64)
+{
+ PAL_CPP_TRY
+ {
+ DumpEATEntries(GUICookie, pNTHeader32, pOptHeader32, pNTHeader64, pOptHeader64);
+ }
+ PAL_CPP_CATCH_ALL
+ {
+ printError(GUICookie,"// ERROR READING EXPORT ADDRESS TABLE");
+ if (g_prEATableRef != NULL)
+ {
+ SDELETE(g_prEATableRef);
+ }
+ g_nEATableRef = 0;
+ }
+ PAL_CPP_ENDTRY
+}
+
+void DumpVtable(void* GUICookie)
+{
+ // VTable : primary processing
+ DWORD pVTable=0;
+ VTableEntry* pVTE;
+ DWORD i,j,k;
+ char* szptr;
+
+ IMAGE_NT_HEADERS32 *pNTHeader32 = NULL;
+ IMAGE_OPTIONAL_HEADER32 *pOptHeader32 = NULL;
+
+ IMAGE_NT_HEADERS64 *pNTHeader64 = NULL;
+ IMAGE_OPTIONAL_HEADER64 *pOptHeader64 = NULL;
+
+ if (g_pPELoader->IsPE32())
+ {
+ pNTHeader32 = g_pPELoader->ntHeaders32();
+ pOptHeader32 = &pNTHeader32->OptionalHeader;
+
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%08x", g_szAsmCodeIndent,KEYWORD(".imagebase"),VAL32(pOptHeader32->ImageBase));
+ printLine(GUICookie,szString);
+ j = VAL16(pOptHeader32->Subsystem);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%08x", g_szAsmCodeIndent,KEYWORD(".file alignment"),VAL32(pOptHeader32->FileAlignment));
+ printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%08x", g_szAsmCodeIndent,KEYWORD(".stackreserve"),VAL32(pOptHeader32->SizeOfStackReserve));
+ printLine(GUICookie,szString);
+ }
+ else
+ {
+ pNTHeader64 = g_pPELoader->ntHeaders64();
+ pOptHeader64 = &pNTHeader64->OptionalHeader;
+
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%016I64x", g_szAsmCodeIndent,KEYWORD(".imagebase"),VAL64(pOptHeader64->ImageBase));
+ printLine(GUICookie,szString);
+ j = VAL16(pOptHeader64->Subsystem);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%08x", g_szAsmCodeIndent,KEYWORD(".file alignment"),VAL32(pOptHeader64->FileAlignment));
+ printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%016I64x", g_szAsmCodeIndent,KEYWORD(".stackreserve"),VAL64(pOptHeader64->SizeOfStackReserve));
+ printLine(GUICookie,szString);
+ }
+ szptr = &szString[0];
+ szptr += sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%04x", g_szAsmCodeIndent,KEYWORD(".subsystem"),j);
+ {
+ const char* psz[15] = {"// UNKNOWN",
+ "// NATIVE",
+ "// WINDOWS_GUI",
+ "// WINDOWS_CUI",
+ "// <illegal value>",
+ "// OS2_CUI",
+ "// <illegal value>",
+ "// POSIX_CUI",
+ "// NATIVE_WINDOWS",
+ "// WINDOWS_CE_GUI",
+ "// EFI_APPLICATION",
+ "// EFI_BOOT_SERVICE_DRIVER",
+ "// EFI_RUNTIME_DRIVER",
+ "// EFI_ROM",
+ "// XBOX"
+ };
+ if(j > 14) j = 4; // <illegal value>
+ sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %s",COMMENT(psz[j]));
+ }
+ printLine(GUICookie,szString);
+
+ szptr = &szString[0];
+ i = (DWORD)VAL32(g_CORHeader->Flags);
+ szptr += sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%08x", g_szAsmCodeIndent,KEYWORD(".corflags"),i);
+ if(i != 0)
+ {
+ char sz[256], *szp = sz;
+ szp += sprintf_s(szp,256," // ");
+ if(i & COMIMAGE_FLAGS_ILONLY) szp += sprintf_s(szp,256-(szp-sz)," ILONLY");
+ if(COR_IS_32BIT_REQUIRED(i))
+ szp += sprintf_s(szp,256-(szp-sz)," 32BITREQUIRED");
+ if(COR_IS_32BIT_PREFERRED(i))
+ szp += sprintf_s(szp,256-(szp-sz)," 32BITPREFERRED");
+ if(i & COMIMAGE_FLAGS_IL_LIBRARY) szp += sprintf_s(szp,256-(szp-sz)," IL_LIBRARY");
+ if(i & COMIMAGE_FLAGS_TRACKDEBUGDATA) szp += sprintf_s(szp,256-(szp-sz)," TRACKDEBUGDATA");
+ szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT(sz));
+ }
+ printLine(GUICookie,szString);
+
+ sprintf_s(szString,SZSTRING_SIZE,"%s// Image base: 0x%p",g_szAsmCodeIndent,g_pPELoader->base());
+ printLine(GUICookie,COMMENT(szString));
+
+ DumpEATEntriesWrapper(GUICookie, pNTHeader32, pOptHeader32, pNTHeader64, pOptHeader64);
+
+ g_nVTableRef = 0;
+ if(VAL32(g_CORHeader->VTableFixups.Size))
+ {
+ IMAGE_SECTION_HEADER *pSecHdr = NULL;
+ DWORD dwNumberOfSections;
+
+ if (g_pPELoader->IsPE32())
+ {
+ pSecHdr = IMAGE_FIRST_SECTION(g_pPELoader->ntHeaders32());
+ dwNumberOfSections = VAL16(g_pPELoader->ntHeaders32()->FileHeader.NumberOfSections);
+ }
+ else
+ {
+ pSecHdr = IMAGE_FIRST_SECTION(g_pPELoader->ntHeaders64());
+ dwNumberOfSections = VAL16(g_pPELoader->ntHeaders64()->FileHeader.NumberOfSections);
+ }
+
+ pVTable = VAL32(g_CORHeader->VTableFixups.VirtualAddress);
+
+ for (i=0; i < dwNumberOfSections; i++,pSecHdr++)
+ {
+ if(((DWORD)pVTable >= VAL32(pSecHdr->VirtualAddress))&&
+ ((DWORD)pVTable < VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->Misc.VirtualSize)))
+ {
+ pVTE = (VTableEntry*)( g_pPELoader->base()
+ + VAL32(pSecHdr->PointerToRawData)
+ + pVTable - VAL32(pSecHdr->VirtualAddress));
+ for(j=VAL32(g_CORHeader->VTableFixups.Size),k=0; j > 0; pVTE++, j-=sizeof(VTableEntry),k++)
+ {
+ szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s [%d] ",g_szAsmCodeIndent,KEYWORD(".vtfixup"),VAL16(pVTE->wCount));
+ DWORD dwSize = VAL16(pVTE->wCount) * 4;
+ WORD wType = VAL16(pVTE->wType);
+ if(wType & COR_VTABLE_32BIT)
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("int32 "));
+ else if(wType & COR_VTABLE_64BIT)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("int64 "));
+ dwSize <<= 1;
+ }
+ if(wType & COR_VTABLE_FROM_UNMANAGED)
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("fromunmanaged "));
+ if(wType & COR_VTABLE_CALL_MOST_DERIVED)
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("callmostderived "));
+ if(wType & 0x8 /*COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN*/)
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("retainappdomain "));
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("at "));
+ szptr = DumpDataPtr(szptr,VAL32(pVTE->dwAddr), dwSize);
+ // Walk every v-table fixup entry and dump the slots.
+ {
+ BYTE *pSlot;
+ if (g_pPELoader->getVAforRVA(VAL32(pVTE->dwAddr), (void **) &pSlot))
+ {
+ char* szptr0 = szptr;
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," //");
+ for (WORD iSlot=0; iSlot<VAL16(pVTE->wCount); iSlot++)
+ {
+ mdMethodDef tkMethod = VAL32(*(DWORD *) pSlot);
+ if (VAL16(pVTE->wType) & COR_VTABLE_32BIT)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %08X", VAL32(*(DWORD *)pSlot));
+ pSlot += sizeof(DWORD);
+ }
+ else
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %016I64X", VAL64(*(unsigned __int64 *)pSlot));
+ pSlot += sizeof(unsigned __int64);
+ }
+ if (g_prVTableRef == NULL)
+ {
+ g_prVTableRef = new DynamicArray<VTableRef>;
+ }
+ (*g_prVTableRef)[g_nVTableRef].tkTok = tkMethod;
+ (*g_prVTableRef)[g_nVTableRef].wEntry = (WORD)k;
+ (*g_prVTableRef)[g_nVTableRef].wSlot = iSlot;
+ g_nVTableRef++;
+
+ //ValidateToken(tkMethod, mdtMethodDef);
+ }
+ sprintf_s(szptr0,SZSTRING_REMAINING_SIZE(szptr0),COMMENT(szptr0));
+ }
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %s",ERRORMSG(RstrUTF(IDS_E_BOGUSRVA)));
+ }
+ printLine(GUICookie,szString);
+ }
+ break;
+ }
+ }
+ }
+}
+// MetaInfo integration:
+void DumpMI(__in __nullterminated const char *str)
+{
+ static BOOL fInit = TRUE;
+ static char* szStr = &szString[0];
+ static void* GUICookie;
+ char* pch;
+ // Reset
+ if(str == (char*)-1)
+ {
+ fInit = TRUE;
+ return;
+ }
+ // Init
+ if(fInit)
+ {
+ strcpy_s(szString,5,"// ");
+ fInit = FALSE;
+ GUICookie = (void*)str;
+ if(g_Mode & MODE_GUI) szStr = &szString[3]; // don't need "//" in GUI mode
+ return;
+ }
+ // Normal work
+ strcat_s(szString,SZSTRING_SIZE,str);
+ if((pch = strchr(szStr,'\n')))
+ {
+ *pch = 0;
+ printLine(GUICookie,szStr);
+ pch++;
+ memcpy(&szString[3], pch, strlen(pch)+1);
+ }
+}
+
+HRESULT VEHandlerReporter( // Return status.
+ LPCWSTR szMsg, // Error message.
+ VEContext Context, // Error context (offset,token)
+ HRESULT hrRpt) // HRESULT for the message
+{
+ WCHAR* wzMsg;
+ if(szMsg)
+ {
+ size_t L = wcslen(szMsg)+256;
+ if((wzMsg = new (nothrow) WCHAR[L]) != NULL)
+ {
+ wcscpy_s(wzMsg,L,szMsg);
+ // include token and offset from Context
+ if(Context.Token) swprintf_s(&wzMsg[wcslen(wzMsg)], L-wcslen(wzMsg), W(" [token:0x%08X]"),Context.Token);
+ if(Context.uOffset) swprintf_s(&wzMsg[wcslen(wzMsg)], L-wcslen(wzMsg), W(" [at:0x%X]"),Context.uOffset);
+ swprintf_s(&wzMsg[wcslen(wzMsg)], L-wcslen(wzMsg), W(" [hr:0x%08X]\n"),hrRpt);
+ DumpMI(UnicodeToUtf(wzMsg));
+ delete[] wzMsg;
+ }
+ }
+ return S_OK;
+}
+
+void DumpMetaInfo(__in __nullterminated const WCHAR* pwzFileName, __in_opt __nullterminated const char* pszObjFileName, void* GUICookie)
+{
+ const WCHAR* pch = wcsrchr(pwzFileName,L'.');
+
+ DumpMI((char*)GUICookie); // initialize the print function for DumpMetaInfo
+
+ if(pch && (!_wcsicmp(pch+1,W("lib")) || !_wcsicmp(pch+1,W("obj"))))
+ { // This works only when all the rest does not
+ // Init and run.
+#ifdef FEATURE_CORECLR
+ if (metaDataGetDispenser(CLSID_CorMetaDataDispenser,
+ IID_IMetaDataDispenserEx, (void **)&g_pDisp))
+#else
+ if(SUCCEEDED(CoInitialize(0)))
+ {
+ if(SUCCEEDED(LegacyActivationShim::CoInitializeCor(0)))
+ {
+ if (SUCCEEDED(LegacyActivationShim::ClrCoCreateInstance(
+ CLSID_CorMetaDataDispenser, NULL, CLSCTX_INPROC_SERVER,
+ IID_IMetaDataDispenserEx, (void **) &g_pDisp)))
+#endif
+ {
+ WCHAR *pwzObjFileName=NULL;
+ if (pszObjFileName)
+ {
+ int nLength = (int) strlen(pszObjFileName)+1;
+ pwzObjFileName = new WCHAR[nLength];
+ memset(pwzObjFileName,0,sizeof(WCHAR)*nLength);
+ WszMultiByteToWideChar(CP_UTF8,0,pszObjFileName,-1,pwzObjFileName,nLength);
+ }
+ DisplayFile((wchar_t*)pwzFileName, true, g_ulMetaInfoFilter, pwzObjFileName, DumpMI);
+ g_pDisp->Release();
+ g_pDisp = NULL;
+ if (pwzObjFileName) VDELETE(pwzObjFileName);
+ }
+#ifndef FEATURE_CORECLR
+ LegacyActivationShim::CoUninitializeCor();
+ }
+ CoUninitialize();
+ }
+#endif
+ }
+ else
+ {
+ HRESULT hr = S_OK;
+ if(g_pDisp == NULL)
+ {
+#ifdef FEATURE_CORECLR
+ hr = metaDataGetDispenser(CLSID_CorMetaDataDispenser,
+ IID_IMetaDataDispenserEx, (void **)&g_pDisp);
+#else
+ hr = LegacyActivationShim::ClrCoCreateInstance(
+ CLSID_CorMetaDataDispenser, NULL, CLSCTX_INPROC_SERVER,
+ IID_IMetaDataDispenserEx, (void **) &g_pDisp);
+#endif
+ }
+ if(SUCCEEDED(hr))
+ {
+ g_ValModuleType = ValidatorModuleTypePE;
+ if(g_pAssemblyImport==NULL) g_pAssemblyImport = GetAssemblyImport(NULL);
+ if(!(g_Mode & MODE_GUI))
+ printLine(GUICookie,RstrUTF(IDS_E_MISTART));
+ //MDInfo metaDataInfo(g_pPubImport, g_pAssemblyImport, (LPCWSTR)pwzFileName, DumpMI, g_ulMetaInfoFilter);
+ MDInfo metaDataInfo(g_pDisp,(LPCWSTR)pwzFileName, DumpMI, g_ulMetaInfoFilter);
+ metaDataInfo.SetVEHandlerReporter((__int64) (size_t) VEHandlerReporter);
+ metaDataInfo.DisplayMD();
+ if(!(g_Mode & MODE_GUI))
+ printLine(GUICookie,RstrUTF(IDS_E_MIEND));
+ }
+ }
+ DumpMI((char*)-1); // reset the print function for DumpMetaInfo
+}
+
+void DumpPreamble()
+{
+ printLine(g_pFile,"");
+ if(g_fDumpHTML)
+ {
+ printLine(g_pFile, "<FONT SIZE=4><B>");
+ }
+ else if(g_fDumpRTF)
+ {
+ }
+ sprintf_s(szString,SZSTRING_SIZE,"// Microsoft (R) .NET Framework IL Disassembler. Version " VER_FILEVERSION_STR);
+ printLine(g_pFile,COMMENT(szString));
+ if(g_fDumpHTML)
+ {
+ printLine(g_pFile, "</B></FONT>");
+ }
+ else if(g_fDumpRTF)
+ {
+ }
+ printLine(g_pFile,"");
+ if(g_fLimitedVisibility || (!g_fShowCA) || (!g_fDumpAsmCode)
+ || (g_Mode & (MODE_DUMP_CLASS | MODE_DUMP_CLASS_METHOD | MODE_DUMP_CLASS_METHOD_SIG)))
+ {
+ printLine(g_pFile,"");
+ printLine(g_pFile,COMMENT(RstrUTF(IDS_E_PARTDASM)));
+ printLine(g_pFile,"");
+ }
+
+ if(g_fLimitedVisibility)
+ {
+ strcpy_s(szString, SZSTRING_SIZE, RstrUTF(IDS_E_ONLYITEMS));
+ if(!g_fHidePub) strcat_s(szString, SZSTRING_SIZE," Public");
+ if(!g_fHidePriv) strcat_s(szString, SZSTRING_SIZE," Private");
+ if(!g_fHideFam) strcat_s(szString, SZSTRING_SIZE," Family");
+ if(!g_fHideAsm) strcat_s(szString, SZSTRING_SIZE," Assembly");
+ if(!g_fHideFAA) strcat_s(szString, SZSTRING_SIZE," FamilyANDAssembly");
+ if(!g_fHidePrivScope) strcat_s(szString, SZSTRING_SIZE," PrivateScope");
+ printLine(g_pFile,COMMENT(szString));
+ }
+}
+
+void DumpSummary()
+{
+ HRESULT hr;
+ ULONG i;
+ const char *pcClass,*pcNS,*pcMember, *pcSig;
+ char szFQN[4096];
+ HENUMInternal hEnum;
+ mdToken tkMember;
+ CQuickBytes qbMemberSig;
+ PCCOR_SIGNATURE pComSig;
+ ULONG cComSig;
+ DWORD dwAttrs;
+ mdToken tkEventType;
+
+ printLine(g_pFile,"//============ S U M M A R Y =================================");
+ if (SUCCEEDED(g_pImport->EnumGlobalFunctionsInit(&hEnum)))
+ {
+ while(g_pImport->EnumNext(&hEnum, &tkMember))
+ {
+ if (FAILED(g_pImport->GetNameOfMethodDef(tkMember, &pcMember)) ||
+ FAILED(g_pImport->GetSigOfMethodDef(tkMember, &cComSig, &pComSig)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "// ERROR in the method record %08X", tkMember);
+ printLine(g_pFile, szString);
+ continue;
+ }
+ qbMemberSig.Shrink(0);
+ pcSig = cComSig ? PrettyPrintSig(pComSig, cComSig, "", &qbMemberSig, g_pImport,NULL) : "NO SIGNATURE";
+ PREFIX_ASSUME(ProperName((char*)pcMember) != 0);
+ sprintf_s(szString,SZSTRING_SIZE,"// %08X [GLM] %s : %s", tkMember,ProperName((char*)pcMember),pcSig);
+ printLine(g_pFile,szString);
+ }
+ }
+ g_pImport->EnumClose(&hEnum);
+ if (SUCCEEDED(g_pImport->EnumGlobalFieldsInit(&hEnum)))
+ {
+ while(g_pImport->EnumNext(&hEnum, &tkMember))
+ {
+ if (FAILED(g_pImport->GetNameOfFieldDef(tkMember, &pcMember)) ||
+ FAILED(g_pImport->GetSigOfFieldDef(tkMember, &cComSig, &pComSig)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "// ERROR in the field record %08X", tkMember);
+ printLine(g_pFile, szString);
+ continue;
+ }
+ qbMemberSig.Shrink(0);
+ pcSig = cComSig ? PrettyPrintSig(pComSig, cComSig, "", &qbMemberSig, g_pImport,NULL) : "NO SIGNATURE";
+ PREFIX_ASSUME(ProperName((char*)pcMember) != 0);
+ sprintf_s(szString,SZSTRING_SIZE,"// %08X [GLF] %s : %s", tkMember,ProperName((char*)pcMember),pcSig);
+ printLine(g_pFile,szString);
+ }
+ }
+ g_pImport->EnumClose(&hEnum);
+
+ for (i = 0; i < g_NumClasses; i++)
+ {
+ if (FAILED(g_pImport->GetNameOfTypeDef(g_cl_list[i], &pcClass, &pcNS)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "// ERROR in the TypeDef record %08X", g_cl_list[i]);
+ printLine(g_pFile, szString);
+ continue;
+ }
+ PREFIX_ASSUME(ProperName((char*)pcClass) != 0);
+ if(*pcNS) sprintf_s(szFQN,4096,"%s.%s", ProperName((char*)pcNS),ProperName((char*)pcClass));
+ else strcpy_s(szFQN,4096,ProperName((char*)pcClass));
+ sprintf_s(szString,SZSTRING_SIZE,"// %08X [CLS] %s", g_cl_list[i],szFQN);
+ printLine(g_pFile,szString);
+ if(SUCCEEDED(g_pImport->EnumInit(mdtMethodDef, g_cl_list[i], &hEnum)))
+ {
+ while(g_pImport->EnumNext(&hEnum, &tkMember))
+ {
+ if (FAILED(g_pImport->GetNameOfMethodDef(tkMember, &pcMember)) ||
+ FAILED(g_pImport->GetSigOfMethodDef(tkMember, &cComSig, &pComSig)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "// ERROR in the method record %08X", tkMember);
+ printLine(g_pFile, szString);
+ continue;
+ }
+ qbMemberSig.Shrink(0);
+ pcSig = cComSig ? PrettyPrintSig(pComSig, cComSig, "", &qbMemberSig, g_pImport,NULL) : "NO SIGNATURE";
+ PREFIX_ASSUME(ProperName((char*)pcMember) != 0);
+ sprintf_s(szString,SZSTRING_SIZE,"// %08X [MET] %s::%s : %s", tkMember,szFQN,ProperName((char*)pcMember),pcSig);
+ printLine(g_pFile,szString);
+ }
+ }
+ g_pImport->EnumClose(&hEnum);
+ if(SUCCEEDED(g_pImport->EnumInit(mdtFieldDef, g_cl_list[i], &hEnum)))
+ {
+ while(g_pImport->EnumNext(&hEnum, &tkMember))
+ {
+ if (FAILED(g_pImport->GetNameOfFieldDef(tkMember, &pcMember)) ||
+ FAILED(g_pImport->GetSigOfFieldDef(tkMember, &cComSig, &pComSig)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "// ERROR in the field record %08X", tkMember);
+ printLine(g_pFile, szString);
+ continue;
+ }
+ qbMemberSig.Shrink(0);
+ pcSig = cComSig ? PrettyPrintSig(pComSig, cComSig, "", &qbMemberSig, g_pImport,NULL) : "NO SIGNATURE";
+ PREFIX_ASSUME(ProperName((char*)pcMember) != 0);
+ sprintf_s(szString,SZSTRING_SIZE,"// %08X [FLD] %s::%s : %s", tkMember,szFQN,ProperName((char*)pcMember),pcSig);
+ printLine(g_pFile,szString);
+ }
+ }
+ g_pImport->EnumClose(&hEnum);
+ if(SUCCEEDED(g_pImport->EnumInit(mdtEvent, g_cl_list[i], &hEnum)))
+ {
+ while(g_pImport->EnumNext(&hEnum, &tkMember))
+ {
+ if (FAILED(g_pImport->GetEventProps(tkMember,&pcMember,&dwAttrs,&tkEventType)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "// Invalid Event %08X record", tkMember);
+ printLine(g_pFile, szString);
+ continue;
+ }
+ qbMemberSig.Shrink(0);
+ pcSig = "NO TYPE";
+ if(RidFromToken(tkEventType))
+ {
+ switch(TypeFromToken(tkEventType))
+ {
+ case mdtTypeRef:
+ case mdtTypeDef:
+ case mdtTypeSpec:
+ pcSig = PrettyPrintClass(&qbMemberSig,tkEventType,g_pImport);
+ break;
+ default:
+ break;
+ }
+ }
+ PREFIX_ASSUME(ProperName((char*)pcMember) != 0);
+ sprintf_s(szString,SZSTRING_SIZE,"// %08X [EVT] %s::%s : %s", tkMember,szFQN,ProperName((char*)pcMember),pcSig);
+ printLine(g_pFile,szString);
+ }
+ }
+ g_pImport->EnumClose(&hEnum);
+ if(SUCCEEDED(g_pImport->EnumInit(mdtProperty, g_cl_list[i], &hEnum)))
+ {
+ while(g_pImport->EnumNext(&hEnum, &tkMember))
+ {
+ if (FAILED(g_pImport->GetPropertyProps(tkMember,&pcMember,&dwAttrs,&pComSig,&cComSig)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "// Invalid Property %08X record", tkMember);
+ printLine(g_pFile, szString);
+ continue;
+ }
+ qbMemberSig.Shrink(0);
+ pcSig = cComSig ? PrettyPrintSig(pComSig, cComSig, "", &qbMemberSig, g_pImport,NULL) : "NO SIGNATURE";
+ PREFIX_ASSUME(ProperName((char*)pcMember) != 0);
+ sprintf_s(szString,SZSTRING_SIZE,"// %08X [PRO] %s::%s : %s", tkMember,szFQN,ProperName((char*)pcMember),pcSig);
+ printLine(g_pFile,szString);
+ }
+ }
+ g_pImport->EnumClose(&hEnum);
+ }
+ printLine(g_pFile,"//=============== END SUMMARY ==================================");
+}
+void DumpRTFPrefix(void* GUICookie,BOOL fFontDefault)
+{
+ g_fDumpRTF = FALSE;
+ printLine(GUICookie,"{\\rtf1\\ansi");
+ if(fFontDefault)
+ printLine(GUICookie,"{\\fonttbl{\\f0\\fmodern\\fprq1\\fcharset1 Courier New;}{\\f1\\fswiss\\fcharset1 Arial;}}");
+ printLine(GUICookie,"{\\colortbl ;\\red0\\green0\\blue128;\\red0\\green128\\blue0;\\red255\\green0\\blue0;}");
+ printLine(GUICookie,"\\viewkind4\\uc1\\pard\\f0\\fs20");
+ g_fDumpRTF = TRUE;
+}
+void DumpRTFPostfix(void* GUICookie)
+{
+ g_fDumpRTF = FALSE;
+ printLine(GUICookie,"}");
+ g_fDumpRTF = TRUE;
+}
+mdToken ClassOf(mdToken tok)
+{
+ mdToken retval=0;
+ switch(TypeFromToken(tok))
+ {
+ case mdtTypeDef:
+ case mdtTypeRef:
+ case mdtTypeSpec:
+ retval = tok;
+ break;
+
+ case mdtFieldDef:
+ case mdtMethodDef:
+ case mdtMemberRef:
+ if (FAILED(g_pImport->GetParentToken(tok, &retval)))
+ {
+ retval = mdTokenNil;
+ }
+ else
+ {
+ retval = ClassOf(retval);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return retval;
+}
+void DumpRefs(BOOL fClassesOnly)
+{
+ CQuickBytes out;
+ DynamicArray<TokPair> *refs = g_refs;
+ TokPair *newrefs = NULL;
+ mdToken tkThisUser,tkThisRef;
+ mdToken tkLastUser = 0xFFFFFFFF, tkLastRef=0xFFFFFFFF;
+ DWORD i=0,j=0;
+
+ g_refs = NULL;
+ printLine(g_pFile,COMMENT((char*)0));
+ printLine(g_pFile,"//============ R E F E R E N C E S ===========================");
+ strcpy_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH,"// ");
+ if(fClassesOnly && g_NumRefs)
+ {
+ if((newrefs = new TokPair[g_NumRefs]))
+ {
+ for(i=0; i<g_NumRefs; i++)
+ {
+ newrefs[i].tkUser = tkThisUser = ClassOf((*refs)[i].tkUser);
+ newrefs[i].tkRef = tkThisRef = ClassOf((*refs)[i].tkRef);
+ if(!tkThisUser) continue;
+ if(!tkThisRef) continue;
+ if(tkThisUser == tkThisRef) continue;
+ for(j = 0; j<i; j++)
+ {
+ if((newrefs[j].tkUser==tkThisUser)&&(newrefs[j].tkRef==tkThisRef))
+ {
+ newrefs[i].tkRef = 0;
+ break;
+ }
+ }
+ }
+ }
+ else fClassesOnly = FALSE;
+ }
+ for(i = 0; i <g_NumRefs; i++)
+ {
+ if(fClassesOnly)
+ {
+ tkThisUser = newrefs[i].tkUser;
+ tkThisRef = newrefs[i].tkRef;
+ }
+ else
+ {
+ tkThisUser = (*refs)[i].tkUser;
+ tkThisRef = (*refs)[i].tkRef;
+ }
+ if(!tkThisUser) continue;
+ if(!tkThisRef) continue;
+ if(tkThisUser == tkThisRef) continue;
+ if((tkThisUser==tkLastUser)&&(tkThisRef==tkLastRef)) continue;
+
+ strcpy_s(szString, SZSTRING_SIZE,g_szAsmCodeIndent);
+ if(tkThisUser != tkLastUser)
+ {
+ PrettyPrintToken(szString, tkThisUser, g_pImport,g_pFile,0); //TypeDef,TypeRef,TypeSpec,MethodDef,FieldDef,MemberRef,MethodSpec,String
+ strcat_s(szString, SZSTRING_SIZE, " references ");
+ printLine(g_pFile,szString);
+ tkLastUser = tkThisUser;
+ }
+ strcpy_s(szString, SZSTRING_SIZE,g_szAsmCodeIndent);
+ strcat_s(szString, SZSTRING_SIZE," - ");
+ PrettyPrintToken(szString, tkThisRef, g_pImport,g_pFile,0); //TypeDef,TypeRef,TypeSpec,MethodDef,FieldDef,MemberRef,MethodSpec,String
+ printLine(g_pFile,szString);
+ tkLastRef = tkThisRef;
+
+ }
+
+ printLine(g_pFile,"//=============== END REFERENCES =============================");
+ printLine(g_pFile,COMMENT((char*)-1));
+ g_refs = refs;
+ if(newrefs) VDELETE(newrefs);
+}
+
+void CloseNamespace(__inout __nullterminated char* szString)
+{
+ if(strlen(g_szNamespace))
+ {
+ char* szptr = &szString[0];
+ if(g_szAsmCodeIndent[0]) g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s%s ",g_szAsmCodeIndent, UNSCOPE());
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("// end of namespace %s"),ProperName(g_szNamespace));
+ printLine(g_pFile,szString);
+ printLine(g_pFile,"");
+ g_szNamespace[0] = 0;
+ }
+}
+
+FILE* OpenOutput(__in __nullterminated const WCHAR* wzFileName)
+{
+ FILE* pfile = NULL;
+ if(g_uCodePage == 0xFFFFFFFF) _wfopen_s(&pfile,wzFileName,W("wb"));
+ else _wfopen_s(&pfile,wzFileName,W("wt"));
+
+ if(pfile)
+ {
+ if(g_uCodePage == CP_UTF8) fwrite("\357\273\277",3,1,pfile);
+ else if(g_uCodePage == 0xFFFFFFFF) fwrite("\377\376",2,1,pfile);
+ }
+ return pfile;
+}
+
+FILE* OpenOutput(__in __nullterminated const char* szFileName)
+{
+ return OpenOutput(UtfToUnicode(szFileName));
+}
+
+//
+// Init PELoader, dump file header info
+//
+#ifdef _PREFAST_
+#pragma warning(push)
+#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
+#endif
+BOOL DumpFile()
+{
+ BOOL fSuccess = FALSE;
+ static WCHAR wzInputFileName[MAX_FILENAME_LENGTH];
+ static char szFilenameANSI[MAX_FILENAME_LENGTH*3];
+ IMetaDataDispenser *pMetaDataDispenser = NULL;
+ const char *pszFilename = g_szInputFile;
+ const DWORD openFlags = ofRead | (g_fProject ? 0 : ofNoTransform);
+
+ if(!(g_Mode & MODE_GUI))
+ {
+ if(g_fDumpHTML)
+ {
+ printLine(g_pFile, "<HTML>");
+ printLine(g_pFile, "<HEAD>");
+ sprintf_s(szString,SZSTRING_SIZE,"<TITLE> %s - IL DASM</TITLE>",g_szInputFile);
+ printLine(g_pFile, szString);
+ printLine(g_pFile, "</HEAD>");
+ printLine(g_pFile, "<BODY>");
+ printLine(g_pFile, "<FONT SIZE=3 FACE=\"Arial\">");
+ printLine(g_pFile, "<PRE>");
+ }
+ else if(g_fDumpRTF)
+ {
+ DumpRTFPrefix(g_pFile,TRUE);
+ }
+ DumpPreamble();
+ }
+ {
+ char* pch = strrchr(g_szInputFile,'.');
+ if(pch && (!_stricmp(pch+1,"lib") || !_stricmp(pch+1,"obj")))
+ {
+ if(!(g_Mode & MODE_GUI))
+ DumpMetaInfo(g_wszFullInputFile,g_pszObjFileName,g_pFile);
+ return FALSE;
+ }
+ }
+
+ if(g_pPELoader) goto DoneInitialization; // skip initialization, it's already done
+
+ g_pPELoader = new PELoader();
+ if (g_pPELoader == NULL)
+ {
+ printError(g_pFile,RstrUTF(IDS_E_INITLDR));
+ goto exit;
+ }
+
+ memset(wzInputFileName,0,sizeof(WCHAR)*MAX_FILENAME_LENGTH);
+ WszMultiByteToWideChar(CP_UTF8,0,pszFilename,-1,wzInputFileName,MAX_FILENAME_LENGTH);
+ memset(szFilenameANSI,0,MAX_FILENAME_LENGTH*3);
+ WszWideCharToMultiByte(g_uConsoleCP,0,wzInputFileName,-1,szFilenameANSI,MAX_FILENAME_LENGTH*3,NULL,NULL);
+ fSuccess = g_pPELoader->open(wzInputFileName);
+
+ if (fSuccess == FALSE)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_FILEOPEN), pszFilename);
+ printError(g_pFile,szString);
+ SDELETE(g_pPELoader);
+ g_pPELoader = NULL;
+ goto exit;
+ }
+ fSuccess = FALSE;
+
+ if (g_pPELoader->getCOMHeader(&g_CORHeader) == FALSE)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_NOCORHDR), pszFilename);
+ printError(g_pFile,szString);
+ if (g_fDumpHeader)
+ DumpHeader(g_CORHeader,g_pFile);
+ goto exit;
+ }
+
+ if (VAL16(g_CORHeader->MajorRuntimeVersion) == 1 || VAL16(g_CORHeader->MajorRuntimeVersion) > COR_VERSION_MAJOR)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"CORHeader->MajorRuntimeVersion = %d",VAL16(g_CORHeader->MajorRuntimeVersion));
+ printError(g_pFile,szString);
+ printError(g_pFile,RstrUTF(IDS_E_BADCORHDR));
+ goto exit;
+ }
+ g_tkEntryPoint = VAL32(IMAGE_COR20_HEADER_FIELD(*g_CORHeader, EntryPointToken)); // integration with MetaInfo
+
+
+#if defined(_DEBUG) && defined(FEATURE_PREJIT)
+ if (g_fNGenNativeMetadata)
+ {
+ //if this is an ngen image, use the native metadata.
+ if( !g_CORHeader->ManagedNativeHeader.Size )
+ {
+ printError( g_pFile, "/native only works on NGen images." );
+ goto exit;
+ }
+ CORCOMPILE_HEADER * pNativeHeader;
+ g_pPELoader->getVAforRVA(VAL32(g_CORHeader->ManagedNativeHeader.VirtualAddress), (void**)&pNativeHeader);
+ g_pPELoader->getVAforRVA(VAL32(pNativeHeader->ManifestMetaData.VirtualAddress), &g_pMetaData);
+ g_cbMetaData = VAL32(pNativeHeader->ManifestMetaData.Size);
+ }
+ else
+#endif
+ {
+ if (g_pPELoader->getVAforRVA(VAL32(g_CORHeader->MetaData.VirtualAddress),&g_pMetaData) == FALSE)
+ {
+ printError(g_pFile, RstrUTF(IDS_E_OPENMD));
+ if (g_fDumpHeader)
+ DumpHeader(g_CORHeader, g_pFile);
+ goto exit;
+ }
+ g_cbMetaData = VAL32(g_CORHeader->MetaData.Size);
+ }
+
+#ifdef FEATURE_CORECLR
+ if (FAILED(getMetaDataInternalInterface(
+ (BYTE *)g_pMetaData,
+ g_cbMetaData,
+ openFlags,
+ IID_IMDInternalImport,
+ (LPVOID *)&g_pImport)))
+#else
+ if (FAILED(g_pCLRRuntimeHostInternal->GetMetaDataInternalInterface(
+ (BYTE *)g_pMetaData,
+ g_cbMetaData,
+ openFlags,
+ IID_IMDInternalImport,
+ (LPVOID *)&g_pImport)))
+#endif
+ {
+ if (g_fDumpHeader)
+ DumpHeader(g_CORHeader, g_pFile);
+ printError(g_pFile, RstrUTF(IDS_E_OPENMD));
+ goto exit;
+ }
+
+ TokenSigInit(g_pImport);
+#ifdef FEATURE_CORECLR
+ if (FAILED(metaDataGetDispenser(CLSID_CorMetaDataDispenser, IID_IMetaDataDispenser, (LPVOID*)&pMetaDataDispenser)))
+#else
+ if (FAILED(CoCreateInstance(CLSID_CorMetaDataDispenser, 0, CLSCTX_INPROC_SERVER, IID_IMetaDataDispenser, (LPVOID*)&pMetaDataDispenser)))
+#endif
+ {
+ if (g_fDumpHeader)
+ DumpHeader(g_CORHeader, g_pFile);
+ printError(g_pFile, RstrUTF(IDS_E_OPENMD));
+ goto exit;
+ }
+ if (FAILED(pMetaDataDispenser->OpenScopeOnMemory(g_pMetaData, g_cbMetaData, openFlags, IID_IMetaDataImport2, (LPUNKNOWN *)&g_pPubImport )))
+ {
+ if (g_fDumpHeader)
+ DumpHeader(g_CORHeader, g_pFile);
+ printError(g_pFile, RstrUTF(IDS_E_OPENMD));
+ goto exit;
+ }
+
+#ifndef FEATURE_CORECLR
+ // Get a symbol binder.
+ ISymUnmanagedBinder *binder;
+ HRESULT hr;
+
+ hr = CoCreateInstance(CLSID_CorSymBinder_SxS, NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_ISymUnmanagedBinder,
+ (void**)&binder);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = binder->GetReaderForFile(g_pPubImport,
+ wzInputFileName,
+ NULL,
+ &g_pSymReader);
+
+ // Release the binder
+ binder->Release();
+ }
+
+ if (FAILED(hr))
+ g_fShowSource = FALSE;
+#endif
+
+ if((g_uNCA = g_pImport->GetCountWithTokenKind(mdtCustomAttribute)))
+ {
+ g_rchCA = new char[g_uNCA+1];
+ _ASSERTE(g_rchCA);
+ }
+
+ EnumClasses();
+ EnumTypedefs();
+
+DoneInitialization:
+ if(g_uNCA)
+ {
+ _ASSERTE(g_rchCA);
+ memset(g_rchCA,0,g_uNCA+1);
+ }
+#ifndef _DEBUG
+ if(HasSuppressingAttribute())
+ {
+ if (g_fDumpHeader)
+ DumpHeader(g_CORHeader,g_pFile);
+ if(g_fDumpMetaInfo)
+ DumpMetaInfo(g_wszFullInputFile,NULL,g_pFile);
+ printError(g_pFile,RstrUTF(IDS_E_SUPPRESSED));
+ goto CloseFileAndExit;
+ }
+#endif
+
+#ifndef FEATURE_CORECLR
+ if (g_Mode & MODE_GUI)
+ {
+ GUIAddItemsToList();
+ }
+ else
+#endif
+ {
+ // Dump the CLR header info if requested.
+ printLine(g_pFile,COMMENT((char*)0)); // start multiline comment
+ if (g_fDumpHeader)
+ {
+ DumpHeader(g_CORHeader,g_pFile);
+ DumpHeaderDetails(g_CORHeader,g_pFile);
+ }
+ else
+ DumpVTables(g_CORHeader,g_pFile);
+ if (g_fDumpStats)
+ DumpStatistics(g_CORHeader,g_pFile);
+
+ if(g_fDumpClassList) PrintClassList();
+ // MetaInfo integration:
+ if(g_fDumpMetaInfo) DumpMetaInfo(g_wszFullInputFile,NULL,g_pFile);
+
+ if(g_fDumpSummary) DumpSummary();
+ printLine(g_pFile,COMMENT((char*)-1)); // end multiline comment
+
+ if(g_fShowRefs) g_refs = new DynamicArray<TokPair>;
+
+ if (g_fDumpAsmCode)
+ {
+ g_szNamespace[0] = 0;
+ if(g_tkClassToDump) //g_tkClassToDump is set in EnumClasses
+ {
+ DumpClass(TopEncloser(g_tkClassToDump), VAL32(IMAGE_COR20_HEADER_FIELD(*g_CORHeader, EntryPointToken)),g_pFile,7); //7-dump everything at once
+ CloseNamespace(szString);
+ goto ReportAndExit;
+ }
+ {
+ HENUMInternal hEnumMethod;
+ ULONG ulNumGlobalFunc=0;
+ if (SUCCEEDED(g_pImport->EnumGlobalFunctionsInit(&hEnumMethod)))
+ {
+ ulNumGlobalFunc = g_pImport->EnumGetCount(&hEnumMethod);
+ g_pImport->EnumClose(&hEnumMethod);
+ }
+#ifndef FEATURE_CORECLR
+ if(g_fShowProgressBar)
+ CreateProgressBar((LONG) (g_NumClasses + ulNumGlobalFunc));
+#endif
+
+ }
+#ifndef FEATURE_CORECLR
+ ProgressStep();
+#endif
+ g_fAbortDisassembly = FALSE;
+ //DumpVtable(g_pFile);
+ DumpMscorlib(g_pFile);
+ if(g_fDumpTypeList) DumpTypelist(g_pFile);
+ DumpManifest(g_pFile);
+ DumpTypedefs(g_pFile);
+ /* First dump the classes w/o members*/
+ if(g_fForwardDecl && g_NumClasses)
+ {
+ printLine(g_pFile,COMMENT("//"));
+ printLine(g_pFile,COMMENT("// ============== CLASS STRUCTURE DECLARATION =================="));
+ printLine(g_pFile,COMMENT("//"));
+ for (DWORD i = 0; i < g_NumClasses; i++)
+ {
+ if(g_cl_enclosing[i] == mdTypeDefNil) // nested classes are dumped within enclosing ones
+ {
+ DumpClass(g_cl_list[i], VAL32(IMAGE_COR20_HEADER_FIELD(*g_CORHeader, EntryPointToken)),g_pFile,2); // 2=header+nested classes
+ }
+ }
+ CloseNamespace(szString);
+ printLine(g_pFile,"");
+ printLine(g_pFile,COMMENT("// ============================================================="));
+ printLine(g_pFile,"");
+ }
+ /* Second, dump the global fields and methods */
+ DumpGlobalFields();
+ DumpGlobalMethods(VAL32(IMAGE_COR20_HEADER_FIELD(*g_CORHeader, EntryPointToken)));
+ /* Third, dump the classes with members */
+ if(g_NumClasses)
+ {
+ printLine(g_pFile,"");
+ printLine(g_pFile,COMMENT("// =============== CLASS MEMBERS DECLARATION ==================="));
+ if(g_fForwardDecl)
+ {
+ printLine(g_pFile,COMMENT("// note that class flags, 'extends' and 'implements' clauses"));
+ printLine(g_pFile,COMMENT("// are provided here for information only"));
+ }
+ printLine(g_pFile,"");
+ for (DWORD i = 0; i < g_NumClasses; i++)
+ {
+ if(g_cl_enclosing[i] == mdTypeDefNil) // nested classes are dumped within enclosing ones
+ {
+ DumpClass(g_cl_list[i], VAL32(IMAGE_COR20_HEADER_FIELD(*g_CORHeader, EntryPointToken)),g_pFile,7); //7=everything
+ if(g_fAbortDisassembly)
+ {
+ printError(g_pFile,"");
+ printError(g_pFile,RstrUTF(IDS_E_DASMABORT));
+ fSuccess = FALSE;
+ goto CloseFileAndExit;
+ }
+ }
+ }
+ CloseNamespace(szString);
+ printLine(g_pFile,"");
+ printLine(g_pFile,COMMENT("// ============================================================="));
+ printLine(g_pFile,"");
+ }
+ if(g_fShowCA)
+ {
+ if(g_uNCA) _ASSERTE(g_rchCA);
+ for(DWORD i=1; i<= g_uNCA; i++)
+ {
+ if(g_rchCA[i] == 0) DumpCustomAttribute(TokenFromRid(i,mdtCustomAttribute),g_pFile,true);
+ }
+ }
+ if(g_fAbortDisassembly)
+ {
+ printError(g_pFile,"");
+ printError(g_pFile,RstrUTF(IDS_E_DASMABORT));
+ fSuccess = FALSE;
+ goto CloseFileAndExit;
+ }
+#ifndef FEATURE_CORECLR
+ ProgressStep();
+#endif
+
+#if (0)
+ /* Third, dump GC/EH info about the native methods, using the IPMap */
+ IMAGE_DATA_DIRECTORY *pIPMap;
+ if (g_pPELoader->IsPE32())
+ {
+ pIPMap = &g_pPELoader->ntHeaders32()->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION];
+ }
+ else
+ {
+ pIPMap = &g_pPELoader->ntHeaders64()->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION];
+ }
+ DWORD IPMapSize;
+ const BYTE * ipmap;
+ IPMapSize = VAL32(pIPMap->Size);
+ g_pPELoader->getVAforRVA(VAL32(pIPMap->VirtualAddress), (void **) &ipmap);
+
+ DumpNativeInfo(ipmap, IPMapSize);
+#endif
+
+ // If there were "ldptr", dump the .rdata section with labels
+ if(g_iPtrCount)
+ {
+ //first, sort the pointers
+ int i,j;
+ bool swapped;
+ do {
+ swapped = FALSE;
+
+ for(i = 1; i < g_iPtrCount; i++)
+ {
+ if((*g_pPtrTags)[i-1] > (*g_pPtrTags)[i])
+ {
+ j = (*g_pPtrTags)[i-1];
+ (*g_pPtrTags)[i-1] = (*g_pPtrTags)[i];
+ (*g_pPtrTags)[i] = j;
+ j = (*g_pPtrSize)[i-1];
+ (*g_pPtrSize)[i-1] = (*g_pPtrSize)[i];
+ (*g_pPtrSize)[i] = j;
+ swapped = TRUE;
+ }
+ }
+ } while(swapped);
+
+ //second, dump data for each ptr as binarray
+
+ IMAGE_SECTION_HEADER *pSecHdr = NULL;
+ if(g_pPELoader->IsPE32())
+ pSecHdr = IMAGE_FIRST_SECTION(g_pPELoader->ntHeaders32());
+ else
+ pSecHdr = IMAGE_FIRST_SECTION(g_pPELoader->ntHeaders64());
+
+ DWORD dwNumberOfSections;
+ if(g_pPELoader->IsPE32())
+ dwNumberOfSections = VAL16(g_pPELoader->ntHeaders32()->FileHeader.NumberOfSections);
+ else
+ dwNumberOfSections = VAL16(g_pPELoader->ntHeaders64()->FileHeader.NumberOfSections);
+
+ DWORD fromPtr,toPtr,limPtr;
+ char* szptr;
+ for(j = 0; j < g_iPtrCount; j++)
+ {
+ BYTE *pb;
+
+ fromPtr = (*g_pPtrTags)[j];
+ for (i=0; i < (int)dwNumberOfSections; i++,pSecHdr++)
+ {
+ if((fromPtr >= VAL32(pSecHdr->VirtualAddress))&&
+ (fromPtr < VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->Misc.VirtualSize))) break;
+ }
+ if(i == (int)dwNumberOfSections)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_ROGUEPTR), fromPtr);
+ printLine(g_pFile,szString);
+ break;
+ }
+ // OK, now we have the section; what about end of BLOB?
+ const char* szTls = "D_";
+ if(strcmp((char*)(pSecHdr->Name),".tls")==0) szTls = "T_";
+ else if(strcmp((char*)(pSecHdr->Name),".text")==0) szTls = "I_";
+ if(j == g_iPtrCount-1)
+ {
+ toPtr = VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->Misc.VirtualSize);
+ }
+ else
+ {
+ toPtr = (*g_pPtrTags)[j+1];
+ if(toPtr > VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->Misc.VirtualSize))
+ {
+ toPtr = VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->Misc.VirtualSize);
+ }
+ }
+ if(toPtr - fromPtr > (*g_pPtrSize)[j]) toPtr = fromPtr + (*g_pPtrSize)[j];
+ limPtr = toPtr; // at limPtr and after, pad with 0
+ if(limPtr > VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->SizeOfRawData))
+ limPtr = VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->SizeOfRawData);
+ PrintBlob:
+ szptr = szString;
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".data"));
+ if(*szTls=='T') szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("tls "));
+ else if(*szTls=='I') szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("cil "));
+ if(fromPtr >= limPtr)
+ { // uninitialized data
+ sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s%8.8X = %s[%d]",szTls,fromPtr,KEYWORD("int8"),toPtr-fromPtr);
+ printLine(g_pFile,szString);
+ }
+ else
+ { // initialized data
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s%8.8X = %s (",szTls,fromPtr,KEYWORD("bytearray"));
+ printLine(g_pFile,szString);
+ szptr = szString;
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s ",g_szAsmCodeIndent);
+ pb = g_pPELoader->base()
+ + VAL32(pSecHdr->PointerToRawData)
+ + fromPtr - VAL32(pSecHdr->VirtualAddress);
+ // now fromPtr is the beginning of the BLOB, and toPtr is [exclusive] end of it
+ DumpHexbytes(szptr, pb, fromPtr, toPtr, limPtr);
+ }
+ // to preserve alignment, dump filler if any
+ if(limPtr == toPtr) // don't need filler if it's the last item in section
+ {
+ if((j < g_iPtrCount-1)&&(toPtr < (DWORD)((*g_pPtrTags)[j+1])))
+ {
+ DWORD align;
+ DWORD stptr = (DWORD)(*g_pPtrTags)[j+1];
+ for(align = 1; (align & stptr)==0; align = align << 1);
+ align -= 1;
+ if(toPtr & align)
+ {
+ fromPtr = toPtr;
+ toPtr = (toPtr + align)&~align;
+ goto PrintBlob;
+ }
+ }
+ }
+ }
+ }
+ReportAndExit:
+ printLine(g_pFile,COMMENT(RstrUTF(IDS_E_DASMOK)));
+ fSuccess = TRUE;
+ }
+ fSuccess = TRUE;
+#ifndef FEATURE_PAL
+ if(g_pFile) // dump .RES file (if any), if not to console
+ {
+ WCHAR wzResFileName[2048], *pwc;
+ memset(wzResFileName,0,sizeof(wzResFileName));
+ WszMultiByteToWideChar(CP_UTF8,0,g_szOutputFile,-1,wzResFileName,2048);
+ pwc = wcsrchr(wzResFileName,L'.');
+ if(pwc == NULL) pwc = &wzResFileName[wcslen(wzResFileName)];
+ wcscpy_s(pwc, 2048 - (pwc - wzResFileName), L".res");
+ DWORD ret = DumpResourceToFile(wzResFileName);
+ switch(ret)
+ {
+ case 0: szString[0] = 0; break;
+ case 1: sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_W_CREATEDW32RES)/*"// WARNING: Created Win32 resource file %ls"*/,
+ UnicodeToUtf(wzResFileName)); break;
+ case 0xDFFFFFFF: sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_CORRUPTW32RES)/*"// ERROR: Corrupt Win32 resources"*/); break;
+ case 0xEFFFFFFF: sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_CANTOPENW32RES)/*"// ERROR: Unable to open file %ls"*/,
+ UnicodeToUtf(wzResFileName)); break;
+ case 0xFFFFFFFF: sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_CANTACCESSW32RES)/*"// ERROR: Unable to access Win32 resources"*/); break;
+ }
+ if(szString[0])
+ {
+ if(ret == 1) printLine(g_pFile,COMMENT(szString));
+ else printError(g_pFile,szString);
+ }
+ }
+#endif
+ if(g_fShowRefs) DumpRefs(TRUE);
+ if(g_fDumpHTML)
+ {
+ printLine(g_pFile, "</PRE>");
+ printLine(g_pFile, "</BODY>");
+ printLine(g_pFile, "</HTML>");
+ }
+ else if(g_fDumpRTF)
+ {
+ DumpRTFPostfix(g_pFile);
+ }
+
+CloseFileAndExit:
+ if(g_pFile)
+ {
+ fclose(g_pFile);
+ g_pFile = NULL;
+ }
+#ifndef FEATURE_CORECLR
+ DestroyProgressBar();
+#endif
+ }
+
+exit:
+ if (pMetaDataDispenser)
+ pMetaDataDispenser->Release();
+ return fSuccess;
+}
+#ifdef _PREFAST_
+#pragma warning(pop)
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(default : 4640)
+#endif
+
+