summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ildasm/.gitmirrorall1
-rw-r--r--src/ildasm/DynamicArray.h110
-rw-r--r--src/ildasm/Litening.icobin0 -> 766 bytes
-rw-r--r--src/ildasm/ceeload.cpp267
-rw-r--r--src/ildasm/ceeload.h78
-rw-r--r--src/ildasm/class.bmpbin0 -> 3126 bytes
-rw-r--r--src/ildasm/classa.bmpbin0 -> 1318 bytes
-rw-r--r--src/ildasm/classag.bmpbin0 -> 1318 bytes
-rw-r--r--src/ildasm/classe.bmpbin0 -> 1318 bytes
-rw-r--r--src/ildasm/classeg.bmpbin0 -> 1318 bytes
-rw-r--r--src/ildasm/classi.bmpbin0 -> 1318 bytes
-rw-r--r--src/ildasm/classig.bmpbin0 -> 1318 bytes
-rw-r--r--src/ildasm/classv.bmpbin0 -> 1318 bytes
-rw-r--r--src/ildasm/classvg.bmpbin0 -> 1318 bytes
-rw-r--r--src/ildasm/dasm.cpp7870
-rw-r--r--src/ildasm/dasm.rc503
-rw-r--r--src/ildasm/dasm_formattype.cpp305
-rw-r--r--src/ildasm/dasm_mi.cpp9
-rw-r--r--src/ildasm/dasm_pr.cpp274
-rw-r--r--src/ildasm/dasm_sz.cpp230
-rw-r--r--src/ildasm/dasm_sz.h15
-rw-r--r--src/ildasm/dasmenum.hpp32
-rw-r--r--src/ildasm/dasmgui.h16
-rw-r--r--src/ildasm/dasmhlp.hhc32
-rw-r--r--src/ildasm/dirs.proj15
-rw-r--r--src/ildasm/dis.cpp2787
-rw-r--r--src/ildasm/dis.h154
-rw-r--r--src/ildasm/dman.cpp1073
-rw-r--r--src/ildasm/dres.cpp315
-rw-r--r--src/ildasm/event.bmpbin0 -> 1318 bytes
-rw-r--r--src/ildasm/exe/ildasm.nativeproj71
-rw-r--r--src/ildasm/field.bmpbin0 -> 1318 bytes
-rw-r--r--src/ildasm/gui.cpp4013
-rw-r--r--src/ildasm/gui.h156
-rw-r--r--src/ildasm/html/clicking.htm35
-rw-r--r--src/ildasm/html/keyboard.htm166
-rw-r--r--src/ildasm/html/menu_options.htm324
-rw-r--r--src/ildasm/html/tree_view_icons.htm102
-rw-r--r--src/ildasm/html/tree_view_icons_files/class.gifbin0 -> 960 bytes
-rw-r--r--src/ildasm/html/tree_view_icons_files/enum.gifbin0 -> 987 bytes
-rw-r--r--src/ildasm/html/tree_view_icons_files/event.gifbin0 -> 963 bytes
-rw-r--r--src/ildasm/html/tree_view_icons_files/field.gifbin0 -> 965 bytes
-rw-r--r--src/ildasm/html/tree_view_icons_files/interface.gifbin0 -> 981 bytes
-rw-r--r--src/ildasm/html/tree_view_icons_files/manifest_classinfo.GIFbin0 -> 843 bytes
-rw-r--r--src/ildasm/html/tree_view_icons_files/manifest_classinfo.jpgbin0 -> 723 bytes
-rw-r--r--src/ildasm/html/tree_view_icons_files/manifest_classinfo.pngbin0 -> 926 bytes
-rw-r--r--src/ildasm/html/tree_view_icons_files/method.gifbin0 -> 963 bytes
-rw-r--r--src/ildasm/html/tree_view_icons_files/namespace.gifbin0 -> 969 bytes
-rw-r--r--src/ildasm/html/tree_view_icons_files/property.gifbin0 -> 961 bytes
-rw-r--r--src/ildasm/html/tree_view_icons_files/static_field.gifbin0 -> 978 bytes
-rw-r--r--src/ildasm/html/tree_view_icons_files/static_method.gifbin0 -> 977 bytes
-rw-r--r--src/ildasm/html/tree_view_icons_files/value_class.gifbin0 -> 960 bytes
-rw-r--r--src/ildasm/ildasm.chmbin0 -> 18371 bytes
-rw-r--r--src/ildasm/ildasm.hhp36
-rw-r--r--src/ildasm/ildasmpch.cpp8
-rw-r--r--src/ildasm/ildasmpch.h26
-rw-r--r--src/ildasm/map.h9
-rw-r--r--src/ildasm/method.bmpbin0 -> 1318 bytes
-rw-r--r--src/ildasm/methodg.bmpbin0 -> 1318 bytes
-rw-r--r--src/ildasm/namespace.bmpbin0 -> 1318 bytes
-rw-r--r--src/ildasm/prop.bmpbin0 -> 1318 bytes
-rw-r--r--src/ildasm/rcdll/ildasmrc.nativeproj18
-rw-r--r--src/ildasm/redarrow.bmpbin0 -> 1318 bytes
-rw-r--r--src/ildasm/resource.h325
-rw-r--r--src/ildasm/staticfield.bmpbin0 -> 1318 bytes
-rw-r--r--src/ildasm/staticmethod.bmpbin0 -> 1318 bytes
-rw-r--r--src/ildasm/staticmethodg.bmpbin0 -> 1318 bytes
-rw-r--r--src/ildasm/util.hpp23
-rw-r--r--src/ildasm/windasm.cpp698
-rw-r--r--src/tools/metainfo/.gitmirrorall1
-rw-r--r--src/tools/metainfo/Native.rc9
-rw-r--r--src/tools/metainfo/mdinfo.cpp4320
-rw-r--r--src/tools/metainfo/mdinfo.h206
-rw-r--r--src/tools/metainfo/mdobj.cpp299
-rw-r--r--src/tools/metainfo/metainfo.cpp199
-rw-r--r--src/tools/metainfo/metainfo.nativeproj42
76 files changed, 25172 insertions, 0 deletions
diff --git a/src/ildasm/.gitmirrorall b/src/ildasm/.gitmirrorall
new file mode 100644
index 0000000000..9ee5c57b99
--- /dev/null
+++ b/src/ildasm/.gitmirrorall
@@ -0,0 +1 @@
+This folder will be mirrored by the Git-TFS Mirror recursively. \ No newline at end of file
diff --git a/src/ildasm/DynamicArray.h b/src/ildasm/DynamicArray.h
new file mode 100644
index 0000000000..eb2aab269f
--- /dev/null
+++ b/src/ildasm/DynamicArray.h
@@ -0,0 +1,110 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#ifndef DYNAMICARRAY_H
+
+#define DYNAMICARRAY_H
+
+#include "memory.h"
+
+const int START_SIZE = 24 ;
+const int MIN_SIZE = 8 ;
+
+template <class T>
+class DynamicArray
+{
+ public:
+ DynamicArray(int iSize = START_SIZE) ;
+ ~DynamicArray() ;
+ T& operator[](int i) ;
+ bool Error() ;
+ private:
+ T* m_pArray ;
+ int m_iMemSize ;
+ int m_iArraySize ;
+ bool m_bError ;
+};
+
+/************************************************************************
+ * *
+ * Default constructor. User has option to pass in the size of the *
+ * initial array. *
+ * *
+ ************************************************************************/
+template<class T> DynamicArray<T>::DynamicArray(int iSize)
+{
+ if( iSize < MIN_SIZE )
+ {
+ iSize = MIN_SIZE ;
+ }
+ m_pArray = new T[iSize] ;
+ m_iMemSize = iSize ;
+ m_iArraySize = 0 ;
+ m_bError = false ;
+}
+
+/************************************************************************
+ * *
+ * Destructor. All it really has to do is delete the array. *
+ * *
+ ************************************************************************/
+template<class T> DynamicArray<T>::~DynamicArray()
+{
+ if( m_pArray )
+ {
+ delete [] m_pArray ;
+ }
+}
+
+/************************************************************************
+ * *
+ * operator [] to work on the left or right side of the equation. *
+ * *
+ ************************************************************************/
+template<class T> T& DynamicArray<T>::operator [](int iIndex)
+{
+ if( iIndex < 0 )
+ {
+ // Error, set error value to true and return the first element of the array
+ m_bError = true ;
+ return m_pArray[0] ;
+ }
+ else if ( iIndex >= m_iArraySize )
+ {
+ if( iIndex >= m_iMemSize )
+ {
+ int iNewSize ;
+ if( iIndex >= m_iMemSize * 2 )
+ {
+ iNewSize = iIndex + 1 ;
+ }
+ else
+ {
+ iNewSize = m_iMemSize * 2 ;
+ }
+
+ // We need to allocate more memory
+ T* pTmp = new T[iNewSize] ;
+ memcpy(pTmp, m_pArray, m_iMemSize * sizeof(T)) ;
+ delete [] m_pArray ;
+ m_pArray = pTmp ;
+ // Record the new memory size
+ m_iMemSize = iNewSize ;
+ }
+
+ //ZeroMemory(&m_pArray[iIndex], sizeof(T)) ;
+
+ ++m_iArraySize ;
+ }
+
+ return m_pArray[iIndex] ;
+}
+
+template<class T> bool DynamicArray<T>::Error()
+{
+ return m_bError ;
+}
+
+#endif
diff --git a/src/ildasm/Litening.ico b/src/ildasm/Litening.ico
new file mode 100644
index 0000000000..7bdaa4f1e9
--- /dev/null
+++ b/src/ildasm/Litening.ico
Binary files differ
diff --git a/src/ildasm/ceeload.cpp b/src/ildasm/ceeload.cpp
new file mode 100644
index 0000000000..1c71ecfbd8
--- /dev/null
+++ b/src/ildasm/ceeload.cpp
@@ -0,0 +1,267 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+//
+// CEELOAD reads in the PE file format using LoadLibrary
+// ===========================================================================
+#include "ildasmpch.h"
+
+#include "ceeload.h"
+#include <corhdr.h>
+#include <corimage.h>
+#include "util.hpp"
+#include "pedecoder.h"
+
+/*************************************************************************************/
+// Constructor and destructor!
+/*************************************************************************************/
+PELoader::PELoader()
+{
+ m_hFile = NULL;
+ m_hMod = NULL;
+ m_hMapFile = NULL;
+ m_pNT64 = NULL;
+ m_bIsPE32 = FALSE;
+ m_FileSize = m_FileSizeAligned = 0;
+}
+
+PELoader::~PELoader()
+{
+
+ m_hMod = NULL;
+ m_pNT64 = NULL;
+ // If we have an hFile then we opened this file ourselves!
+ // If we do not then this file was loaded by the OS and the OS will
+ // close it for us.
+ if (m_hFile)
+ this->close();
+}
+
+/*************************************************************************************/
+/*************************************************************************************/
+void PELoader::close()
+{
+
+ // _ASSERTE(m_hFile != NULL);
+ if (m_hFile)
+ {
+ if (m_hMod)
+ UnmapViewOfFile((void*)m_hMod);
+ if (m_hMapFile)
+ CloseHandle(m_hMapFile);
+ CloseHandle(m_hFile);
+
+ m_hMod = NULL;
+ m_hMapFile = NULL;
+ m_hFile = NULL;
+ m_FileSize = m_FileSizeAligned = 0;
+ }
+}
+
+
+BOOL PELoader::open(LPCSTR moduleName)
+{
+ HMODULE newhMod = NULL;
+ DWORD dwFileSizeLow;
+
+ _ASSERTE(moduleName);
+ if (!moduleName)
+ return FALSE;
+
+
+ m_hFile = CreateFileA(moduleName, GENERIC_READ, FILE_SHARE_READ,
+ 0, OPEN_EXISTING, 0, 0);
+ if (m_hFile == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ dwFileSizeLow = GetFileSize( m_hFile, NULL);
+ if (dwFileSizeLow == INVALID_FILE_SIZE)
+ return FALSE;
+ m_FileSize = dwFileSizeLow;
+
+ m_hMapFile = WszCreateFileMapping(m_hFile, NULL, PAGE_READONLY, 0, 0, NULL);
+ if (m_hMapFile == NULL)
+ return FALSE;
+
+ newhMod = (HMODULE) MapViewOfFile(m_hMapFile, FILE_MAP_READ, 0, 0, 0);
+ if (newhMod == NULL)
+ return FALSE;
+ return open(newhMod);
+}
+
+BOOL PELoader::open(const WCHAR* moduleName)
+{
+ HMODULE newhMod = NULL;
+ DWORD dwFileSizeLow;
+
+ _ASSERTE(moduleName);
+ if (!moduleName)
+ return FALSE;
+
+ m_hFile = WszCreateFile(moduleName, GENERIC_READ, FILE_SHARE_READ,
+ 0, OPEN_EXISTING, 0, 0);
+ if (m_hFile == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ dwFileSizeLow = GetFileSize( m_hFile, NULL);
+ if (dwFileSizeLow == INVALID_FILE_SIZE)
+ return FALSE;
+ m_FileSize = dwFileSizeLow;
+
+ m_hMapFile = WszCreateFileMapping(m_hFile, NULL, PAGE_READONLY, 0, 0, NULL);
+ if (m_hMapFile == NULL)
+ return FALSE;
+
+ newhMod = (HMODULE) MapViewOfFile(m_hMapFile, FILE_MAP_READ, 0, 0, 0);
+ if (newhMod == NULL)
+ return FALSE;
+ return open(newhMod);
+}
+
+
+/*************************************************************************************/
+BOOL PELoader::open(HMODULE hMod)
+{
+ IMAGE_DOS_HEADER * pdosHeader;
+
+ // get the dos header...
+ m_hMod = hMod;
+ pdosHeader = (IMAGE_DOS_HEADER*) hMod;
+ // If this is not a PE32+ image
+ if (pdosHeader->e_magic == VAL16(IMAGE_DOS_SIGNATURE) &&
+ 0 < VAL32(pdosHeader->e_lfanew) && VAL32(pdosHeader->e_lfanew) < 0xFF0) // has to start on first page
+ {
+ size_t fileAlignment;
+
+ m_pNT32 = (IMAGE_NT_HEADERS32*) ((BYTE *)m_hMod + VAL32(pdosHeader->e_lfanew));
+
+ m_bIsPE32 = (m_pNT32->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC));
+
+ if (m_bIsPE32)
+ {
+ if ((m_pNT32->Signature != VAL32(IMAGE_NT_SIGNATURE)) ||
+ (m_pNT32->FileHeader.SizeOfOptionalHeader != VAL16(sizeof(IMAGE_OPTIONAL_HEADER32))))
+ {
+ // Make this appear uninitalized because for some reason this file is toasted.
+ m_pNT32 = NULL;
+ m_hMod = NULL;
+ return FALSE;
+ }
+ fileAlignment = VAL32(m_pNT32->OptionalHeader.FileAlignment)-1;
+ }
+ else //For now assume not i386 is IA64
+ {
+ if ((m_pNT64->Signature != VAL32(IMAGE_NT_SIGNATURE)) ||
+ (m_pNT64->FileHeader.SizeOfOptionalHeader != VAL16(sizeof(IMAGE_OPTIONAL_HEADER64))))
+ {
+ // Make this appear uninitalized because for some reason this file is toasted.
+ m_pNT64 = NULL;
+ m_hMod = NULL;
+ return FALSE;
+ }
+ fileAlignment = VAL32(m_pNT64->OptionalHeader.FileAlignment)-1;
+ }
+ m_FileSizeAligned = (m_FileSize + fileAlignment)&(~fileAlignment);
+ }
+ else
+ {
+ // Make this appear uninitalized because for some reason this file is toasted.
+ m_hMod = NULL;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*************************************************************************************/
+void PELoader::dump()
+{
+}
+
+/*************************************************************************************/
+BOOL PELoader::getCOMHeader(IMAGE_COR20_HEADER **ppCorHeader)
+{
+ PIMAGE_SECTION_HEADER pSectionHeader;
+
+ if (m_bIsPE32)
+ {
+ PIMAGE_NT_HEADERS32 pImageHeader;
+ // Get the image header from the image, then get the directory location
+ // of the COM+ header which may or may not be filled out.
+ pImageHeader = (PIMAGE_NT_HEADERS32)Cor_RtlImageNtHeader(m_hMod, (ULONG) m_FileSize);
+ PREFIX_ASSUME(pImageHeader != NULL);
+ pSectionHeader = (PIMAGE_SECTION_HEADER) Cor_RtlImageRvaToVa32(pImageHeader, (PBYTE)m_hMod,
+ VAL32(pImageHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COMHEADER].VirtualAddress),
+ (DWORD)m_FileSizeAligned /* FileLength */);
+ }
+ else
+ {
+ PIMAGE_NT_HEADERS64 pImageHeader;
+
+ // Get the image header from the image, then get the directory location
+ // of the COM+ header which may or may not be filled out.
+ pImageHeader = (PIMAGE_NT_HEADERS64)Cor_RtlImageNtHeader(m_hMod, (ULONG) m_FileSize);
+ PREFIX_ASSUME(pImageHeader != NULL);
+ pSectionHeader = (PIMAGE_SECTION_HEADER) Cor_RtlImageRvaToVa64(pImageHeader, (PBYTE)m_hMod,
+ VAL32(pImageHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COMHEADER].VirtualAddress),
+ (DWORD)m_FileSizeAligned /* FileLength */);
+ }
+
+ // If the section header exists, then return ok and the address.
+ if (pSectionHeader)
+ {
+ *ppCorHeader = (IMAGE_COR20_HEADER *) pSectionHeader;
+ return TRUE;
+ }
+ // If there is no COM+ Data in this image, return false.
+ else
+ return FALSE;
+}
+
+/*************************************************************************************/
+BOOL PELoader::getVAforRVA(DWORD rva,void **ppva)
+{
+ PIMAGE_SECTION_HEADER pSectionHeader;
+
+ if (m_bIsPE32)
+ {
+ // Get the image header from the image, then get the directory location
+ // of the COM+ header which may or may not be filled out.
+ PIMAGE_NT_HEADERS32 pImageHeader;
+ pImageHeader = (PIMAGE_NT_HEADERS32) Cor_RtlImageNtHeader(m_hMod, (ULONG) m_FileSize);
+ PREFIX_ASSUME(pImageHeader != NULL);
+ pSectionHeader = (PIMAGE_SECTION_HEADER) Cor_RtlImageRvaToVa32(pImageHeader, (PBYTE)m_hMod,
+ rva, (DWORD)m_FileSizeAligned /* FileLength */);
+ }
+ else
+ {
+ PIMAGE_NT_HEADERS64 pImageHeader;
+ pImageHeader = (PIMAGE_NT_HEADERS64) Cor_RtlImageNtHeader(m_hMod, (ULONG) m_FileSize);
+ PREFIX_ASSUME(pImageHeader != NULL);
+ pSectionHeader = (PIMAGE_SECTION_HEADER) Cor_RtlImageRvaToVa64(pImageHeader, (PBYTE)m_hMod,
+ rva, (DWORD)m_FileSizeAligned /* FileLength */);
+ }
+
+ // If the section header exists, then return ok and the address.
+ if (pSectionHeader)
+ {
+ *ppva = pSectionHeader;
+ return TRUE;
+ }
+ // If there is no COM+ Data in this image, return false.
+ else
+ return FALSE;
+}
+
+void SectionInfo::Init(PELoader *pPELoader, IMAGE_DATA_DIRECTORY *dir)
+{
+ _ASSERTE(dir);
+ m_dwSectionOffset = VAL32(dir->VirtualAddress);
+ if (m_dwSectionOffset != 0)
+ m_pSection = pPELoader->base() + m_dwSectionOffset;
+ else
+ m_pSection = 0;
+ m_dwSectionSize = VAL32(dir->Size);
+}
+
diff --git a/src/ildasm/ceeload.h b/src/ildasm/ceeload.h
new file mode 100644
index 0000000000..a6c5d63bea
--- /dev/null
+++ b/src/ildasm/ceeload.h
@@ -0,0 +1,78 @@
+// ==++==
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// ==--==
+// ===========================================================================
+// File: CEELOAD.H
+//
+
+// CEELOAD.H defines the class use to represent the PE file
+// ===========================================================================
+#ifndef CEELoad_H
+#define CEELoad_H
+
+class PELoader;
+
+//
+// Used to cache information about sections we're interested in (descr, callsig, il)
+//
+class SectionInfo
+{
+public:
+ BYTE * m_pSection; // pointer to the beginning of the section
+ DWORD m_dwSectionOffset; // RVA
+ DWORD m_dwSectionSize;
+
+ // init this class's member variables from the provided directory
+ void Init(PELoader *pPELoader, IMAGE_DATA_DIRECTORY *dir);
+
+ // returns whether this RVA is inside the section
+ BOOL InSection(DWORD dwRVA)
+ {
+ return (dwRVA >= m_dwSectionOffset) && (dwRVA < m_dwSectionOffset + m_dwSectionSize);
+ }
+};
+
+class PELoader {
+ protected:
+
+ HMODULE m_hMod;
+ HANDLE m_hFile;
+ HANDLE m_hMapFile;
+ BOOL m_bIsPE32;
+ size_t m_FileSize;
+ size_t m_FileSizeAligned;
+
+ union
+ {
+ PIMAGE_NT_HEADERS64 m_pNT64;
+ PIMAGE_NT_HEADERS32 m_pNT32;
+ };
+
+ public:
+ SectionInfo m_DescrSection;
+ SectionInfo m_CallSigSection;
+ SectionInfo m_ILSection;
+
+ PELoader();
+ ~PELoader();
+ BOOL open(const char* moduleNameIn);
+ BOOL open(const WCHAR* moduleNameIn);
+ BOOL open(HMODULE hMod);
+ BOOL getCOMHeader(IMAGE_COR20_HEADER **ppCorHeader);
+ BOOL getVAforRVA(DWORD rva,void **ppCorHeader);
+ void close();
+ void dump();
+ inline BOOL IsPE32() { return m_bIsPE32; };
+ inline PIMAGE_NT_HEADERS32 ntHeaders32() { return m_pNT32; };
+ inline PIMAGE_NT_HEADERS64 ntHeaders64() { return m_pNT64; };
+ inline PIMAGE_DOS_HEADER dosHeader() { return (PIMAGE_DOS_HEADER)m_hMod; };
+ inline PIMAGE_FILE_HEADER coffHeader() { return &(m_pNT32->FileHeader); };
+ inline DWORD Signature() { return m_pNT32->Signature; };
+ inline BYTE* base() { return (BYTE*) m_hMod; };
+ inline HMODULE getHModule() { return m_hMod; };
+ inline HANDLE getHFile() { return m_hFile; } ;
+};
+
+#endif // CEELoad_H
diff --git a/src/ildasm/class.bmp b/src/ildasm/class.bmp
new file mode 100644
index 0000000000..1574b641df
--- /dev/null
+++ b/src/ildasm/class.bmp
Binary files differ
diff --git a/src/ildasm/classa.bmp b/src/ildasm/classa.bmp
new file mode 100644
index 0000000000..d0467c45e3
--- /dev/null
+++ b/src/ildasm/classa.bmp
Binary files differ
diff --git a/src/ildasm/classag.bmp b/src/ildasm/classag.bmp
new file mode 100644
index 0000000000..72793ce02f
--- /dev/null
+++ b/src/ildasm/classag.bmp
Binary files differ
diff --git a/src/ildasm/classe.bmp b/src/ildasm/classe.bmp
new file mode 100644
index 0000000000..a5f641c915
--- /dev/null
+++ b/src/ildasm/classe.bmp
Binary files differ
diff --git a/src/ildasm/classeg.bmp b/src/ildasm/classeg.bmp
new file mode 100644
index 0000000000..3aeded1ed2
--- /dev/null
+++ b/src/ildasm/classeg.bmp
Binary files differ
diff --git a/src/ildasm/classi.bmp b/src/ildasm/classi.bmp
new file mode 100644
index 0000000000..74d64feb09
--- /dev/null
+++ b/src/ildasm/classi.bmp
Binary files differ
diff --git a/src/ildasm/classig.bmp b/src/ildasm/classig.bmp
new file mode 100644
index 0000000000..79b43144a9
--- /dev/null
+++ b/src/ildasm/classig.bmp
Binary files differ
diff --git a/src/ildasm/classv.bmp b/src/ildasm/classv.bmp
new file mode 100644
index 0000000000..ecf345ac05
--- /dev/null
+++ b/src/ildasm/classv.bmp
Binary files differ
diff --git a/src/ildasm/classvg.bmp b/src/ildasm/classvg.bmp
new file mode 100644
index 0000000000..a77f99b359
--- /dev/null
+++ b/src/ildasm/classvg.bmp
Binary files differ
diff --git a/src/ildasm/dasm.cpp b/src/ildasm/dasm.cpp
new file mode 100644
index 0000000000..a9cb52e707
--- /dev/null
+++ b/src/ildasm/dasm.cpp
@@ -0,0 +1,7870 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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
+
+// Define also LegacyActivationShim::CoInitializeEE wrapper around CoInitializeEE
+#define LEGACY_ACTIVATION_SHIM_DEFINE_CoInitializeEE
+#include "LegacyActivationShim.h"
+#include "clrinternal.h"
+
+
+
+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_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),L"// ");
+ 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),L"%s// ");
+ buff +=5;
+ cchBuff -= 5;
+ break;
+ case IDS_E_NORVA:
+ wcscpy_s(buffer,COUNTOF(buffer),L"/* ");
+ buff += 3;
+ cchBuff -= 3;
+ break;
+ default:
+ break;
+ }
+ _ASSERTE(g_hResources != NULL);
+ WszLoadString(g_hResources,id,buff,cchBuff);
+ if(id == IDS_E_NORVA)
+ wcscat_s(buff,cchBuff,L" */");
+ 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;
+
+// CLR internal hosting API
+ICLRRuntimeHostInternal *g_pCLRRuntimeHostInternal = NULL;
+
+BOOL Init()
+{
+ 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;
+ }
+
+ 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()
+{
+ GUIAddOpcode(NULL,NULL);
+
+ 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);
+ }
+
+ if (g_pCLRRuntimeHostInternal != NULL)
+ {
+ g_pCLRRuntimeHostInternal->Release();
+ g_pCLRRuntimeHostInternal = NULL;
+ }
+
+ LegacyActivationShim::CoUninitializeEE(COUNINITEE_DEFAULT);
+ LegacyActivationShim::CoUninitializeCor();
+ CoUninitialize();
+} // 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;
+
+ WIN_PAL_CPP_TRY
+ {
+ if (strcmp(PrettyPrintClass(&out, g_cl_list[i], g_pImport), g_pszClassToDump) == 0)
+ {
+ g_tkClassToDump = g_cl_list[i];
+ }
+ }
+ WIN_PAL_CPP_CATCH_ALL
+ { }
+ WIN_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,L"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;
+ WIN_PAL_CPP_TRY {
+ byt = pBlob[j];
+ }
+ WIN_PAL_CPP_CATCH_ALL
+ {
+ strcat_s(szString, SZSTRING_SIZE,ERRORMSG("INVALID DATA ADDRESS"));
+ bBreak = TRUE;
+ }
+ WIN_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 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* szNamespace = "";
+ char* szName = str;
+ char* szAssembly = NULL;
+ 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 = "mscorlib";
+ }
+ 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;
+
+ if (FAILED(g_pCLRRuntimeHostInternal->GetMetaDataInternalInterfaceFromPublic(
+ pUnk,
+ IID_IMDInternalImport,
+ (LPVOID *)ppIMDInew)))
+ {
+ 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))||(strchr(str,'#') != NULL))
+ 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))||(strchr(str,'#') != NULL))
+ 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;
+ 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;
+
+ pszMemberName;
+ 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(szString, 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)&&(strchr(szf,'#') == NULL))
+ 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)&&(strchr(szf,'#') == NULL))
+ 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)," = ");
+ WIN_PAL_CPP_TRY {
+ szptr = DumpUnicodeString(GUICookie,szString,(WCHAR*)MDDV.m_wzValue,MDDV.m_cbSize/sizeof(WCHAR));
+ } WIN_PAL_CPP_CATCH_ALL {
+ strcat_s(szString, SZSTRING_SIZE,ERRORMSG("INVALID DATA ADDRESS"));
+ } WIN_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),"(");
+ WIN_PAL_CPP_TRY {
+ DumpByteArray(szString,(BYTE*)MDDV.m_wzValue,MDDV.m_cbSize,GUICookie);
+ } WIN_PAL_CPP_CATCH_ALL {
+ szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(" Invalid blob at 0x%08X)"), MDDV.m_wzValue);
+ } WIN_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];
+
+ WIN_PAL_CPP_TRY
+ {
+ fRet = Disassemble(pImport, ILHeader, GUICookie, FuncToken, pszArgname, ulArgs);
+ }
+ WIN_PAL_CPP_CATCH_ALL
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_DASMERR),g_szAsmCodeIndent);
+ printLine(GUICookie, szString);
+ }
+ WIN_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* pszTailSig = "";
+ 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[32];
+ 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;
+
+ WIN_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: ;
+ } WIN_PAL_CPP_CATCH_ALL {
+ printError(GUICookie,"INVALID DATA ADDRESS");
+ bRet = TRUE;
+ } WIN_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;
+
+ WIN_PAL_CPP_TRY
+ {
+ CQuickBytes qbTempSig;
+ pszPlainSig = PrettyPrintSig(pComSig, cComSig, "", &qbTempSig, g_pImport, NULL);
+ }
+ WIN_PAL_CPP_CATCH_ALL
+ {
+ pszPlainSig = "";
+ }
+ WIN_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,32,(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)
+#ifdef _WIN64
+ sprintf_s(szArgPrefix,32,"@%I64d0",(size_t)pszArgname);
+#else
+ sprintf_s(szArgPrefix,32,"@%d0",(size_t)pszArgname);
+#endif //_WIN64
+ } //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;
+ }
+ 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;
+ WIN_PAL_CPP_TRY {
+ szStr = PrettyPrintSig(pComSig, cComSig, (DumpBody ? pszMemberName : ""), &qbMemberSig, g_pImport,NULL);
+ }
+ WIN_PAL_CPP_CATCH_ALL
+ {
+ printError(GUICookie,"INVALID ADDRESS IN FIELD SIGNATURE");
+ bRet = TRUE;
+ } WIN_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;
+ WIN_PAL_CPP_TRY
+ {
+ CQuickBytes qbTempSig;
+ pszPlainSig = PrettyPrintSig(pComSig, cComSig, "", &qbTempSig, g_pImport, NULL);
+ }
+ WIN_PAL_CPP_CATCH_ALL
+ {
+ pszPlainSig = "";
+ }
+ WIN_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 *pch = "";
+ if(DumpBody)
+ {
+ pch = szptr+1;
+ strcpy_s(pch,SZSTRING_REMAINING_SIZE(szptr),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);
+ if(!ProgressStep()) g_fAbortDisassembly = TRUE;
+ }
+
+ 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;
+
+ if(!ProgressStep())
+ {
+ g_fAbortDisassembly = TRUE;
+ break;
+ }
+ }
+ 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(L"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* szString,BYTE *pb, DWORD fromPtr, DWORD toPtr, DWORD limPtr)
+{
+ char sz[256];
+ char* szptr = &szString[strlen(szString)];
+ 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
+ {
+ WIN_PAL_CPP_TRY
+ {
+ sz[k] = *pb; // check the ptr validity
+ }
+ WIN_PAL_CPP_CATCH_ALL
+ {
+ pb = &zero;
+ } WIN_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)
+{
+ WIN_PAL_CPP_TRY
+ {
+ DumpEATEntries(GUICookie, pNTHeader32, pOptHeader32, pNTHeader64, pOptHeader64);
+ }
+ WIN_PAL_CPP_CATCH_ALL
+ {
+ printError(GUICookie,"// ERROR READING EXPORT ADDRESS TABLE");
+ if (g_prEATableRef != NULL)
+ {
+ SDELETE(g_prEATableRef);
+ }
+ g_nEATableRef = 0;
+ }
+ WIN_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);
+ {
+ 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])
+ {
+ wcscpy_s(wzMsg,L,szMsg);
+ // include token and offset from Context
+ if(Context.Token) swprintf_s(&wzMsg[wcslen(wzMsg)], L-wcslen(wzMsg), L" [token:0x%08X]",Context.Token);
+ if(Context.uOffset) swprintf_s(&wzMsg[wcslen(wzMsg)], L-wcslen(wzMsg), L" [at:0x%X]",Context.uOffset);
+ swprintf_s(&wzMsg[wcslen(wzMsg)], L-wcslen(wzMsg), L" [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,L"lib") || !_wcsicmp(pch+1,L"obj")))
+ { // This works only when all the rest does not
+ // Init and run.
+ if(SUCCEEDED(CoInitialize(0)))
+ {
+ if(SUCCEEDED(LegacyActivationShim::CoInitializeCor(0)))
+ {
+ if (SUCCEEDED(LegacyActivationShim::ClrCoCreateInstance(
+ CLSID_CorMetaDataDispenser, NULL, CLSCTX_INPROC_SERVER,
+ IID_IMetaDataDispenserEx, (void **) &g_pDisp)))
+ {
+ 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);
+ }
+ LegacyActivationShim::CoUninitializeCor();
+ }
+ CoUninitialize();
+ }
+ }
+ else
+ {
+ HRESULT hr = S_OK;
+ if(g_pDisp == NULL)
+ {
+ hr = LegacyActivationShim::ClrCoCreateInstance(
+ CLSID_CorMetaDataDispenser, NULL, CLSCTX_INPROC_SERVER,
+ IID_IMetaDataDispenserEx, (void **) &g_pDisp);
+ }
+ 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,L"wb");
+ else _wfopen_s(&pfile,wzFileName,L"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;
+
+ 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);
+ }
+
+ const DWORD openFlags = ofRead | (g_fProject ? 0 : ofNoTransform);
+ if (FAILED(g_pCLRRuntimeHostInternal->GetMetaDataInternalInterface(
+ (BYTE *)g_pMetaData,
+ g_cbMetaData,
+ openFlags,
+ IID_IMDInternalImport,
+ (LPVOID *)&g_pImport)))
+ {
+ if (g_fDumpHeader)
+ DumpHeader(g_CORHeader, g_pFile);
+ printError(g_pFile, RstrUTF(IDS_E_OPENMD));
+ goto exit;
+ }
+
+ TokenSigInit(g_pImport);
+ if (FAILED(CoCreateInstance(CLSID_CorMetaDataDispenser, 0, CLSCTX_INPROC_SERVER, IID_IMetaDataDispenser, (LPVOID*)&pMetaDataDispenser)))
+ {
+ 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;
+ }
+
+
+ // 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;
+
+ 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
+
+ if (g_Mode & MODE_GUI)
+ {
+ GUIAddItemsToList();
+ }
+ else
+ {
+ // 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);
+ }
+ if(g_fShowProgressBar)
+ CreateProgressBar((LONG) (g_NumClasses + ulNumGlobalFunc));
+ }
+ ProgressStep();
+ 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;
+ }
+ ProgressStep();
+
+#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);
+ sprintf_s(szString,SZSTRING_REMAINING_SIZE(szptr),"%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(szString, 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;
+ 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);
+ }
+ }
+ 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;
+ }
+ DestroyProgressBar();
+ }
+
+exit:
+ if (pMetaDataDispenser)
+ pMetaDataDispenser->Release();
+ return fSuccess;
+}
+#ifdef _PREFAST_
+#pragma warning(pop)
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(default : 4640)
+#endif
+
+
diff --git a/src/ildasm/dasm.rc b/src/ildasm/dasm.rc
new file mode 100644
index 0000000000..a1619cff90
--- /dev/null
+++ b/src/ildasm/dasm.rc
@@ -0,0 +1,503 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include "resource.h"
+
+#ifndef FEATURE_PAL
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+#include <winresrc.h>
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+#endif // !FEATURE_PAL
+
+#define FX_VER_FILEDESCRIPTION_STR "Microsoft .NET Framework IL disassembler\0"
+
+#include <fxver.h>
+#include <fxver.rc>
+
+#include <copyrightstring.rc>
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+#ifndef FEATURE_PAL
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON2 ICON DISCARDABLE "Litening.ico"
+
+#if FX_VFT == VFT_DLL
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_FIELD BITMAP MOVEABLE PURE "field.bmp"
+IDB_METHOD BITMAP MOVEABLE PURE "method.bmp"
+IDB_STATICFIELD BITMAP MOVEABLE PURE "staticfield.bmp"
+IDB_STATICMETHOD BITMAP MOVEABLE PURE "staticmethod.bmp"
+IDB_REDARROW BITMAP MOVEABLE PURE "redarrow.bmp"
+IDB_EVENT BITMAP DISCARDABLE "event.bmp"
+IDB_PROP BITMAP DISCARDABLE "prop.bmp"
+IDB_NAMESPACE BITMAP DISCARDABLE "namespace.bmp"
+IDB_CLASS BITMAP DISCARDABLE "classa.bmp"
+IDB_CLASSENUM BITMAP DISCARDABLE "classe.bmp"
+IDB_CLASSINT BITMAP DISCARDABLE "classi.bmp"
+IDB_CLASSVAL BITMAP DISCARDABLE "classv.bmp"
+
+IDB_METHOD_GEN BITMAP MOVEABLE PURE "methodg.bmp"
+IDB_STATICMETHOD_GEN BITMAP MOVEABLE PURE "staticmethodg.bmp"
+IDB_CLASS_GEN BITMAP DISCARDABLE "classag.bmp"
+IDB_CLASSENUM_GEN BITMAP DISCARDABLE "classeg.bmp"
+IDB_CLASSINT_GEN BITMAP DISCARDABLE "classig.bmp"
+IDB_CLASSVAL_GEN BITMAP DISCARDABLE "classvg.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 157, 306
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
+CAPTION "Dump options"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ DEFPUSHBUTTON L"OK",IDOK,13,285,50,14
+ PUSHBUTTON L"Cancel",IDCANCEL,81,285,50,14
+ GROUPBOX L"Encoding",IDC_STATIC,13,3,129,28
+ CONTROL L"ANSI",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON,19,16,34,9
+ CONTROL L"UTF-8",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,55,16,34,
+ 9
+ CONTROL L"Unicode",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,91,16,
+ 40,9
+ CONTROL L"Dump Class List",IDC_CHECK19,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,14,36,106,10
+ CONTROL L"Dump Statistics",IDC_CHECK2,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,14,48,106,10
+ CONTROL L"Show Progress Bar",IDC_CHECK18,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,14,60,124,11
+ CONTROL L"Dump Header",IDC_CHECK1,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,14,73,106,10
+ CONTROL L"Dump IL Code",IDC_CHECK3,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,14,86,106,10
+ CONTROL L"Token Values",IDC_CHECK4,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,37,99,106,10
+ CONTROL L"Actual Bytes",IDC_CHECK5,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,37,110,106,10
+ CONTROL L"Line Numbers",IDC_CHECK20,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,37,120,106,10
+ CONTROL L"Source Lines",IDC_CHECK6,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,37,131,106,10
+ CONTROL L"Expand try/catch",IDC_CHECK7,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,37,142,106,10
+ CONTROL L"Dump Metainfo",IDC_CHECK8,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,14,158,106,10
+ CONTROL L"More HEX",IDC_CHECK11,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,37,174,106,10
+ CONTROL L"Raw: Counts,Sizes",IDC_CHECK12,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,37,185,106,10
+ CONTROL L"Raw: Header",IDC_CHECK10,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,37,198,106,10
+ CONTROL L"Raw: Header,Schema",IDC_CHECK14,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 37,209,106,10
+ CONTROL L"Raw: Header,Schema,Rows",IDC_CHECK15,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,37,222,106,10
+ CONTROL L"Raw: Heaps",IDC_CHECK17,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,37,233,106,10
+ CONTROL L"Unresolved Externals",IDC_CHECK13,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 37,246,106,10
+ CONTROL L"Validate",IDC_CHECK16,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,37,257,106,10
+ CONTROL L"Debug",IDC_CHECK9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 37,270,106,10
+END
+
+IDD_ABOUT DIALOGEX 0, 0, 289, 112
+STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION
+EXSTYLE WS_EX_CLIENTEDGE
+CAPTION L"About IL DASM"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ DEFPUSHBUTTON L"OK",ID_ABOUT_OK,122,83,50,14
+ ICON IDI_ICON2,IDC_STATIC,18,22,21,20,0
+ LTEXT L"Static",IDC_ABOUT_LINE1,47,22,279,11
+ LTEXT L"Static",IDC_ABOUT_LINE2,47,38,279,11
+ LTEXT L"Static",IDC_ABOUT_LINE3,47,56,279,11
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+FileAccel ACCELERATORS MOVEABLE PURE
+BEGIN
+ "O", 1, VIRTKEY, CONTROL
+ "D", 2, VIRTKEY, CONTROL
+ "T", 3, VIRTKEY, CONTROL
+ "X", 4, VIRTKEY, CONTROL
+ "M", 21, VIRTKEY, CONTROL
+ VK_F1, 31, VIRTKEY
+ VK_ESCAPE, 4, VIRTKEY
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_DIALOG1, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 150
+ TOPMARGIN, 3
+ BOTTOMMARGIN, 299
+ END
+
+ IDD_ABOUT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 232
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 105
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_FILE L"&File"
+ IDS_VIEW L"&View"
+ IDS_HELP L"&Help"
+ IDS_OPEN L"&Open\tCtrl+O"
+ IDS_DUMP L"&Dump\tCtrl+D"
+ IDS_DUMPTREE L"Dump &TreeView\tCtrl+T"
+ IDS_EXIT L"E&xit\tCtrl+X"
+ IDS_FONTS L"Set &Fonts"
+ IDS_FONT_TREE L"&Tree view"
+ IDS_FONT_DASM L"&Disassembly"
+ IDS_SORT_BY_NAME L"Sort by &name"
+ IDS_SHOW_PUB L"Hide &Public"
+ IDS_SHOW_PRIV L"Hide P&rivate"
+ IDS_SHOW_FAM L"Hide Famil&y"
+ IDS_SHOW_ASM L"Hide &Assembly"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_FIND L"&Find"
+ IDS_FINDNEXT L"Find &Next"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_MI_DEBUG L"&Debug"
+ IDS_MI_SCHEMA L"Raw:Header,Sch&ema"
+ IDS_MI_RAW L"Raw:Header,Schema,&Rows"
+ IDS_MI_HEAPS L"Raw:Hea&ps"
+ IDS_MI_VALIDATE L"&Validate"
+ IDS_SHOW_METAINFO L"&Show!\tCtrl+M"
+ IDS_ABOUT L"&About IL DASM"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_SHOW_FAA L"Hide FamAN&DAssem"
+ IDS_SHOW_FOA L"Hide Fam&ORAssem"
+ IDS_SHOW_PSCOPE L"Hide Private&Scope"
+ IDS_FULL_INFO L"Show member &types"
+ IDS_BYTES L"Show &bytes"
+ IDS_TOKENS L"Show token &values"
+ IDS_SOURCELINES L"Show source &lines"
+ IDS_QUOTEALLNAMES L"&Quote all names"
+ IDS_EXPANDTRY L"E&xpand try/catch"
+ IDS_SHOW_HEADER L"&Headers"
+ IDS_SHOW_STAT L"Stat&istics"
+ IDS_METAINFO L"&MetaInfo"
+ IDS_MI_HEADER L"Raw:&Header"
+ IDS_MI_HEX L"&More HEX"
+ IDS_MI_CSV L"Raw:&Counts,Sizes"
+ IDS_MI_UNREX L"&Unresolved ext."
+ IDS_TREEVIEWFCN L"Full &Class Names"
+ IDS_CAVERBAL L"V&erbal CA blobs"
+ IDS_DUMPRTF L"&Use RTF"
+END
+
+#endif // FX_VFT == VFT_DLL
+#endif // !FEATURE_PAL
+
+#if FX_VFT == VFT_DLL
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_USAGE_TITLE L"ILDASM command line syntax"
+ IDS_USAGE_01 L"Usage: ildasm [options] <file_name> [options]\n\n"
+ IDS_USAGE_02 L"Options for output redirection:\n"
+#ifndef FEATURE_PAL
+ IDS_USAGE_03 L" /OUT=<file name> Direct output to file rather than to GUI.\n"
+ IDS_USAGE_04 L" /TEXT Direct output to console window rather than to GUI.\n\n"
+ IDS_USAGE_04A L" /HTML Output in HTML format (valid with /OUT option only).\n"
+ IDS_USAGE_04B L" /RTF Output in rich text format (invalid with /TEXT option).\n"
+ IDS_USAGE_05 L"Options for GUI or file/console output (EXE and DLL files only):\n"
+#else
+ IDS_USAGE_03 L" /OUT=<file name> Direct output to file rather than to console.\n"
+ IDS_USAGE_04A L" /HTML Output in HTML format (valid with /OUT option only).\n"
+ IDS_USAGE_04B L" /RTF Output in rich text format (valid with /OUT option only).\n"
+ IDS_USAGE_05 L"Options for file/console output:\n"
+#endif
+#ifdef OWNER_OPTION_ENABLED
+ IDS_USAGE_06 L" /OWNER=<owner name> Set owner name to disassemble a protected PE file.\n"
+#endif
+ IDS_USAGE_07 L" /BYTES Show actual bytes (in hex) as instruction comments.\n"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_USAGE_08 L" /RAWEH Show exception handling clauses in raw form.\n"
+ IDS_USAGE_09 L" /TOKENS Show metadata tokens of classes and members.\n"
+ IDS_USAGE_10 L" /SOURCE Show original source lines as comments.\n"
+#ifdef _DEBUG
+ IDS_USAGE_10A L" /PRETTY This option is obsolete and no longer supported.\n"
+#endif
+ IDS_USAGE_11 L" /LINENUM Include references to original source lines.\n"
+ IDS_USAGE_12 L" /VISIBILITY=<vis>[+<vis>...] Only disassemble the items with specified\n"
+ IDS_USAGE_13 L" visibility. (<vis> = PUB | PRI | FAM | ASM | FAA | FOA | PSC)\n"
+ IDS_USAGE_14 L" /PUBONLY Only disassemble the public items (same as /VIS=PUB).\n"
+ IDS_USAGE_15 L" /QUOTEALLNAMES Include all names into single quotes.\n"
+ IDS_USAGE_15A L" /NOCA Suppress output of custom attributes.\n"
+ IDS_USAGE_15B L" /CAVERBAL Output CA blobs in verbal form (default - in binary form).\n"
+#ifndef FEATURE_PAL
+ IDS_USAGE_16 L" /NOBAR Suppress disassembly progress bar window pop-up.\n\n"
+ IDS_USAGE_17 L"The following options are valid for file/console output only:\n"
+ IDS_USAGE_18 L"Options for EXE and DLL files:\n"
+#endif
+ IDS_USAGE_19 L" /UTF8 Use UTF-8 encoding for output (default - ANSI).\n"
+ IDS_USAGE_20 L" /UNICODE Use UNICODE encoding for output.\n"
+ IDS_USAGE_21 L" /NOIL Suppress IL assembler code output.\n"
+ IDS_USAGE_21A L" /FORWARD Use forward class declaration.\n"
+ IDS_USAGE_21B L" /TYPELIST Output full list of types (to preserve type ordering in round-trip).\n"
+ IDS_USAGE_21C L" /PROJECT Display .NET projection view if input is a .winmd file.\n"
+ IDS_USAGE_22 L" /HEADERS Include file headers information in the output.\n"
+ IDS_USAGE_23 L" /ITEM=<class>[::<method>[(<sig>)] Disassemble the specified item only\n\n"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_USAGE_24 L" /STATS Include statistics on the image.\n"
+ IDS_USAGE_25 L" /CLASSLIST Include list of classes defined in the module.\n"
+ IDS_USAGE_26 L" /ALL Combination of /HEADER,/BYTES,/STATS,/CLASSLIST,/TOKENS\n\n"
+#ifndef FEATURE_PAL
+ IDS_USAGE_27 L"Options for EXE,DLL,OBJ and LIB files:\n"
+#endif
+ IDS_USAGE_28 L" /METADATA[=<specifier>] Show MetaData, where <specifier> is:\n"
+ IDS_USAGE_29 L" MDHEADER Show MetaData header information and sizes.\n"
+ IDS_USAGE_30 L" HEX Show more things in hex as well as words.\n"
+ IDS_USAGE_31 L" CSV Show the record counts and heap sizes.\n"
+ IDS_USAGE_32 L" UNREX Show unresolved externals.\n"
+#ifndef FEATURE_PAL
+ IDS_USAGE_33 L" DEBUG Show debug information in addition to other MetaData.\n"
+#endif
+ IDS_USAGE_34 L" SCHEMA Show the MetaData header and schema information.\n"
+ IDS_USAGE_35 L" RAW Show the raw MetaData tables.\n"
+ IDS_USAGE_36 L" HEAPS Show the raw heaps.\n"
+ IDS_USAGE_37 L" VALIDATE Validate the consistency of the metadata.\n"
+#ifndef FEATURE_PAL
+ IDS_USAGE_38 L"Options for LIB files only:\n"
+ IDS_USAGE_39 L" /OBJECTFILE=<obj_file_name> Show MetaData of a single object file in library\n"
+#endif
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_USAGE_40 L" /ALL Combination of /HEADER, /BYTES, /TOKENS\n\n"
+ IDS_USAGE_41 L"\nOption key is '-' or '/', options are recognized by first 3 characters\n\n"
+ IDS_USAGE_42 L"Example: ildasm /tok /byt myfile.exe /out=myfile.il\n\n"
+ IDS_USAGE_43 L"\n\nPress any key to close the console window..."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_E_INITLDR L"error : PELoader initialization failed"
+ IDS_E_FILEOPEN L"error : File '%s' not found or not a PE file"
+ IDS_E_NOCORHDR L"error : '%s' has no valid CLR header and cannot be disassembled"
+ IDS_E_BADCORHDR L"error : Bad CLR header, or the version of the file format is not supported"
+ IDS_E_OPENMD L"error : Failed to open meta data"
+ IDS_E_COPYRIGHT L"error : Copyrighted material - can not disassemble!"
+ IDS_E_DASMABORT L"********* DISASSEMBLY ABORTED BY THE OPERATOR **************"
+ IDS_E_DASMOK L"*********** DISASSEMBLY COMPLETE ***********************"
+ IDS_E_PARTDASM L"warning : THIS IS A PARTIAL DISASSEMBLY, NOT SUITABLE FOR RE-ASSEMBLING"
+ IDS_E_INSTRDT L"error : Failed to create instruction decoding table"
+ IDS_E_NOCOMPR L"error : Compression not supported"
+ IDS_E_CLSENUM L"error : Unable to enumerate classes"
+ IDS_E_SELFNSTD L"error : class %08X is nested in itself"
+ IDS_E_NOENCLOS L"error : class %08X is nested in missing class %08x"
+ IDS_E_INVALIDTK L"error : invalid token (%08x)"
+ IDS_E_INVALIDRECORD L"error : Invalid record (%08x)"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_E_UNEXPTYPE L"error : unexpected token type, expected %02x, got %02x"
+ IDS_E_AUTOCA L"--- The following custom attribute is added automatically, do not uncomment -------"
+ IDS_E_PARAMSEQNO L"error : parameter %d has sequence number %d (0x%X), parameter info skipped"
+ IDS_E_METHBEG L"Method begins at RVA 0x%x"
+ IDS_E_DASMERR L"%s ********* ERROR DISASSEMBLING THE METHOD IL CODE ***********"
+ IDS_E_DASMNATIVE L"Disassembly of native methods is not supported."
+ IDS_E_METHODRT L"Method provided by Runtime"
+ IDS_E_NORVA L"COULD NOT GET RVA"
+ IDS_E_MEMBRENUM L"Unable to enum members"
+ IDS_E_ODDMEMBER L"Unidentified member 0x%08X of class '%s'"
+ IDS_E_ENUMINIT L"*** EnumInit(mdtInterfaceImpl) failed"
+ IDS_E_NODATA L"No data."
+ IDS_E_VTFUTABLE L"Failed to get vtable fix-up table."
+ IDS_E_BOGUSRVA L"Bogus RVA for entry."
+ IDS_E_EATJTABLE L"Failed to get export address table jumps table."
+ IDS_E_EATJSIZE L"Error! size of ExportAddressTableJumps %d not a multiple of reserved size %d"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_E_RESFLAGS L"Error! reserved flags need to be 0."
+ IDS_E_MIHENTRY L"Failed to get vtable method data."
+ IDS_E_CODEMGRTBL L"Failed to get Code Manager table."
+ IDS_E_IMPORTDATA L"Failed to read import data."
+ IDS_E_COMIMAGE L"Not a CLR image"
+ IDS_E_MDDETAILS L"Unable to get MetaData details."
+ IDS_E_MISTART L"================================= M E T A I N F O ================================================\n"
+ IDS_E_MIEND L"================================= END OF METAINFO ================================================\n"
+ IDS_E_ONLYITEMS L"Only shown items having accessibility:"
+ IDS_E_ROGUEPTR L"ERROR: One of used pointers references undefined data (D_%8.8X)"
+ IDS_E_DECOMPRESS L"Failed to decompress method"
+ IDS_E_COMPRESSED L"Method is compressed"
+ IDS_E_CODESIZE L"Code size %d (0x%x)"
+ IDS_E_BOGUSLVSIG L"******** ERROR: Bogus local variable signature (0x%08X) ***********"
+ IDS_E_INSTRDECOD L"***Instruction decoding ERROR: %02X at position 0x%X (%d)"
+ IDS_E_INSTRTYPE L"ERROR: Unknown type 0x%X of instruction 0x%X"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_E_ARGINDEX L"%-10s %d // ERROR: invalid arg index (>=%d)"
+ IDS_E_LVINDEX L"%-10s %d // ERROR: invalid local var index (>=%d)"
+ IDS_E_SECTHEADER L"Error: no section header for RVA 0x%x, defaulting to empty string"
+ IDS_E_BADTOKENTYPE L"%-10s 0x%8.8X // ERROR: invalid token type"
+ IDS_E_MDAIMPORT L"ERROR: failed to obtain IMetaDataAssemblyImport (0x%08X)"
+ IDS_E_MDAFROMMDI L"ERROR: failed to obtain IMetaDataAssemblyImport from IMDInternalImport (0x%08X)"
+ IDS_E_MDIIMPORT L"ERROR: failed to obtain IMDInternalImport (0x%08X)"
+ IDS_E_NOMANIFEST L"Module contains no Manifest data"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_E_MULTIPLEINPUT L"MULTIPLE INPUT FILES SPECIFIED\n\n"
+ IDS_E_INVALIDOPTION L"INVALID COMMAND LINE OPTION: %s\n\n"
+ IDS_PROGRESSBOX L"ProgressBox"
+ IDS_DISASSEMBLING L"Disassembling"
+ IDS_PB_FILE L"File %s"
+ IDS_PB_FILE1 L"File ...%s"
+ IDS_PB_TOFILE L"To file %s"
+ IDS_PB_TOFILE1 L"To file ...%s"
+ IDS_PB_CLASSESDONE L"%d classes, %d done"
+ IDS_PB_GLOBALSDONE L"%d global methods, %d done"
+ IDS_PB_CANCEL L"Cancel"
+ IDS_PB_WRITINGDATA L"Writing global data"
+ IDS_W_CREATEDW32RES L"WARNING: Created Win32 resource file %s"
+ IDS_E_CORRUPTW32RES L"ERROR: Corrupt Win32 resources"
+ IDS_E_CANTOPENW32RES L"ERROR: Unable to open file %s"
+ IDS_E_CANTACCESSW32RES L"ERROR: Unable to access Win32 resources"
+ IDS_CANTVIEW_TX L"Can't view %s::%s(%s)"
+ IDS_CANTVIEW_HD L"Can't View IL"
+ IDS_ONLYPEINGUI L"ILDASM supports only PE files in graphic mode"
+ IDS_BADFILETYPE L"Invalid File Type"
+ IDS_E_CANTOPENOUT L"Unable to open '%s' for output."
+ IDS_E_CANTCREATEPROC L"Failed to CreateProcess\n\n"
+ IDS_TEXTTOOLARGEFORGUI L"Text too large for GUI. Use File/Dump menu entry to disassemble to file."
+ IDS_FILTER_IN L"PE file (*.exe,*.dll,*.mod,*.mdl,*.winmd)\t*.exe;*.dll;*.mod;*.mdl;*.winmd\tAny type (*.*)\t*.*\t\0"
+ IDS_FILTER_OUT L"IL file (*.il)\t*.il\tText file (*.txt) \t*.txt\tAny type (*.*)\t*.*\t\0"
+ IDS_FILTER_OUT2 L"Text file (*.txt) \t*.txt\tAny type (*.*)\t*.*\t\0"
+ IDS_CANNOTOPENFILE L"Cannot open file"
+ IDS_UNABLETOREGLIBS L"Unable to register libraries!"
+ IDS_ERRORREOPENINGFILE L"Error reopening the file with FileToken 0x%08X"
+ IDS_ASSEMNAMETOOLONG L"error *** Assembly name too long, truncated to 1023 characters"
+ IDS_ASMREFNAMETOOLONG L"error *** AssemblyRef name too long, truncated to 1023 characters"
+ IDS_ERRORCAPTION L"ERROR"
+ IDS_ILDASM_TITLE L"Microsoft (R) .NET Framework IL Disassembler"
+ IDS_VERSION L"Version %s"
+ IDS_W_CREATEDMRES L"WARNING: managed resource file %s created"
+ IDS_E_READINGMRES L"ERROR: reading managed resource %s at offset 0x%X"
+ IDS_RTL L"RTL_False" // change this to RTL_True on Arabic/Hebrew system
+ IDS_E_SUPPRESSED L"Protected module -- cannot disassemble"
+ IDS_LEGALCOPYRIGHT L"\251 Microsoft Corporation. All rights reserved."
+END
+#endif // FX_VFT == VFT_DLL
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef FEATURE_PAL
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
+#endif // !FEATURE_PAL
diff --git a/src/ildasm/dasm_formattype.cpp b/src/ildasm/dasm_formattype.cpp
new file mode 100644
index 0000000000..b196483fb8
--- /dev/null
+++ b/src/ildasm/dasm_formattype.cpp
@@ -0,0 +1,305 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+//
+/******************************************************************************/
+/* dasm_formatType.cpp */
+/******************************************************************************/
+#include "ildasmpch.h"
+
+#include "formattype.h"
+
+BOOL g_fQuoteAllNames = FALSE; // used by ILDASM
+BOOL g_fDumpTokens = FALSE; // used by ILDASM
+LPCSTR *rAsmRefName = NULL; // used by ILDASM
+ULONG ulNumAsmRefs = 0; // used by ILDASM
+BOOL g_fDumpRTF = FALSE; // used by ILDASM
+BOOL g_fDumpHTML = FALSE; // used by ILDASM
+BOOL g_fUseProperName = FALSE; // used by ILDASM
+DynamicArray<mdToken> *g_dups = NULL; // used by ILDASM
+DWORD g_NumDups=0; // used by ILDASM
+DynamicArray<TypeDefDescr> *g_typedefs = NULL; // used by ILDASM
+DWORD g_NumTypedefs=0; // used by ILDASM
+
+// buffers created in Init and deleted in Uninit (dasm.cpp)
+CQuickBytes * g_szBuf_KEYWORD = NULL;
+CQuickBytes * g_szBuf_COMMENT = NULL;
+CQuickBytes * g_szBuf_ERRORMSG = NULL;
+CQuickBytes * g_szBuf_ANCHORPT = NULL;
+CQuickBytes * g_szBuf_JUMPPT = NULL;
+CQuickBytes * g_szBuf_UnquotedProperName = NULL;
+CQuickBytes * g_szBuf_ProperName = NULL;
+
+// Protection against null names, used by ILDASM
+const char * const szStdNamePrefix[] = {"MO","TR","TD","","FD","","MD","","PA","II","MR","","CA","","PE","","","SG","","","EV",
+"","","PR","","","MOR","TS","","","","","AS","","","AR","","","FL","ET","MAR"};
+
+//-------------------------------------------------------------------------------
+// Reference analysis (ILDASM)
+DynamicArray<TokPair> *g_refs = NULL;
+DWORD g_NumRefs=0;
+mdToken g_tkRefUser=0; // for PrettyPrintSig
+
+mdToken g_tkVarOwner = 0;
+mdToken g_tkMVarOwner = 0;
+
+// Include the shared formatting routines
+#include "formattype.cpp"
+
+// Special dumping routines for keywords, comments and errors, used by ILDASM
+
+const char* KEYWORD(__in_opt __nullterminated const char* szOrig)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ }
+ CONTRACTL_END;
+
+ const char* szPrefix = "";
+ const char* szPostfix = "";
+ if(g_fDumpHTML)
+ {
+ szPrefix = "<B><FONT COLOR=NAVY>";
+ szPostfix = "</FONT></B>";
+ }
+ else if(g_fDumpRTF)
+ {
+ szPrefix = "\\b\\cf1 ";
+ szPostfix = "\\cf0\\b0 ";
+ }
+ if(szOrig == NULL) return szPrefix;
+ if(szOrig == (char*)-1) return szPostfix;
+ if(*szPrefix)
+ {
+ g_szBuf_KEYWORD->Shrink(0);
+ appendStr(g_szBuf_KEYWORD,szPrefix);
+ appendStr(g_szBuf_KEYWORD,szOrig);
+ appendStr(g_szBuf_KEYWORD,szPostfix);
+ return asString(g_szBuf_KEYWORD);
+ }
+ else
+ return szOrig;
+}
+const char* COMMENT(__in_opt __nullterminated const char* szOrig)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ }
+ CONTRACTL_END;
+
+ const char* szPrefix = "";
+ const char* szPostfix = "";
+ if(g_fDumpHTML)
+ {
+ szPrefix = "<I><FONT COLOR=GREEN>";
+ szPostfix = "</FONT></I>";
+ }
+ else if(g_fDumpRTF)
+ {
+ szPrefix = "\\cf2\\i ";
+ szPostfix = "\\i0\\cf0 ";
+ }
+ else
+ {
+ szPrefix = "";
+ szPostfix = "";
+ }
+ if(szOrig == NULL) return szPrefix;
+ if(szOrig == (char*)-1) return szPostfix;
+ if(*szPrefix)
+ {
+ g_szBuf_COMMENT->Shrink(0);
+ appendStr(g_szBuf_COMMENT,szPrefix);
+ appendStr(g_szBuf_COMMENT,szOrig);
+ appendStr(g_szBuf_COMMENT,szPostfix);
+ return asString(g_szBuf_COMMENT);
+ }
+ else
+ return szOrig;
+}
+const char* ERRORMSG(__in_opt __nullterminated const char* szOrig)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ }
+ CONTRACTL_END;
+
+ char* szPrefix = "";
+ char* szPostfix = "";
+ if(g_fDumpHTML)
+ {
+ szPrefix = "<I><B><FONT COLOR=RED>";
+ szPostfix = "</FONT></B></I>";
+ }
+ else if(g_fDumpRTF)
+ {
+ szPrefix = "\\cf3\\i\\b ";
+ szPostfix = "\\cf0\\b0\\i0 ";
+ }
+ if(szOrig == NULL) return szPrefix;
+ if(szOrig == (char*)-1) return szPostfix;
+ if(*szPrefix)
+ {
+ g_szBuf_ERRORMSG->Shrink(0);
+ appendStr(g_szBuf_ERRORMSG,szPrefix);
+ appendStr(g_szBuf_ERRORMSG,szOrig);
+ appendStr(g_szBuf_ERRORMSG,szPostfix);
+ return asString(g_szBuf_ERRORMSG);
+ }
+ else
+ return szOrig;
+}
+
+const char* ANCHORPT(__in __nullterminated const char* szOrig, mdToken tk)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ }
+ CONTRACTL_END;
+
+ if(g_fDumpHTML)
+ {
+ char szPrefix[64];
+ const char* szPostfix = "</A>";
+ sprintf_s(szPrefix, COUNTOF(szPrefix), "<A NAME=A%08X>",tk);
+ g_szBuf_ANCHORPT->Shrink(0);
+ appendStr(g_szBuf_ANCHORPT,szPrefix);
+ appendStr(g_szBuf_ANCHORPT,szOrig);
+ appendStr(g_szBuf_ANCHORPT,szPostfix);
+ return asString(g_szBuf_ANCHORPT);
+ }
+ else
+ return szOrig;
+}
+const char* JUMPPT(__in __nullterminated const char* szOrig, mdToken tk)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ }
+ CONTRACTL_END;
+
+ if(g_fDumpHTML)
+ {
+ char szPrefix[64];
+ const char* szPostfix = "</A>";
+ sprintf_s(szPrefix,COUNTOF(szPrefix), "<A HREF=#A%08X>",tk);
+ g_szBuf_JUMPPT->Shrink(0);
+ appendStr(g_szBuf_JUMPPT,szPrefix);
+ appendStr(g_szBuf_JUMPPT,szOrig);
+ appendStr(g_szBuf_JUMPPT,szPostfix);
+ return asString(g_szBuf_JUMPPT);
+ }
+ else
+ return szOrig;
+}
+const char* SCOPE(void) { return g_fDumpRTF ? "\\{" : "{"; }
+const char* UNSCOPE(void) { return g_fDumpRTF ? "\\}" : "}"; }
+const char* LTN(void) { return g_fDumpHTML ? "&lt;" : "<"; }
+const char* GTN(void) { return g_fDumpHTML ? "&gt;" : ">"; }
+const char* AMP(void) { return g_fDumpHTML ? "&amp;" : "&"; }
+
+
+
+/******************************************************************************/
+// Function: convert spec.symbols to esc sequences and single-quote if necessary
+const char* UnquotedProperName(__in __nullterminated const char* name, unsigned len/*=(unsigned)-1*/)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ }
+ CONTRACTL_END;
+
+ CQuickBytes *buff = g_szBuf_UnquotedProperName;
+ _ASSERTE (buff);
+ if(g_fUseProperName)
+ {
+ const char *pcn,*pcend,*ret;
+ if (name != NULL)
+ {
+ if (*name != 0)
+ {
+ pcn = name;
+ if (len == (unsigned)(-1))
+ len = (unsigned)strlen(name);
+ pcend = pcn + len;
+ buff->Shrink(0);
+ for (pcn = name; pcn < pcend; pcn++)
+ {
+ switch(*pcn)
+ {
+ case '\t': appendChar(buff,'\\'); appendChar(buff,'t'); break;
+ case '\n': appendChar(buff,'\\'); appendChar(buff,'n'); break;
+ case '\b': appendChar(buff,'\\'); appendChar(buff,'b'); break;
+ case '\r': appendChar(buff,'\\'); appendChar(buff,'r'); break;
+ case '\f': appendChar(buff,'\\'); appendChar(buff,'f'); break;
+ case '\v': appendChar(buff,'\\'); appendChar(buff,'v'); break;
+ case '\a': appendChar(buff,'\\'); appendChar(buff,'a'); break;
+ case '\\': appendChar(buff,'\\'); appendChar(buff,'\\'); break;
+ case '\'': appendChar(buff,'\\'); appendChar(buff,'\''); break;
+ case '\"': appendChar(buff,'\\'); appendChar(buff,'\"'); break;
+ case '{': appendStr(buff,SCOPE()); break;
+ case '}': appendStr(buff,UNSCOPE()); break;
+ case '<': appendStr(buff,LTN()); break;
+ case '>': appendStr(buff,GTN()); break;
+ case '&': appendStr(buff,AMP()); break;
+ default: appendChar(buff,*pcn);
+ }
+ }
+ ret = asString(buff);
+ }
+ else ret = "";
+ }
+ else ret = NULL;
+ return ret;
+ }
+ return name;
+}
+/******************************************************************************/
+// Function: convert spec.symbols to esc sequences and single-quote if necessary
+const char* ProperName(__in __nullterminated const char* name, bool isLocalName)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ }
+ CONTRACTL_END;
+
+ CQuickBytes *buff = g_szBuf_ProperName;
+ _ASSERTE (buff);
+ if(g_fUseProperName)
+ {
+ char *ret;
+ BOOL fQuoted;
+ if(name)
+ {
+ if(*name)
+ {
+ buff->Shrink(0);
+ fQuoted = isLocalName ? IsLocalToQuote(name) : IsNameToQuote(name);
+ if(fQuoted) appendChar(buff,'\'');
+ appendStr(buff,UnquotedProperName(name));
+ if(fQuoted) appendChar(buff,'\'');
+ ret = asString(buff);
+ }
+ else ret = "";
+ }
+ else ret = NULL;
+ return ret;
+ }
+ return name;
+}
diff --git a/src/ildasm/dasm_mi.cpp b/src/ildasm/dasm_mi.cpp
new file mode 100644
index 0000000000..a2ae27a580
--- /dev/null
+++ b/src/ildasm/dasm_mi.cpp
@@ -0,0 +1,9 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include "ildasmpch.h"
+
+#include "../tools/metainfo/mdinfo.cpp"
+#include "../tools/metainfo/mdobj.cpp"
diff --git a/src/ildasm/dasm_pr.cpp b/src/ildasm/dasm_pr.cpp
new file mode 100644
index 0000000000..23f9ae1d3f
--- /dev/null
+++ b/src/ildasm/dasm_pr.cpp
@@ -0,0 +1,274 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include "ildasmpch.h"
+
+#include "resource.h"
+#include "formattype.h"
+
+WCHAR* RstrW(unsigned id);
+
+extern HINSTANCE g_hInstance;
+extern HINSTANCE g_hResources;
+extern DWORD g_NumClasses;
+extern char g_szInputFile[]; // in UTF-8
+extern char g_szOutputFile[]; // in UTF-8
+
+#define IDC_CANCEL 101
+
+HWND g_hwndProgress = NULL;
+HWND g_hwndProgBox = NULL;
+HWND g_hwndFromFile = NULL;
+HWND g_hwndToFile = NULL;
+HWND g_hwndTally = NULL;
+HWND g_hwndCancel = NULL;
+HANDLE g_hThreadReady = NULL; // event
+
+BOOL g_fInitCommonControls = TRUE;
+BOOL g_fRegisterClass = TRUE;
+ULONG g_ulCount, g_ulRange;
+RECT rcClient; // client area of parent window
+
+WCHAR* UtfToUnicode(__in __nullterminated const char* sz); // defined in dis.cpp
+
+LRESULT CALLBACK ProgBoxWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDC_CANCEL:
+ g_hwndProgress = NULL;
+ g_hwndProgBox = NULL;
+ g_hwndFromFile = NULL;
+ g_hwndToFile = NULL;
+ g_hwndTally = NULL;
+ g_hwndCancel = NULL;
+ DestroyWindow (hwnd);
+ break;
+ }
+ break;
+
+
+ case WM_CLOSE:
+ g_hwndProgress = NULL;
+ g_hwndProgBox = NULL;
+ g_hwndFromFile = NULL;
+ g_hwndToFile = NULL;
+ g_hwndTally = NULL;
+ g_hwndCancel = NULL;
+ //break;
+ default:
+ return WszDefWindowProc(hwnd, uMsg, wParam, lParam);
+ }
+ return 0;
+}
+DWORD WINAPI ProgressMainLoop(LPVOID pv)
+{
+ MSG msg;
+ DWORD cyVScroll;
+ HFONT hFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT); //(ANSI_FIXED_FONT);
+ WCHAR wzStr[1024];
+
+ if(g_fInitCommonControls)
+ {
+ InitCommonControls();
+ g_fInitCommonControls = FALSE;
+ }
+ g_ulCount = 0;
+ if(g_fRegisterClass)
+ {
+ _ASSERTE(g_hResources != NULL);
+ WNDCLASSW wndClass;
+
+ wndClass.style = CS_HREDRAW|CS_VREDRAW|CS_NOCLOSE;
+ wndClass.lpfnWndProc = ProgBoxWndProc;
+ wndClass.cbClsExtra = 0;
+ wndClass.cbWndExtra = 0;
+ wndClass.hInstance = g_hInstance;
+ wndClass.hIcon = WszLoadIcon(g_hResources,MAKEINTRESOURCE(IDI_ICON2));
+ wndClass.hCursor = NULL;
+ wndClass.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
+ wndClass.lpszMenuName = NULL;
+ wndClass.lpszClassName = L"ProgressBox";
+
+ if (WszRegisterClass(&wndClass) == 0) return 0;
+
+ g_fRegisterClass = FALSE;
+ }
+ cyVScroll = GetSystemMetrics(SM_CYVSCROLL);
+ if(g_hwndProgBox = WszCreateWindowEx (0,
+ RstrW(IDS_PROGRESSBOX), //"ProgressBox",
+ RstrW(IDS_DISASSEMBLING), //"Disassembling",
+ WS_VISIBLE | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_CLIPCHILDREN,
+ 400, 200, 400, 8*cyVScroll,
+ HWND_DESKTOP,
+ (HMENU)0,
+ g_hInstance,
+ NULL))
+ {
+ GetClientRect(g_hwndProgBox, &rcClient);
+
+ if(g_hwndFromFile = WszCreateWindowEx (0,
+ L"STATIC",
+ L"",
+ WS_CHILD|WS_VISIBLE|SS_CENTER,
+ rcClient.left, rcClient.bottom-6*cyVScroll,rcClient.right, cyVScroll,
+ g_hwndProgBox,
+ (HMENU)0,
+ g_hInstance,
+ NULL))
+ {
+ SendMessageA(g_hwndFromFile,WM_SETFONT,(LPARAM)hFont,FALSE);
+ WCHAR* wzFileName = UtfToUnicode(g_szInputFile);
+ if(wcslen(wzFileName) <= 60) swprintf_s(wzStr,1024,RstrW(IDS_PB_FILE) /*"File %s"*/,wzFileName);
+ else
+ {
+ WCHAR * p=wzFileName;
+ while(p = wcschr(p,L'\\'))
+ {
+ if(wcslen(p) <= 60) break;
+ p++;
+ }
+ if(p == NULL) p = &wzFileName[wcslen(wzFileName)-50];
+ swprintf_s(wzStr,1024,RstrW(IDS_PB_FILE1) /*"File ...%s"*/,p);
+ }
+ WszSendMessage(g_hwndFromFile, WM_SETTEXT,0,(LPARAM)wzStr);
+ }
+ if(g_hwndToFile = WszCreateWindowEx (0,
+ L"STATIC",
+ L"",
+ WS_CHILD|WS_VISIBLE|SS_CENTER,
+ rcClient.left, rcClient.bottom-5*cyVScroll,rcClient.right, cyVScroll,
+ g_hwndProgBox,
+ (HMENU)0,
+ g_hInstance,
+ NULL))
+ {
+ SendMessageA(g_hwndToFile,WM_SETFONT,(LPARAM)hFont,FALSE);
+ WCHAR* wzFileName = UtfToUnicode(g_szOutputFile);
+ if(wcslen(wzFileName) <= 60) swprintf_s(wzStr,1024,RstrW(IDS_PB_TOFILE) /*"To file %s"*/,wzFileName);
+ else
+ {
+ WCHAR * p=wzFileName;
+ while(p = wcschr(p,L'\\'))
+ {
+ if(wcslen(p) <= 60) break;
+ p++;
+ }
+ if(p == NULL) p = &wzFileName[wcslen(wzFileName)-50];
+ swprintf_s(wzStr,1024,RstrW(IDS_PB_TOFILE1) /*"To file ...%s"*/,p);
+ }
+ WszSendMessage(g_hwndToFile, WM_SETTEXT,0,(LPARAM)wzStr);
+ }
+ if(g_hwndTally = WszCreateWindowEx (0,
+ L"STATIC",
+ L"",
+ WS_CHILD|WS_VISIBLE|SS_CENTER,
+ rcClient.left, rcClient.bottom-4*cyVScroll,rcClient.right, cyVScroll,
+ g_hwndProgBox,
+ (HMENU)0,
+ g_hInstance,
+ NULL))
+ {
+ SendMessageA(g_hwndTally,WM_SETFONT,(LPARAM)hFont,FALSE);
+ if(g_ulCount <= g_NumClasses) swprintf_s(wzStr,1024,RstrW(IDS_PB_CLASSESDONE) /*"%d classes, %d done"*/,g_NumClasses,g_ulCount);
+ else swprintf_s(wzStr,1024,RstrW(IDS_PB_GLOBALSDONE) /*"%d global methods, %d done"*/,g_ulRange-g_NumClasses,g_ulCount-g_NumClasses);
+ WszSendMessage(g_hwndTally, WM_SETTEXT,0,(LPARAM)wzStr);
+ }
+ if(g_hwndProgress = WszCreateWindowEx (0,
+ PROGRESS_CLASS,
+ L"",
+ WS_CHILD|WS_VISIBLE|SS_CENTER, // SS_CENTER gives smooth progress and solid bar
+ rcClient.left, rcClient.bottom-3*cyVScroll,rcClient.right, cyVScroll,
+ g_hwndProgBox,
+ (HMENU)0,
+ g_hInstance,
+ NULL))
+ {
+ // Set the range for the progress bar.
+ SendMessageA (g_hwndProgress, PBM_SETRANGE, 0L, MAKELPARAM(0, g_ulRange));
+ // Set the step.
+ SendMessageA (g_hwndProgress, PBM_SETSTEP, (WPARAM)1, 0L);
+ }
+ if(g_hwndCancel = WszCreateWindowEx (0,
+ L"BUTTON",
+ RstrW(IDS_PB_CANCEL), //"Cancel",
+ WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON|BS_TEXT,
+ rcClient.left+150, rcClient.bottom-3*cyVScroll/2,rcClient.right-300, 4*cyVScroll/3,
+ g_hwndProgBox,
+ (HMENU)IDC_CANCEL,
+ g_hInstance,
+ NULL))
+ {
+ SendMessageA(g_hwndCancel,WM_SETFONT,(LPARAM)hFont,FALSE);
+ }
+ }
+ SetEvent(g_hThreadReady);
+ while (WszGetMessage(&msg, NULL, 0, 0))
+ {
+ TranslateMessage(&msg);
+ WszDispatchMessage(&msg);
+ }
+ return 0;
+}
+
+void CreateProgressBar(LONG lRange)
+{
+ DWORD dwThreadID;
+ g_ulCount = 0;
+ if((g_ulRange = (ULONG)lRange)==0) return;
+
+ g_hThreadReady = WszCreateEvent(NULL,FALSE,FALSE,NULL);
+ if (g_hThreadReady != NULL)
+ {
+ // Thread is never aborted, it always exits by itself
+ HANDLE hThread = CreateThread(NULL,0,ProgressMainLoop,NULL,0,&dwThreadID);
+ if (hThread != NULL)
+ {
+ CloseHandle(hThread);
+ WaitForSingleObject(g_hThreadReady,INFINITE);
+ }
+ CloseHandle(g_hThreadReady);
+ }
+}
+
+BOOL ProgressStep()
+{
+ if(g_hwndProgBox)
+ {
+ WCHAR wzStr[1024];
+ if(g_hwndTally)
+ {
+ if(g_ulCount <= g_NumClasses)
+ swprintf_s(wzStr,1024,RstrW(IDS_PB_CLASSESDONE) /*"%d classes, %d done"*/,g_NumClasses,g_ulCount);
+ else if(g_ulCount <= g_ulRange)
+ swprintf_s(wzStr,1024,RstrW(IDS_PB_GLOBALSDONE) /*"%d global methods, %d done"*/,g_ulRange-g_NumClasses,g_ulCount-g_NumClasses);
+ else
+ wcscpy_s(wzStr,1024,RstrW(IDS_PB_WRITINGDATA)); //"Writing global data");
+ wzStr[1023]=0;
+ WszSendMessage(g_hwndTally, WM_SETTEXT,0,(LPARAM)wzStr);
+ }
+
+ if(g_hwndProgress && g_ulCount && (g_ulCount <= g_ulRange))
+ WszSendMessage (g_hwndProgress, PBM_STEPIT, 0L, 0L);
+ g_ulCount++;
+ }
+ else if(g_ulCount) return FALSE; // disassembly started and was aborted
+ return TRUE;
+}
+
+void DestroyProgressBar()
+{
+ if(g_hwndProgBox) WszSendMessage (g_hwndProgBox,WM_COMMAND,IDC_CANCEL,0);
+ g_hwndProgress = NULL;
+ g_hwndProgBox = NULL;
+ g_hwndFromFile = NULL;
+ g_hwndToFile = NULL;
+ g_hwndTally = NULL;
+ g_hwndCancel = NULL;
+ g_ulCount = 0;
+}
diff --git a/src/ildasm/dasm_sz.cpp b/src/ildasm/dasm_sz.cpp
new file mode 100644
index 0000000000..036c521ca9
--- /dev/null
+++ b/src/ildasm/dasm_sz.cpp
@@ -0,0 +1,230 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include "ildasmpch.h"
+
+#include <metadata.h>
+#include <utilcode.h>
+#include "debugmacros.h"
+#include "dasm_sz.h"
+#include "ceeload.h"
+
+extern PELoader *g_pPELoader;
+
+unsigned SizeOfValueType(mdToken tk, IMDInternalImport* pImport)
+{
+ unsigned ret = 0xFFFFFFFF;
+ if((TypeFromToken(tk)==mdtTypeDef)&&RidFromToken(tk)&&pImport)
+ {
+ DWORD dwAttrs;
+ mdToken tkExtends;
+ if (FAILED(pImport->GetTypeDefProps(tk, &dwAttrs, &tkExtends)))
+ {
+ return ret;
+ }
+ if(!(IsTdInterface(dwAttrs)||IsTdAbstract(dwAttrs)||IsTdImport(dwAttrs)))
+ {
+ mdToken tkField;
+ DWORD dwFieldAttrs;
+ unsigned uFieldSize;
+ ULONG ulPack=0,
+ ulSize = 0,
+ ulInstFieldSize = 0;
+
+ if (FAILED(pImport->GetClassPackSize(tk,&ulPack))) ulPack = 0;
+ if (FAILED(pImport->GetClassTotalSize(tk,&ulSize))) ulSize = 0;
+
+ if (IsTdExplicitLayout(dwAttrs))
+ {
+ MD_CLASS_LAYOUT hLayout;
+ if (SUCCEEDED(pImport->GetClassLayoutInit(tk,&hLayout)))
+ {
+ ULONG ulOffset;
+ while (SUCCEEDED(pImport->GetClassLayoutNext(&hLayout,&tkField,&ulOffset)) && RidFromToken(tkField))
+ {
+ if (FAILED(pImport->GetFieldDefProps(tkField, &dwFieldAttrs)))
+ {
+ break;
+ }
+ if (!(IsFdStatic(dwFieldAttrs)||IsFdLiteral(dwFieldAttrs)))
+ {
+ uFieldSize = SizeOfField(tkField,pImport);
+ if (uFieldSize == 0xFFFFFFFF) return uFieldSize;
+ uFieldSize += ulOffset;
+ if (uFieldSize > ulInstFieldSize) ulInstFieldSize = uFieldSize;
+ }
+ }
+ }
+ }
+ else
+ {
+ HENUMInternal hEnumField;
+ unsigned cFieldsMax = 0;
+ if (SUCCEEDED(pImport->EnumInit(mdtFieldDef, tk, &hEnumField)))
+ {
+ if ((cFieldsMax = pImport->EnumGetCount(&hEnumField)) != 0)
+ {
+ while (pImport->EnumNext(&hEnumField, &tkField) && RidFromToken(tkField))
+ {
+ if (FAILED(pImport->GetFieldDefProps(tkField, &dwFieldAttrs)))
+ {
+ break;
+ }
+ if (!IsFdStatic(dwFieldAttrs) && !IsFdLiteral(dwFieldAttrs))
+ {
+ uFieldSize = SizeOfField(tkField,pImport);
+ if (uFieldSize == 0xFFFFFFFF) return uFieldSize;
+ if (ulPack > 1)
+ {
+ ULONG ulDelta = ulInstFieldSize % ulPack;
+ if (ulDelta != 0) ulInstFieldSize += ulPack - ulDelta;
+ }
+ ulInstFieldSize += uFieldSize;
+ }
+ }
+ }
+ pImport->EnumClose(&hEnumField);
+ }
+ }
+ ret = (ulInstFieldSize > ulSize) ? ulInstFieldSize : ulSize;
+ if(ret == 0) ret = 1; // zero-sized value types automatically get 1 byte
+ }
+ }
+ return ret;
+}
+
+unsigned SizeOfField(mdToken tk, IMDInternalImport* pImport)
+{
+ unsigned ret = 0xFFFFFFFF;
+ if((TypeFromToken(tk) == mdtFieldDef) && RidFromToken(tk) && pImport)
+ {
+ PCCOR_SIGNATURE pSig;
+ ULONG cSig;
+ if (FAILED(pImport->GetSigOfFieldDef(tk, &cSig, &pSig)))
+ {
+ return ret;
+ }
+ ret = SizeOfField(&pSig,cSig,pImport);
+ }
+ return ret;
+}
+
+unsigned SizeOfField(PCCOR_SIGNATURE *ppSig, ULONG cSig, IMDInternalImport* pImport)
+{
+ unsigned ret = 0xFFFFFFFF;
+ if(ppSig && *ppSig && cSig && pImport)
+ {
+ unsigned callConv = CorSigUncompressData(*ppSig);
+ if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD))
+ {
+ mdToken tk;
+ int typ;
+ BOOL Reiterate;
+ unsigned uElementNumber = 1;
+ PCCOR_SIGNATURE pSigStart = *ppSig;
+ PCCOR_SIGNATURE pSigEnd = *ppSig+cSig;
+
+ // Size of the pointer depends on bitness of the assembly
+ unsigned nSizeOfPointer = g_pPELoader->IsPE32() ? 4 : 8;
+
+ do {
+ Reiterate = FALSE;
+ switch(typ = *(*ppSig)++) {
+ case ELEMENT_TYPE_VOID :
+ return 0;
+
+ case ELEMENT_TYPE_I1 :
+ case ELEMENT_TYPE_U1 :
+ case ELEMENT_TYPE_BOOLEAN :
+ return uElementNumber;
+
+ case ELEMENT_TYPE_CHAR :
+ case ELEMENT_TYPE_I2 :
+ case ELEMENT_TYPE_U2 :
+ return (uElementNumber << 1);
+
+ case ELEMENT_TYPE_I4 :
+ case ELEMENT_TYPE_U4 :
+ case ELEMENT_TYPE_R4 :
+ return (uElementNumber << 2);
+
+ case ELEMENT_TYPE_I8 :
+ case ELEMENT_TYPE_U8 :
+ case ELEMENT_TYPE_R8 :
+ return (uElementNumber << 3);
+
+ case ELEMENT_TYPE_OBJECT :
+ case ELEMENT_TYPE_STRING :
+ case ELEMENT_TYPE_FNPTR :
+ case ELEMENT_TYPE_CLASS :
+ case ELEMENT_TYPE_PTR :
+ case ELEMENT_TYPE_BYREF :
+ //case ELEMENT_TYPE_VAR :
+ case ELEMENT_TYPE_U :
+ case ELEMENT_TYPE_I :
+ return (uElementNumber * nSizeOfPointer);
+
+ case ELEMENT_TYPE_TYPEDBYREF : // pair of ptrs
+ return (uElementNumber * nSizeOfPointer * 2);
+
+ case ELEMENT_TYPE_VALUETYPE :
+ *ppSig += CorSigUncompressToken(*ppSig, &tk);
+ ret = SizeOfValueType(tk,pImport);
+ if(ret != 0xFFFFFFFF) ret *= uElementNumber;
+ return ret;
+
+ // Modifiers or depedant types
+
+ case ELEMENT_TYPE_ARRAY :
+ ret = SizeOfField(ppSig, cSig-(unsigned)((*ppSig)-pSigStart), pImport);
+ if(ret != 0xFFFFFFFF)
+ {
+ unsigned rank = CorSigUncompressData(*ppSig);
+ if (rank == 0) ret = 0xFFFFFFFF;
+ else
+ {
+ int* lowerBounds = new (nothrow) int[2*rank];
+ int* sizes = &lowerBounds[rank];
+ memset(lowerBounds, 0, sizeof(int)*2*rank);
+
+ unsigned numSizes = CorSigUncompressData(*ppSig);
+ _ASSERTE(numSizes <= rank);
+ unsigned i;
+ for(i =0; i < numSizes; i++)
+ sizes[i] = CorSigUncompressData(*ppSig);
+
+ unsigned numLowBounds = CorSigUncompressData(*ppSig);
+ _ASSERTE(numLowBounds <= rank);
+ for(i = 0; i < numLowBounds; i++)
+ *ppSig+=CorSigUncompressSignedInt(*ppSig,&lowerBounds[i]);
+
+ for(i = 0; i < numSizes; i++)
+ {
+ if (sizes[i]) uElementNumber *= sizes[i];
+ }
+ ret *= uElementNumber;
+ delete[] lowerBounds;
+ }
+ }
+ return ret;
+
+ case ELEMENT_TYPE_CMOD_OPT :
+ case ELEMENT_TYPE_CMOD_REQD :
+ *ppSig += CorSigUncompressToken(*ppSig, &tk);
+ case ELEMENT_TYPE_PINNED :
+ case ELEMENT_TYPE_SZARRAY : // uElementNumber doesn't change
+ if(*ppSig < pSigEnd) Reiterate = TRUE;
+ break;
+
+ default:
+ case ELEMENT_TYPE_SENTINEL :
+ case ELEMENT_TYPE_END :
+ break;
+ } // end switch
+ } while(Reiterate);
+ } // end if(CALLCONV_FIELD)
+ } // end if(signature && import)
+ return ret;
+}
diff --git a/src/ildasm/dasm_sz.h b/src/ildasm/dasm_sz.h
new file mode 100644
index 0000000000..d1682bf225
--- /dev/null
+++ b/src/ildasm/dasm_sz.h
@@ -0,0 +1,15 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#ifndef _DASM_SZ_H_
+#define _DASM_SZ_H_
+
+unsigned SizeOfValueType(mdToken tk, IMDInternalImport* pImport);
+
+unsigned SizeOfField(mdToken tk, IMDInternalImport* pImport);
+
+unsigned SizeOfField(PCCOR_SIGNATURE *ppSig, ULONG cSig, IMDInternalImport* pImport);
+
+#endif
diff --git a/src/ildasm/dasmenum.hpp b/src/ildasm/dasmenum.hpp
new file mode 100644
index 0000000000..f636fe47ca
--- /dev/null
+++ b/src/ildasm/dasmenum.hpp
@@ -0,0 +1,32 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include "openum.h"
+
+typedef struct
+{
+ const char * pszName;
+
+ OPCODE Ref; // reference codes
+
+ BYTE Type; // Inline0 etc.
+
+ BYTE Len; // std mapping
+ BYTE Std1;
+ BYTE Std2;
+} opcodeinfo_t;
+
+#ifdef DECLARE_DATA
+opcodeinfo_t OpcodeInfo[] =
+{
+#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) { s,c,args,l,s1,s2 },
+#include "opcode.def"
+#undef OPDEF
+};
+#else
+extern opcodeinfo_t OpcodeInfo[];
+#endif
+
+
diff --git a/src/ildasm/dasmgui.h b/src/ildasm/dasmgui.h
new file mode 100644
index 0000000000..990cec0433
--- /dev/null
+++ b/src/ildasm/dasmgui.h
@@ -0,0 +1,16 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+BOOL CreateGUI();
+void GUISetModule(__in __nullterminated const char *pszModule);
+void GUIMainLoop();
+void GUIAddOpcode(__inout_opt __nullterminated const char *szString, __in_opt void *GUICookie);
+BOOL GUIAddItemsToList();
+void GUIAddOpcode(__inout __nullterminated const char *szString);
+void DestroyGUI();
+UINT GetDasmMBRTLStyle();
+
+BOOL DisassembleMemberByName(__in __nullterminated const char *pszClassName, __in __nullterminated const char *pszMemberName, __in __nullterminated const char *pszSig);
+BOOL IsGuiILOnly();
diff --git a/src/ildasm/dasmhlp.hhc b/src/ildasm/dasmhlp.hhc
new file mode 100644
index 0000000000..dcedac2abb
--- /dev/null
+++ b/src/ildasm/dasmhlp.hhc
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<HTML>
+<HEAD>
+<meta name="GENERATOR" content="Microsoft&reg; HTML Help Workshop 4.1">
+<!-- Sitemap 1.0 -->
+</HEAD><BODY>
+<OBJECT type="text/site properties">
+ <param name="Window Styles" value="0x800021">
+</OBJECT>
+<UL>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="Menu Options">
+ <param name="Local" value="html\menu_options.htm">
+ <param name="URL" value="html\menu_options.htm">
+ </OBJECT>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="Tree View Icons">
+ <param name="Local" value="html\tree_view_icons.htm">
+ <param name="URL" value="html\tree_view_icons.htm">
+ </OBJECT>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="Clicking on Tree View Items">
+ <param name="Local" value="html\clicking.htm">
+ <param name="URL" value="html\clicking.htm">
+ </OBJECT>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="Keyboard Commands">
+ <param name="Local" value="html\keyboard.htm">
+ <param name="URL" value="html\keyboard.htm">
+ </OBJECT>
+</UL>
+</BODY></HTML>
diff --git a/src/ildasm/dirs.proj b/src/ildasm/dirs.proj
new file mode 100644
index 0000000000..86d561e3f8
--- /dev/null
+++ b/src/ildasm/dirs.proj
@@ -0,0 +1,15 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.props" />
+ <!--Leaf project Properties-->
+ <!--The following projects will build during PHASE 1-->
+ <PropertyGroup>
+ <BuildInPhaseDefault>false</BuildInPhaseDefault>
+ <BuildInPhase1>true</BuildInPhase1>
+ </PropertyGroup>
+ <ItemGroup Condition="'$(BuildExePhase)' == '1'">
+ <ProjectFile Include="exe\ildasm.nativeproj" />
+ <ProjectFile Include="rcdll\ildasmrc.nativeproj" />
+ </ItemGroup>
+ <!--Import the targets-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\tools\Microsoft.DevDiv.Traversal.targets" />
+</Project>
diff --git a/src/ildasm/dis.cpp b/src/ildasm/dis.cpp
new file mode 100644
index 0000000000..4356b6f40a
--- /dev/null
+++ b/src/ildasm/dis.cpp
@@ -0,0 +1,2787 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+//
+// Disassembler
+//
+#include "ildasmpch.h"
+
+#include "debugmacros.h"
+#include "corpriv.h"
+#include "dasmenum.hpp"
+#include "dasmgui.h"
+#include "formattype.h"
+#include "dis.h"
+#include "resource.h"
+#include "ilformatter.h"
+#include "outstring.h"
+
+#include "ceeload.h"
+#include "dynamicarray.h"
+extern PELoader * g_pPELoader;
+#include <corsym.h>
+
+extern ISymUnmanagedReader* g_pSymReader;
+extern BOOL g_fDumpAsmCode;
+extern char g_szAsmCodeIndent[];
+extern BOOL g_fShowBytes;
+extern BOOL g_fShowSource;
+extern BOOL g_fInsertSourceLines;
+extern BOOL g_fTryInCode;
+extern BOOL g_fQuoteAllNames;
+extern BOOL g_fDumpTokens;
+extern DynamicArray<__int32> *g_pPtrTags; //to keep track of all "ldptr"
+extern DynamicArray<DWORD> *g_pPtrSize; //to keep track of all "ldptr"
+extern int g_iPtrCount;
+static BOOL ConvToLiteral(__inout __nullterminated char* retBuff, const WCHAR* str, int cbStr);
+extern DWORD g_Mode;
+extern unsigned g_uConsoleCP;
+
+#define PADDING 28
+
+extern BOOL g_fThisIsInstanceMethod;
+extern unsigned g_uCodePage;
+extern HANDLE hConsoleOut;
+extern HANDLE hConsoleErr;
+// globals for source file info
+ULONG_PTR ulWasFileToken = 0xFFFFFFFF;
+GUID guidWasLang={0}, guidWasLangVendor={0},guidWasDoc={0};
+WCHAR wzWasFileName[2048];
+ULONG ulWasLine = 0;
+FILE* pFile=NULL;
+BOOL bIsNewFile = TRUE;
+WCHAR wzUniBuf[UNIBUF_SIZE];
+char szString[SZSTRING_SIZE];
+//-----------------------------------
+struct LexScope
+{
+ DWORD dwStart;
+ DWORD dwEnd;
+ ISymUnmanagedScope* pISymScope;
+ DWORD dwZOrder;
+ inline bool IsOpen() { return (dwZOrder != 0); };
+ inline bool Covers(DWORD dwOffset) { return ((dwStart <= dwOffset) && (dwOffset < dwEnd)); };
+};
+//-----------------------------------
+
+OPCODE DecodeOpcode(const BYTE *pCode, DWORD *pdwLen)
+{
+ OPCODE opcode;
+
+ *pdwLen = 1;
+ opcode = OPCODE(pCode[0]);
+ switch(opcode) {
+ case CEE_PREFIX1:
+ opcode = OPCODE(pCode[1] + 256);
+ if (opcode < 0 || opcode >= CEE_COUNT)
+ opcode = CEE_COUNT;
+ *pdwLen = 2;
+ break;
+ case CEE_PREFIXREF:
+ case CEE_PREFIX2:
+ case CEE_PREFIX3:
+ case CEE_PREFIX4:
+ case CEE_PREFIX5:
+ case CEE_PREFIX6:
+ case CEE_PREFIX7:
+ *pdwLen = 3;
+ return CEE_COUNT;
+ default:
+ break;
+ }
+ return opcode;
+}
+//------------------------------------------------------------------
+WCHAR* UtfToUnicode(__in __nullterminated const char* sz)
+{
+ WCHAR* wz = wzUniBuf;
+ if (WszMultiByteToWideChar(CP_UTF8,0,sz,-1,wz,UNIBUF_SIZE/2) == 0)
+ {
+ wz[UNIBUF_SIZE/2 - 1] = 0;
+ }
+ return wz;
+}
+char* UnicodeToAnsi(__in __nullterminated const WCHAR* wz)
+{
+ char* sz = (char*)(&wzUniBuf[UNIBUF_SIZE/2]);
+ if (WszWideCharToMultiByte(g_uConsoleCP,0,wz,-1,sz,UNIBUF_SIZE,NULL,NULL) == 0)
+ {
+ sz[UNIBUF_SIZE - 1] = 0;
+ }
+ return sz;
+}
+WCHAR* AnsiToUnicode(__in __nullterminated const char* sz)
+{
+ WCHAR* wz = wzUniBuf;
+ if (WszMultiByteToWideChar(g_uConsoleCP,0,sz,-1,wz,UNIBUF_SIZE/2) == 0)
+ {
+ wz[UNIBUF_SIZE/2 - 1] = 0;
+ }
+ return wz;
+}
+char* UnicodeToUtf(__in __nullterminated const WCHAR* wz)
+{
+ char* sz = (char*)(&wzUniBuf[UNIBUF_SIZE/2]);
+ if (WszWideCharToMultiByte(CP_UTF8,0,wz,-1,sz,UNIBUF_SIZE,NULL,NULL) == 0)
+ {
+ sz[UNIBUF_SIZE - 1] = 0;
+ }
+ return sz;
+}
+char* AnsiToUtf(__in __nullterminated const char* sz) { return UnicodeToUtf(AnsiToUnicode(sz));}
+
+static void UnicodeToConsoleOrMsgBox(__in __nullterminated const WCHAR* wz)
+{
+ if (g_Mode & MODE_GUI)
+ WszMessageBox(NULL,wz,RstrW(IDS_ERRORCAPTION),MB_OK|MB_ICONERROR|GetDasmMBRTLStyle());
+ else
+ {
+ //DWORD dw;
+ //char* sz = UnicodeToAnsi(wz);
+ //WriteFile(hConsoleOut,(CONST VOID *)sz, (ULONG32)strlen(sz),&dw,NULL);
+ //WriteFile(hConsoleOut,(CONST VOID *)"\r\n", 2,&dw,NULL);
+ printf("%s\n",UnicodeToAnsi(wz));
+ }
+}
+static void UnicodeToFile(__in __nullterminated const WCHAR* wz, FILE* pF)
+{
+ unsigned endofline = 0x000A000D;
+ int L;
+ if((L=(int)wcslen(wz))) fwrite(wz,L*sizeof(WCHAR),1,pF);
+ fwrite(&endofline,4,1,pF);
+}
+static void ToGUIOrFile(__in __nullterminated const char* sz, void* GUICookie)
+{
+ if (g_Mode & MODE_GUI)
+ GUIAddOpcode(sz, GUICookie);
+ else
+ {
+ if(g_fDumpRTF) fprintf((FILE*)GUICookie,"%s\\line\n",sz);
+ else fprintf((FILE*)GUICookie,"%s\n",sz);
+ }
+}
+//------------------------------------------------------------------
+void printError(void* GUICookie, __in __nullterminated const char* string)
+{
+ if(g_Mode & MODE_GUI) printLine(GUICookie, ERRORMSG(string));
+ else
+ {
+ //DWORD dw;
+ const char* sz = ERRORMSG(string);
+ if(GUICookie) printLine(GUICookie, sz);
+ //sz = UnicodeToAnsi(UtfToUnicode(string));
+ //WriteFile(hConsoleErr,(CONST VOID *)sz, (ULONG32)strlen(sz),&dw,NULL);
+ //WriteFile(hConsoleErr,(CONST VOID *)"\r\n", 2,&dw,NULL);
+ fprintf(stderr,"%s\n",UnicodeToAnsi(UtfToUnicode(string)));
+ }
+}
+void printLine(void* GUICookie, __in __nullterminated const char* string)
+{
+ const char* sz = string;
+
+ if (GUICookie == NULL)
+ {
+ UnicodeToConsoleOrMsgBox(UtfToUnicode(string));
+ return;
+ }
+
+
+ if(g_uCodePage != CP_UTF8)
+ {
+ WCHAR* wz = UtfToUnicode(string);
+ if(g_uCodePage != 0xFFFFFFFF)
+ {
+ sz = UnicodeToAnsi(wz);
+ }
+ else if(GUICookie && (!(g_Mode & MODE_GUI)))
+ {
+ UnicodeToFile(wz,(FILE*)GUICookie);
+ return;
+ }
+ else sz = (char*)wz;
+ }
+ ToGUIOrFile(sz,GUICookie);
+}
+
+void printLineW(void* GUICookie, __in __nullterminated const WCHAR* string)
+{
+ const char* sz = (const char*)string;
+
+ if (GUICookie == NULL)
+ {
+ UnicodeToConsoleOrMsgBox(string);
+ return;
+ }
+ if(g_uCodePage == 0xFFFFFFFF)
+ {
+ if(!(g_Mode & MODE_GUI))
+ {
+ UnicodeToFile(string,(FILE*)GUICookie);
+ return;
+ }
+ }
+ else if(g_uCodePage == CP_UTF8)
+ sz = UnicodeToUtf(string);
+ else if(g_uCodePage == g_uConsoleCP)
+ sz = UnicodeToAnsi(string);
+
+ ToGUIOrFile(sz,GUICookie);
+}
+
+char * DumpQString(void* GUICookie,
+ __in __nullterminated const char* szToDump,
+ __in __nullterminated const char* szPrefix,
+ unsigned uMaxLen)
+{
+ unsigned Lwt = (unsigned)strlen(szString);
+ char* szptr = &szString[Lwt];
+ const char* p = szToDump;
+ unsigned L = (unsigned)strlen(szToDump);
+ unsigned l,i;
+ unsigned tally=0;
+ *szptr++ = '"';
+
+ do
+ {
+ l = L;
+ if(l > uMaxLen+2) // +2 - to account for leading/trailing doublequotes in szToDump
+ {
+ l = uMaxLen;
+ while((p[l-1] == '\\')&& l) l--;
+ if(l == 0) l = (uMaxLen+1) & 0xFFFFFFFE;
+ }
+ if(tally)
+ {
+ printLine(GUICookie,szString);
+ szptr = szString;
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s+ \"",szPrefix);
+ }
+ else uMaxLen = uMaxLen - (ULONG32)strlen(szPrefix) + Lwt;
+ tally++;
+ for(i=0; i < l; i++, szptr++, p++)
+ {
+ switch(*p)
+ {
+ case '\n': *szptr++ = '\\'; *szptr = 'n'; break;
+ case '\r': *szptr++ = '\\'; *szptr = 'r'; break;
+ case '\t': *szptr++ = '\\'; *szptr = 't'; break;
+ case '\b': *szptr++ = '\\'; *szptr = 'b'; break;
+ case '\f': *szptr++ = '\\'; *szptr = 'f'; break;
+ case '\v': *szptr++ = '\\'; *szptr = 'v'; break;
+ case '\a': *szptr++ = '\\'; *szptr = 'a'; break;
+ case '\?': *szptr++ = '\\'; *szptr = '?'; break;
+ case '\\': *szptr++ = '\\'; *szptr = '\\'; break;
+ case '"': *szptr++ = '\\'; *szptr = '"'; break;
+ case '{': szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),SCOPE()); szptr--; break;
+ case '}': szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),UNSCOPE()); szptr--; break;
+ case '<': szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),LTN()); szptr--; break;
+ case '>': szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),GTN()); szptr--; break;
+ default: *szptr = *p; break;
+ }
+ }
+ *szptr++ = '"';
+ *szptr = 0;
+ L -= l;
+ } while(L);
+ return szptr;
+}
+struct DasmExceptionInfoClause : COR_ILMETHOD_SECT_EH_CLAUSE_FAT {
+public:
+ bool ClauseIsFat;
+};
+DasmExceptionInfoClause* g_ehInfo = NULL;
+ULONG g_ehCount = 0;
+/********************************************************************************/
+/* used by qsort to sort the g_ehInfo table */
+static int __cdecl ehInfoCmp(const void *op1, const void *op2)
+{
+ DasmExceptionInfoClause* p1 = (DasmExceptionInfoClause*)op1;
+ DasmExceptionInfoClause* p2 = (DasmExceptionInfoClause*)op2;
+ int d;
+ d = p1->GetTryOffset() - p2->GetTryOffset(); if(d) return d;
+ d = p1->GetTryLength() - p2->GetTryLength(); if(d) return d;
+ d = p1->GetHandlerOffset() - p2->GetHandlerOffset(); if(d) return d;
+ d = p1->GetHandlerLength() - p2->GetHandlerLength(); if(d) return d;
+ return 0;
+}
+
+BOOL enumEHInfo(const COR_ILMETHOD_SECT_EH* eh, IMDInternalImport *pImport, DWORD dwCodeSize)
+{
+ COR_ILMETHOD_SECT_EH_CLAUSE_FAT ehBuff;
+ const COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehInfo;
+ BOOL fTryInCode = FALSE;
+ if(g_ehInfo) VDELETE(g_ehInfo);
+ g_ehCount = 0;
+ if(eh && (g_ehCount = eh->EHCount()))
+ {
+ g_ehInfo = new DasmExceptionInfoClause[g_ehCount];
+ _ASSERTE(g_ehInfo != NULL);
+ unsigned i;
+ for (i = 0; i < g_ehCount; i++)
+ {
+ ehInfo = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)eh->EHClause(i, &ehBuff);
+ memcpy(&g_ehInfo[i],ehInfo,sizeof(COR_ILMETHOD_SECT_EH_CLAUSE_FAT));
+ g_ehInfo[i].ClauseIsFat = eh->IsFat();
+ //_ASSERTE((ehInfo->GetFlags() & SEH_NEW_PUT_MASK) == 0); // we are using 0x80000000 and 0x40000000
+ g_ehInfo[i].SetFlags((CorExceptionFlag)((int)ehInfo->GetFlags() & ~SEH_NEW_PUT_MASK));
+ }
+ // check if all boundaries are within method code:
+ fTryInCode = g_fTryInCode;
+ for(i=0; i < g_ehCount; i++)
+ {
+ if( (g_ehInfo[i].GetTryOffset() >= dwCodeSize) ||
+ (g_ehInfo[i].GetTryOffset() + g_ehInfo[i].GetTryLength() >= dwCodeSize)||
+ (g_ehInfo[i].GetHandlerOffset() >= dwCodeSize) ||
+ (g_ehInfo[i].GetHandlerOffset() + g_ehInfo[i].GetHandlerLength() > dwCodeSize))
+ {
+ g_ehInfo[i].SetFlags((CorExceptionFlag)((int)g_ehInfo[i].GetFlags() | ERR_OUT_OF_CODE));
+ fTryInCode = FALSE; // if out of code, don't expand
+ }
+ }
+
+ if(fTryInCode)
+ {
+ DWORD dwWasTryOffset=0xFFFFFFFF, dwWasTryLength=0xFFFFFFFF, dwLastOffset=0xFFFFFFFF;
+ unsigned iNewTryBlock=0;
+ qsort(g_ehInfo, g_ehCount, sizeof(DasmExceptionInfoClause), ehInfoCmp);
+ for(i=0; i < g_ehCount; i++)
+ {
+ if((g_ehInfo[i].GetTryOffset() != dwWasTryOffset)||(g_ehInfo[i].GetTryLength() != dwWasTryLength))
+ {
+ g_ehInfo[i].SetFlags((CorExceptionFlag)((int)g_ehInfo[i].GetFlags() | NEW_TRY_BLOCK)); // insert try in source
+ dwLastOffset = g_ehInfo[i].GetTryOffset() + g_ehInfo[i].GetTryLength();
+ dwWasTryOffset = g_ehInfo[i].GetTryOffset();
+ dwWasTryLength = g_ehInfo[i].GetTryLength();
+ iNewTryBlock = i;
+ }
+
+ // determine offset of the block that lexically follows the try block (filter or handler)
+ DWORD dwFilterOrHandlerOffset;
+ if (g_ehInfo[i].GetFlags() & COR_ILEXCEPTION_CLAUSE_FILTER)
+ {
+ dwFilterOrHandlerOffset = g_ehInfo[i].GetFilterOffset();
+ }
+ else
+ dwFilterOrHandlerOffset = g_ehInfo[i].GetHandlerOffset();
+
+ if (dwFilterOrHandlerOffset == dwLastOffset)
+ {
+ if((i == iNewTryBlock)||((int)g_ehInfo[iNewTryBlock].GetFlags() & PUT_INTO_CODE))
+ g_ehInfo[i].SetFlags((CorExceptionFlag)((int)g_ehInfo[i].GetFlags() | PUT_INTO_CODE)); // insert catch/filter/finally in source
+ else
+ g_ehInfo[i].SetFlags((CorExceptionFlag)((int)g_ehInfo[i].GetFlags() | NEW_TRY_BLOCK)); // insert catch/filter/finally in source
+
+ dwLastOffset = (g_ehInfo[i].GetHandlerOffset() + g_ehInfo[i].GetHandlerLength());
+ }
+ else
+ g_ehInfo[i].SetFlags((CorExceptionFlag)((int)g_ehInfo[i].GetFlags() | NEW_TRY_BLOCK)); // insert try in source
+ }
+ }
+ else
+ {
+ for(i=0; i < g_ehCount; i++)
+ {
+ g_ehInfo[i].SetFlags((CorExceptionFlag)((int)g_ehInfo[i].GetFlags() | NEW_TRY_BLOCK)); // insert try in source
+ }
+ }
+ }
+ return fTryInCode;
+}
+
+// This dumps the hex bytes for the given EHINFO clause
+void DumpHexEHInfo(DasmExceptionInfoClause *ehInfo, void *GUICookie)
+{
+ char *szptr = &szString[0];
+ _ASSERTE(g_fShowBytes);
+ COR_ILMETHOD_SECT_EH_CLAUSE_SMALL eh; // Temporary holder if we should dump the small version
+ BYTE *pb;
+ size_t sizeToDump; // Size of the hex data we're dumping
+
+ szptr = &szString[0];
+ szptr += sprintf_s(szptr, SZSTRING_SIZE,"%s// HEX:", g_szAsmCodeIndent);
+ ehInfo->SetFlags((CorExceptionFlag)((int)ehInfo->GetFlags() & ~SEH_NEW_PUT_MASK));
+
+ if (ehInfo->ClauseIsFat)
+ {
+ // Easy, though probably less common case
+ pb = (BYTE *)ehInfo;
+ sizeToDump = sizeof(COR_ILMETHOD_SECT_EH_CLAUSE_FAT);
+ } else
+ {
+ // Dev11 #2227 - we should dump small clauses as such in the hex dump
+ // Recreate the small EH clause, here, if it came is as a small clause
+ eh.SetFlags(ehInfo->GetFlags());
+ eh.TryOffset = ehInfo->TryOffset;
+ eh.TryLength = ehInfo->TryLength;
+ eh.HandlerOffset = ehInfo->HandlerOffset;
+ eh.HandlerLength = ehInfo->HandlerLength;
+
+ // A couple of sanity checks to make sure things the hex bites recreated are alright
+ _ASSERTE(sizeof(eh.FilterOffset) == sizeof(eh.ClassToken));
+ _ASSERTE(offsetof(COR_ILMETHOD_SECT_EH_CLAUSE_SMALL, FilterOffset) == offsetof(COR_ILMETHOD_SECT_EH_CLAUSE_SMALL, ClassToken));
+ eh.FilterOffset = ehInfo->FilterOffset;
+
+ pb = (BYTE *)&eh;
+ sizeToDump = sizeof(COR_ILMETHOD_SECT_EH_CLAUSE_SMALL);
+ }
+ // Now dump the bytes out
+ for (size_t i = 0; i < sizeToDump; i++)
+ szptr += sprintf_s(szptr, SZSTRING_REMAINING_SIZE(szptr), " %2.2X", *pb++);
+ printLine(GUICookie, COMMENT(szString));
+ // ehInfo->SetFlags((CorExceptionFlag)((dwFlags & ~SEH_NEW_PUT_MASK) | PUT_INTO_CODE));
+}
+
+void dumpOneEHInfo(DasmExceptionInfoClause* ehInfo, IMDInternalImport *pImport, void *GUICookie)
+{
+ //char szString[4096];
+ char* szptr = &szString[0];
+ if(!ehInfo) return;
+ DWORD dwFlags = ehInfo->GetFlags();
+ if(dwFlags & PUT_INTO_CODE)
+ return; // by the time dumpEHInfo is called, this ehInfo is done
+ if(dwFlags & NEW_TRY_BLOCK)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s%s IL_%04x ",g_szAsmCodeIndent,KEYWORD(".try"),ehInfo->GetTryOffset());
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s IL_%04x ",KEYWORD("to"),ehInfo->GetTryOffset()+ehInfo->GetTryLength());
+ }
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s ",g_szAsmCodeIndent);
+
+ if (dwFlags & COR_ILEXCEPTION_CLAUSE_FILTER)
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%s IL_%04x ",KEYWORD("filter"),ehInfo->GetFilterOffset());
+ else if (dwFlags & COR_ILEXCEPTION_CLAUSE_FAULT)
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), KEYWORD("fault "));
+ else if (dwFlags & COR_ILEXCEPTION_CLAUSE_FINALLY || IsNilToken(ehInfo->GetClassToken()))
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), KEYWORD("finally "));
+ else
+ {
+ CQuickBytes out;
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%s %s ",KEYWORD("catch"),PrettyPrintClass(&out, ehInfo->GetClassToken(), pImport));
+ REGISTER_REF(g_tkRefUser,ehInfo->GetClassToken());
+ }
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%s IL_%04x",KEYWORD("handler"),ehInfo->GetHandlerOffset());
+ if(ehInfo->GetHandlerLength() != (DWORD) -1)
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), " %s IL_%04x",KEYWORD("to"),ehInfo->GetHandlerOffset()+ehInfo->GetHandlerLength());
+
+ printLine(GUICookie, szString);
+
+ if(g_fShowBytes)
+ DumpHexEHInfo(ehInfo, GUICookie);
+ /*
+ if(ehInfo->GetFlags() & ERR_OUT_OF_CODE)
+ {
+ sprintf(szString,"%s// WARNING: Boundary outside the method code",g_szAsmCodeIndent);
+ printLine(GUICookie,szString);
+ }
+ */
+}
+void dumpEHInfo(IMDInternalImport *pImport, void *GUICookie)
+{
+ //char szString[4096];
+
+ if(! g_ehCount) return;
+ sprintf_s(szString, SZSTRING_SIZE, "%s// Exception count %d", g_szAsmCodeIndent, g_ehCount);
+ //sprintf_s(szString, SZSTRING_SIZE, "%s// %d irregular exception clauses", g_szAsmCodeIndent, g_ehCount);
+ printLine(GUICookie, COMMENT(szString));
+
+ for (unsigned i = 0; i < g_ehCount; i++)
+ {
+ DasmExceptionInfoClause* ehInfo = &g_ehInfo[i];
+ dumpOneEHInfo(ehInfo,pImport,GUICookie);
+ }
+}
+
+static int __cdecl cmpLineCode(const void *p1, const void *p2)
+{ int ret = (((LineCodeDescr*)p1)->PC - ((LineCodeDescr*)p2)->PC);
+ if(ret==0)
+ {
+ ret= (((LineCodeDescr*)p1)->Line - ((LineCodeDescr*)p2)->Line);
+ if(ret==0) ret= (((LineCodeDescr*)p1)->Column - ((LineCodeDescr*)p2)->Column);
+ }
+ return ret;
+}
+
+static int __cdecl cmpLexScope(const void *p1, const void *p2)
+{
+ LexScope* pls1 = (LexScope*)p1;
+ LexScope* pls2 = (LexScope*)p2;
+ int d;
+ if((d = pls1->dwStart - pls2->dwStart)) return d;
+ return (pls2->dwEnd - pls1->dwEnd);
+}
+
+char* DumpDataPtr(__inout __nullterminated char* buffer, DWORD ptr, DWORD size)
+{
+ // check if ptr really points to some data in one of sections
+ IMAGE_SECTION_HEADER *pSecHdr = NULL;
+ DWORD i;
+ 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);
+ }
+
+ for (i=0; i < dwNumberOfSections; i++,pSecHdr++)
+ {
+ if((ptr >= VAL32(pSecHdr->VirtualAddress))&&
+ (ptr < VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->Misc.VirtualSize)))
+ {
+ if(ptr+size > VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->Misc.VirtualSize)) i = dwNumberOfSections;
+ break;
+ }
+ }
+ if(i < dwNumberOfSections)
+ { // yes, the pointer points to real data
+ int j;
+ for(j=0; (j < g_iPtrCount)&&((*g_pPtrTags)[j] != (__int32)ptr); j++);
+ if(j == g_iPtrCount)
+ {
+ if (g_pPtrSize == NULL)
+ {
+ g_pPtrSize = new DynamicArray<DWORD>;
+ }
+ if (g_pPtrTags == NULL)
+ {
+ g_pPtrTags = new DynamicArray<__int32>;
+ }
+
+ (*g_pPtrSize)[g_iPtrCount] = size;
+ (*g_pPtrTags)[g_iPtrCount++] = ptr;
+ }
+ else if((*g_pPtrSize)[j] < size) (*g_pPtrSize)[j] = size;
+ const char* szTls = "D_";
+ if(strcmp((const char*)(pSecHdr->Name),".tls") == 0) szTls = "T_";
+ else if(strcmp((const char*)(pSecHdr->Name),".text") == 0) szTls = "I_";
+ buffer+=sprintf_s(buffer,SZSTRING_REMAINING_SIZE(buffer), "%s%8.8X",szTls,ptr);
+ } //else print as hex
+ else
+ {
+ buffer+=sprintf_s(buffer,SZSTRING_REMAINING_SIZE(buffer),ERRORMSG("0x%8.8X /* WARNING: rogue pointer! (size 0x%8.8X) */"),ptr,size);
+ }
+ return buffer;
+}
+
+void DumpLocals(IMDInternalImport *pImport,COR_ILMETHOD_DECODER *pMethod, __in __nullterminated char* szVarPrefix, void* GUICookie)
+{
+ if (pMethod->GetLocalVarSigTok())
+ {
+ DWORD cbSigLen;
+ PCCOR_SIGNATURE pComSig;
+ CQuickBytes qbMemberSig;
+ size_t dwL;
+
+
+ if (FAILED(pImport->GetSigFromToken(pMethod->GetLocalVarSigTok(), &cbSigLen, &pComSig)))
+ {
+ printLine(GUICookie, "Invalid record");
+ return;
+ }
+
+ _ASSERTE(*pComSig == IMAGE_CEE_CS_CALLCONV_LOCAL_SIG);
+
+ appendStr(&qbMemberSig, g_szAsmCodeIndent);
+ appendStr(&qbMemberSig, KEYWORD(".locals "));
+ if(g_fDumpTokens)
+ {
+ char sz[32];
+ sprintf_s(sz,32,"/*%08X*/ ",pMethod->GetLocalVarSigTok());
+ appendStr(&qbMemberSig,COMMENT(sz));
+ }
+ if(pMethod->GetFlags() & CorILMethod_InitLocals) appendStr(&qbMemberSig, KEYWORD("init "));
+ dwL = qbMemberSig.Size();
+
+ char* pszTailSig = (char *) PrettyPrintSig(pComSig, cbSigLen, 0, &qbMemberSig, pImport,szVarPrefix);
+ if(strlen(pszTailSig) < dwL+3) return;
+
+ {
+ ULONG32 i,j,k,indent = (ULONG32)strlen(g_szAsmCodeIndent)+9; // indent+.locals (
+ char chAfterComma;
+ char *pComma = pszTailSig, *pch;
+ while((pComma = strchr(pComma,',')))
+ {
+ for(pch = pszTailSig, i=0, j=0, k=0; pch < pComma; pch++)
+ {
+ if(*pch == '\'') j=1-j;
+ else if(j==0)
+ {
+ if(*pch == '[') i++;
+ else if(*pch == ']') i--;
+ else if(strncmp(pch,LTN(),strlen(LTN()))==0) k++;
+ else if(strncmp(pch,GTN(),strlen(GTN()))==0) k--;
+ }
+ }
+ pComma++;
+ if((i==0)&&(k==0)&&(j==0)) // no brackets or all opened/closed
+ {
+ chAfterComma = *pComma;
+ *pComma = 0;
+ printLine(GUICookie,pszTailSig);
+ *pComma = chAfterComma;
+ for(i=0; i<indent; i++) pszTailSig[i] = ' ';
+ strcpy_s(&pszTailSig[indent],strlen(pComma)+1,pComma);
+ pComma = pszTailSig;
+ }
+ }
+ }
+ printLine(GUICookie, pszTailSig);
+ }
+}
+void LoadScope(ISymUnmanagedScope *pIScope,
+ DynamicArray<LexScope> *pdaScope,
+ ULONG *pulScopes)
+{
+ ULONG32 ulVars;
+ ULONG32 ulStart;
+ ULONG32 ulEnd;
+ ISymUnmanagedScope** ppChildScope = new ISymUnmanagedScope*[4096];
+ ULONG32 ulChildren;
+ unsigned i;
+
+ if(SUCCEEDED(pIScope->GetLocalCount(&ulVars)) && ulVars)
+ {
+ if(SUCCEEDED(pIScope->GetStartOffset(&ulStart)) &&
+ SUCCEEDED(pIScope->GetEndOffset(&ulEnd)))
+ {
+ (*pdaScope)[*pulScopes].dwStart = ulStart;
+ (*pdaScope)[*pulScopes].dwEnd = ulEnd;
+ (*pdaScope)[*pulScopes].dwZOrder = 0;
+ (*pdaScope)[*pulScopes].pISymScope = pIScope;
+ pIScope->AddRef();
+ (*pulScopes)++;
+ }
+ }
+ if(SUCCEEDED(pIScope->GetChildren(4096,&ulChildren,ppChildScope)))
+ {
+ for(i = 0; i < ulChildren; i++)
+ {
+ if(ppChildScope[i]) {
+ LoadScope(ppChildScope[i],pdaScope,pulScopes);
+ ppChildScope[i]->Release();
+ }
+ }
+ }
+ VDELETE(ppChildScope);
+
+}
+//#define SHOW_LEXICAL_SCOPES
+void OpenScope(ISymUnmanagedScope *pIScope,
+ __inout_ecount(ulLocals) ParamDescriptor *pLV,
+ ULONG ulLocals)
+{
+ ULONG32 dummy;
+ ULONG32 ulVars;
+ ULONG32 ulSlot;
+ ISymUnmanagedVariable** pVars = NULL;
+
+ if(FAILED(pIScope->GetLocalCount(&ulVars))) return;
+
+ ULONG32 ulNameLen;
+#ifdef SHOW_LEXICAL_SCOPES
+ for(unsigned jj = 0; jj < ulLocals; jj++) pLV[jj].attr = 0xFFFFFFFF;
+#endif
+ if(ulVars)
+ {
+ pVars = new ISymUnmanagedVariable*[ulVars+4];
+ memset(pVars,0,sizeof(PVOID)*(ulVars+4));
+
+ if(SUCCEEDED(pIScope->GetLocals(ulVars+4,&dummy,pVars)))
+ {
+ WCHAR* wzName = wzUniBuf;
+ char* szName = NULL;
+ for(ULONG ilv = 0; ilv < ulVars; ilv++)
+ {
+ if(pVars[ilv])
+ {
+ // get the local var slot number and make sure that it's in bounds:
+ if(SUCCEEDED(pVars[ilv]->GetAddressField1(&ulSlot)) && ulSlot < ulLocals)
+ {
+ if(SUCCEEDED(pVars[ilv]->GetName(UNIBUF_SIZE/2,&ulNameLen,wzName)))
+ {
+ szName = UnicodeToUtf(wzName);
+#ifndef SHOW_LEXICAL_SCOPES
+ for(ULONG32 j=0; j<ulLocals; j++)
+ {
+ if(j == ulSlot) continue;
+ if((pLV[ulSlot].name!=NULL)&&(!strcmp(szName,pLV[j].name)))
+ {
+ sprintf_s(szName,UNIBUF_SIZE/2,"V_%d",ulSlot);
+ break;
+ }
+ }
+#endif
+ if (!*szName)
+ sprintf_s(szName,UNIBUF_SIZE/2,"V_%d",ulSlot);
+ ulNameLen = (ULONG32) strlen(szName);
+ if((pLV[ulSlot].name==NULL)||(ulNameLen > (ULONG32)strlen(pLV[ulSlot].name)))
+ {
+ VDELETE(pLV[ulSlot].name);
+ pLV[ulSlot].name = new char[ulNameLen+1];
+ }
+ if(pLV[ulSlot].name != NULL)
+ strcpy_s(pLV[ulSlot].name,ulNameLen+1,szName);
+ }
+ pLV[ulSlot].attr = ulSlot;
+ }
+ pVars[ilv]->Release();
+ }
+ }
+ }
+ VDELETE(pVars);
+ }
+}
+
+char* DumpUnicodeString(void* GUICookie,
+ __inout __nullterminated char* szString,
+ __in_ecount(cbString) WCHAR* pszString,
+ ULONG cbString,
+ bool SwapString )
+{
+ unsigned i,L;
+ char* szStr=NULL, *szRet = NULL;
+#if defined(ALIGN_ACCESS) || BIGENDIAN
+ WCHAR* pszStringCopy = NULL;
+ // Make a copy if the string is unaligned or we have to modify it
+ if (cbString > 0)
+ {
+#if !BIGENDIAN
+ if((size_t)pszString & (sizeof(WCHAR)-1))
+#endif
+ {
+ L = (cbString+1)*sizeof(WCHAR);
+ pszStringCopy = new WCHAR[cbString+1];
+ memcpy(pszStringCopy, pszString, L);
+ pszString=pszStringCopy;
+ }
+ }
+#endif
+
+#if BIGENDIAN
+ if (SwapString)
+ SwapStringLength(pszString, cbString);
+#endif
+
+ // first, check for embedded zeros:
+ for(i=0; i < cbString; i++)
+ {
+ if(pszString[i] == 0) goto DumpAsByteArray;
+ }
+ szStr = new char[cbString*3 + 5];
+ memset(szStr,0,cbString*3 + 5);
+
+ WszWideCharToMultiByte(CP_UTF8,0,pszString,cbString,&szStr[0],cbString*3,NULL,NULL);
+ L = (unsigned)strlen(szStr);
+
+ szStr[L] = 0;
+ for(i=0; i < L; i++)
+ {
+ if((!isprint(((BYTE)(szStr[i]))))&&(szStr[i]!='\t')&&(szStr[i]!='\n')&&(szStr[i]!='\r')) break;
+ }
+
+ if(i == L)
+ {
+ szRet = DumpQString(GUICookie,szStr,g_szAsmCodeIndent, 50);
+ }
+ else
+ {
+DumpAsByteArray:
+ strcat_s(szString,SZSTRING_SIZE,KEYWORD("bytearray"));
+ strcat_s(szString,SZSTRING_SIZE," (");
+
+#if BIGENDIAN
+ SwapStringLength(pszString, cbString);
+#endif
+ DumpByteArray(szString,(BYTE*)pszString,cbString*sizeof(WCHAR),GUICookie);
+ szRet = &szString[strlen(szString)];
+ }
+ if(szStr) VDELETE(szStr);
+#if defined(ALIGN_ACCESS) || BIGENDIAN
+ if(pszStringCopy) VDELETE(pszStringCopy);
+#endif
+ return szRet;
+}
+
+// helper to avoid mixing of SEH and stack objects with destructors
+BOOL SourceLinesHelper(void *GUICookie, LineCodeDescr* pLCD, __out_ecount(nSize) WCHAR* pFileName, UINT nSize)
+{
+ _ASSERTE(nSize > 0);
+ memset(pFileName, 0, nSize * sizeof(WCHAR));
+
+ if(pLCD->FileToken == 0)
+ {
+ return FALSE;
+ }
+
+ struct Param
+ {
+ void *GUICookie;
+ LineCodeDescr* pLCD;
+ WCHAR* pFileName;
+ UINT nSize;
+ BOOL fRet;
+ } param;
+ param.GUICookie = GUICookie;
+ param.pLCD = pLCD;
+ param.pFileName = pFileName;
+ param.nSize = nSize;
+ param.fRet = FALSE;
+
+ PAL_TRY(Param *, pParam, &param) {
+ GUID guidLang={0},guidLangVendor={0},guidDoc={0};
+ WCHAR wzLang[64],wzVendor[64],wzDoc[64];
+ ULONG32 k;
+ if(pParam->pLCD->FileToken != ulWasFileToken)
+ {
+ ((ISymUnmanagedDocument*)(pParam->pLCD->FileToken))->GetLanguage(&guidLang);
+ ((ISymUnmanagedDocument*)(pParam->pLCD->FileToken))->GetLanguageVendor(&guidLangVendor);
+ ((ISymUnmanagedDocument*)(pParam->pLCD->FileToken))->GetDocumentType(&guidDoc);
+ if(memcmp(&guidLang,&guidWasLang,sizeof(GUID))
+ ||memcmp(&guidLangVendor,&guidWasLangVendor,sizeof(GUID))
+ ||memcmp(&guidDoc,&guidWasDoc,sizeof(GUID)))
+ {
+ GuidToLPWSTR(guidLang,wzLang,64);
+ GuidToLPWSTR(guidLangVendor,wzVendor,64);
+ GuidToLPWSTR(guidDoc,wzDoc,64);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s '%ls', '%ls', '%ls'", g_szAsmCodeIndent,KEYWORD(".language"),
+ wzLang,wzVendor,wzDoc);
+ printLine(pParam->GUICookie,szString);
+ memcpy(&guidWasLang,&guidLang,sizeof(GUID));
+ memcpy(&guidWasLangVendor,&guidLangVendor,sizeof(GUID));
+ memcpy(&guidWasDoc,&guidDoc,sizeof(GUID));
+ }
+
+ /*
+ BOOL fHasEmbeddedSource=FALSE;
+ ((ISymUnmanagedDocument*)(pParam->pLCD->FileToken))->HasEmbeddedSource(&fHasEmbeddedSource);
+ sprintf(szString,"%s// PDB has %sembedded source",g_szAsmCodeIndent,
+ fHasEmbeddedSource ? "" : "no ");
+ printLine(pParam->GUICookie,szString);
+ */
+ }
+ ((ISymUnmanagedDocument*)(pParam->pLCD->FileToken))->GetURL(pParam->nSize,&k,pParam->pFileName);
+ ulWasFileToken = pParam->pLCD->FileToken;
+ pParam->fRet = TRUE;
+ } PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_ERRORREOPENINGFILE),pLCD->FileToken);
+ printError(GUICookie, szString);
+ }
+ WIN_PAL_ENDTRY
+
+ return param.fRet;
+}
+
+#ifdef _PREFAST_
+#pragma warning(push)
+#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
+#endif
+BOOL Disassemble(IMDInternalImport *pImport, BYTE *ILHeader, void *GUICookie, mdToken FuncToken, ParamDescriptor* pszArgname, ULONG ulArgs)
+{
+ HRESULT hr;
+ DWORD PC;
+ BOOL fNeedNewLine = FALSE;
+ //char szString[4096];
+ char* szptr;
+ BYTE* pCode = NULL;
+ BOOL fTryInCode;
+
+ COR_ILMETHOD_DECODER method((COR_ILMETHOD*) ILHeader);
+
+ pCode = const_cast<BYTE*>(method.Code);
+
+ sprintf_s(szString,SZSTRING_SIZE, RstrUTF(IDS_E_CODESIZE),g_szAsmCodeIndent, method.GetCodeSize(), method.GetCodeSize());
+ printLine(GUICookie, szString);
+
+ if(method.GetCodeSize() == 0) return TRUE;
+
+ sprintf_s(szString,SZSTRING_SIZE, "%s%s %d",g_szAsmCodeIndent, KEYWORD(".maxstack"),method.GetMaxStack());
+ printLine(GUICookie, szString);
+
+ //------------ Source lines display ---------------------------------
+ ULONG32 ulLines =0;
+ LineCodeDescr* LineCode = NULL;
+ BOOL fShowSource = FALSE;
+ BOOL fInsertSourceLines = FALSE;
+ LineCodeDescr* pLCD = NULL;
+ ParamDescriptor* pszLVname = NULL;
+ ULONG ulVars=0;
+ char szVarPrefix[64];
+ // scope handling:
+ DynamicArray<LexScope> daScope;
+ ULONG ulScopes=0;
+ DWORD dwScopeZOrder = 0;
+ ISymUnmanagedScope* pRootScope = NULL;
+ ISymUnmanagedMethod* pSymMethod = NULL;
+ char szFileName[2048];
+ ISymUnmanagedDocument* pMethodDoc[2] = {NULL,NULL};
+ ULONG32 ulMethodLine[2];
+ ULONG32 ulMethodCol[2];
+ BOOL fHasRangeInfo = FALSE;
+
+ strcpy_s(szVarPrefix,64,"V0");
+ if(g_pSymReader)
+ {
+ g_pSymReader->GetMethod(FuncToken,&pSymMethod);
+ if(g_fShowSource || g_fInsertSourceLines)
+ {
+ if(pSymMethod)
+ {
+ unsigned ulActualLines=0; // VS compilers produce "Hidden" line numbers, don't count them
+ if(FAILED(pSymMethod->GetSourceStartEnd(pMethodDoc,ulMethodLine,ulMethodCol,&fHasRangeInfo)))
+ {
+ fHasRangeInfo = FALSE;
+ }
+ pSymMethod->GetSequencePointCount(&ulLines);
+ if (ulLines != 0)
+ {
+ LineCode = new LineCodeDescr[ulLines+2];
+ memset(LineCode, 0, sizeof(LineCodeDescr) * (ulLines + 2));
+ }
+ if(ulLines != 0 && LineCode != NULL)
+ {
+ pLCD = &LineCode[0];
+ if(fHasRangeInfo)
+ {
+ //printLine(GUICookie,"// Has source range info");
+ pLCD->Line = ulMethodLine[0];
+ pLCD->Column = ulMethodCol[0];
+ pLCD->PC = 0;
+ pLCD->FileToken = (ULONG_PTR)pMethodDoc[0];
+ ulActualLines++;
+ pLCD++;
+ }
+ if(ulLines)
+ {
+ ULONG32 *offsets=new ULONG32[ulLines], *lines=new ULONG32[ulLines], *columns=new ULONG32[ulLines];
+ ULONG32 *endlines=new ULONG32[ulLines], *endcolumns=new ULONG32[ulLines];
+ ISymUnmanagedDocument** docs = (ISymUnmanagedDocument**)(new PVOID[ulLines]);
+ ULONG32 actualCount;
+ pSymMethod->GetSequencePoints(ulLines,&actualCount, offsets,docs,lines,columns, endlines, endcolumns);
+ for(ULONG i = 0; i < ulLines; i++)
+ {
+ pLCD->Line = lines[i];
+ pLCD->Column = columns[i];
+ pLCD->LineEnd = endlines[i];
+ pLCD->ColumnEnd = endcolumns[i];
+ pLCD->PC = offsets[i];
+ pLCD->FileToken = (ULONG_PTR)docs[i];
+ ulActualLines++;
+ pLCD++;
+ }
+ VDELETE(offsets);
+ VDELETE(lines);
+ VDELETE(columns);
+ VDELETE(endlines);
+ VDELETE(endcolumns);
+ VDELETE(docs);
+ } // end if(ulLines)
+ if(fHasRangeInfo)
+ {
+ pLCD->Line = ulMethodLine[1];
+ pLCD->Column = ulMethodCol[1];
+ pLCD->PC = method.GetCodeSize();
+ pLCD->FileToken = (ULONG_PTR)pMethodDoc[1];
+ ulActualLines++;
+ pLCD++;
+ }
+
+ ulLines = ulActualLines;
+ qsort(LineCode,ulLines,sizeof(LineCodeDescr),cmpLineCode);
+ fShowSource = g_fShowSource;
+ fInsertSourceLines = g_fInsertSourceLines;
+ pLCD = &LineCode[0];
+ } // end if(LineCode)
+ } //end if (pSymMethod)
+ }//end if(g_fShowSource)
+ if (method.GetLocalVarSigTok())
+ {
+ // first, get the real number of local vars from signature
+ DWORD cbSigLen;
+ PCCOR_SIGNATURE pComSig;
+ mdSignature mdLocalVarSigTok = method.GetLocalVarSigTok();
+ if ((TypeFromToken(mdLocalVarSigTok) != mdtSignature) ||
+ (!pImport->IsValidToken(mdLocalVarSigTok)) || (RidFromToken(mdLocalVarSigTok) == 0))
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_BOGUSLVSIG),mdLocalVarSigTok);
+ printError(GUICookie,szString);
+ return FALSE;
+ }
+ if (FAILED(pImport->GetSigFromToken(mdLocalVarSigTok, &cbSigLen, &pComSig)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, RstrUTF(IDS_E_INVALIDRECORD), mdLocalVarSigTok);
+ printError(GUICookie, szString);
+ return FALSE;
+ }
+ _ASSERTE(*pComSig == IMAGE_CEE_CS_CALLCONV_LOCAL_SIG);
+ pComSig++;
+
+ ULONG ulVarsInSig = CorSigUncompressData(pComSig);
+ if(pSymMethod) pSymMethod->GetRootScope(&pRootScope);
+ else pRootScope = NULL;
+
+ if(pRootScope)
+ {
+ ulVars = ulVarsInSig;
+ }
+ else ulVars = 0;
+ if(ulVars)
+ {
+ ULONG ilvs;
+ pszLVname = new ParamDescriptor[ulVars];
+ memset(pszLVname,0,ulVars*sizeof(ParamDescriptor));
+ for(ilvs = 0; ilvs < ulVars; ilvs++)
+ {
+ pszLVname[ilvs].name = new char[16];
+ sprintf_s(pszLVname[ilvs].name,16,"V_%d",ilvs);
+ pszLVname[ilvs].attr = ilvs;
+ }
+ LoadScope(pRootScope,&daScope,&ulScopes);
+ qsort(&daScope[0],ulScopes,sizeof(LexScope),cmpLexScope);
+ OpenScope(pRootScope,pszLVname,ulVars);
+#ifdef _WIN64
+ sprintf_s(szVarPrefix,64,"@%I64d0",(size_t)pszLVname);
+#else
+ sprintf_s(szVarPrefix,64,"@%d0",(size_t)pszLVname);
+#endif //_WIN64
+
+#ifndef SHOW_LEXICAL_SCOPES
+ for(unsigned jjj = 0; jjj < ulScopes; jjj++)
+ {
+ OpenScope(daScope[jjj].pISymScope,pszLVname,ulVars);
+ daScope[jjj].pISymScope->Release();
+ }
+ ulScopes = 0;
+#endif
+ } //end if(ulLVScount)
+ if(pRootScope) pRootScope->Release();
+ } //end if (method.LocalVarSigTok)
+ } //end if(g_pDebugImport)
+ //-------------------------------------------------------------------
+ g_tkRefUser = FuncToken;
+ DumpLocals(pImport,&method, szVarPrefix, GUICookie);
+ g_tkRefUser = 0;
+
+#if defined(_DEBUG)
+ const BYTE* curFormat = pCode;
+ #pragma warning(disable : 4640)
+ static ILFormatter ilFormatter;
+ static OutString formatOut;
+ static OutString line;
+ #pragma warning(default : 4640)
+
+ if (g_fPrettyPrint) {
+ extern IMetaDataImport2* g_pPubImport;
+ ilFormatter.init(g_pPubImport, method.Code, &method.Code[method.CodeSize], method.MaxStack, method.EH);
+ }
+#endif
+
+ PC = 0;
+ fTryInCode = enumEHInfo(method.EH, pImport, method.GetCodeSize());
+ DasmExceptionInfoClause* ehInfoToPutNext = NULL;
+ if(g_Mode & MODE_GUI)
+ { // in GUI, reset everything for each method
+ ulWasFileToken = 0xFFFFFFFF;
+ memset(&guidWasLang,0,sizeof(GUID));
+ memset(&guidWasLangVendor,0,sizeof(GUID));
+ memset(&guidWasDoc,0,sizeof(GUID));
+ memset(wzWasFileName,0,sizeof(wzWasFileName));
+ ulWasLine = 0;
+ }
+ while (PC < method.GetCodeSize())
+ {
+ DWORD Len;
+ DWORD i,ii;
+ OPCODE instr;
+ char sz[1024];
+
+ instr = DecodeOpcode(&pCode[PC], &Len);
+ if (instr == CEE_COUNT)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_INSTRDECOD), pCode[PC],PC,PC);
+ printError(GUICookie, szString);
+ /*
+ while (PC < method.CodeSize)
+ {
+ printf("%02x\n", pCode[PC]);
+ PC++;
+ }
+ */
+ return FALSE;
+ }
+
+ if (fNeedNewLine)
+ {
+ fNeedNewLine = FALSE;
+ if (!(g_Mode & MODE_GUI))
+ printLine(GUICookie,"");
+ }
+
+ if(fShowSource || fInsertSourceLines)
+ {
+ while(PC == pLCD->PC)
+ {
+ bIsNewFile = FALSE;
+ if((pLCD->FileToken != ulWasFileToken) || (pLCD->Line < ulWasLine))
+ {
+ WCHAR wzFileName[2048];
+ SourceLinesHelper(GUICookie, pLCD, wzFileName, 2048);
+ bIsNewFile = (wcscmp(wzFileName,wzWasFileName)!=0);
+ if(bIsNewFile||(pLCD->Line < ulWasLine))
+ {
+ wcscpy_s(wzWasFileName,2048,wzFileName);
+ memset(szFileName,0,2048);
+ WszWideCharToMultiByte(CP_UTF8,0,wzFileName,-1,szFileName,2048,NULL,NULL);
+ if(fShowSource)
+ {
+ if(pFile) fclose(pFile);
+ pFile = NULL;
+ if(fopen_s(&pFile,szFileName,"rt") != 0)
+ {
+ char* pch = strrchr(szFileName,'\\');
+ if(pch == NULL) pch = strrchr(szFileName,':');
+ pFile = NULL;
+ if(pch) fopen_s(&pFile,pch+1,"rt");
+ }
+ if(bIsNewFile)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"// Source File '%s' %s",szFileName,(pFile ? "" : "not found"));
+ printLine(GUICookie, COMMENT(szString));
+ }
+ ulWasLine = 0;
+ }
+ }
+ }
+ if(fInsertSourceLines)
+ {
+ if(bIsNewFile)
+ {
+ const char* pszFN = ProperName(szFileName);
+ sprintf_s(szString,SZSTRING_SIZE,(*pszFN == '\'' ? "%s%s %d,%d : %d,%d %s"
+ : "%s%s %d,%d : %d,%d '%s'"),
+ g_szAsmCodeIndent,KEYWORD(".line"),pLCD->Line,pLCD->LineEnd,
+ pLCD->Column,pLCD->ColumnEnd,pszFN);
+ }
+ else
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s %d,%d : %d,%d ''",g_szAsmCodeIndent,KEYWORD(".line"),
+ pLCD->Line,pLCD->LineEnd,pLCD->Column,pLCD->ColumnEnd);
+
+ printLine(GUICookie,szString);
+ }
+
+ ULONG k= pLCD->Line;
+ if(pFile)
+ {
+ for(k = ulWasLine; k < pLCD->Line; k++)
+ {
+ if(NULL==fgets(sz,1024,pFile)) { k--; break;}
+ if((ulWasLine != 0)||(k == (pLCD->Line-1)))
+ {
+ while((sz[strlen(sz)-1]=='\n') || (sz[strlen(sz)-1]=='\r')) sz[strlen(sz)-1]=0;
+ sprintf_s(szString,SZSTRING_SIZE,"//%6.6d: %s",k+1,sz);
+ printLine(GUICookie, COMMENT(szString));
+ }
+ }
+ ulWasLine = k;
+ }
+ if(pLCD < &LineCode[ulLines-1]) pLCD++;
+ else { fShowSource = FALSE; break; }
+ }
+ }
+ if(fTryInCode)
+ {
+ g_tkRefUser = FuncToken;
+ // dumpOneEHInfo(ehInfoToPutNext,pImport,GUICookie); //doesn't do anything if ehInfoToPutNext == NULL
+ g_tkRefUser = 0;
+ ehInfoToPutNext = NULL;
+
+ for(ii = g_ehCount; ii > 0; ii--)
+ {
+ i = g_ehCount - ii;
+ DWORD theEnd = g_ehInfo[i].GetHandlerOffset()+g_ehInfo[i].GetHandlerLength();
+ if(g_ehInfo[i].GetFlags() & PUT_INTO_CODE)
+ {
+ if(PC == theEnd)
+ {
+ // reduce indent, close }
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,UNSCOPE(),COMMENT("// end handler"));
+ printLine(GUICookie,szString);
+ if(g_fShowBytes)
+ DumpHexEHInfo(&g_ehInfo[i], GUICookie);
+ g_ehInfo[i].SetTryOffset(0xFF000000);
+ g_ehInfo[i].SetHandlerOffset(0xFF000000);
+ }
+ }
+ else
+ {
+ DWORD theTryEnd = g_ehInfo[i].GetTryOffset()+g_ehInfo[i].GetTryLength();
+ if(theTryEnd > theEnd) theEnd = theTryEnd; // try block after the handler
+ if(PC == theEnd) // If we've already found the first, don't skip to the next one
+ ehInfoToPutNext = &g_ehInfo[i];
+ }
+ }
+
+ for(i = 0; i < g_ehCount; i++)
+ {
+ if(g_ehInfo[i].GetFlags() & PUT_INTO_CODE)
+ {
+ if(g_ehInfo[i].GetFlags() & NEW_TRY_BLOCK)
+ {
+ if(PC == g_ehInfo[i].GetTryOffset()+g_ehInfo[i].GetTryLength())
+ {
+ // reduce indent, close }
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,UNSCOPE(),COMMENT("// end .try"));
+ printLine(GUICookie,szString);
+ }
+ if(PC == g_ehInfo[i].GetTryOffset())
+ {
+ // Put try, {, increase indent
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,KEYWORD(".try"));
+ printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+ }
+ }
+
+ DWORD dwFlags = g_ehInfo[i].GetFlags();
+
+ if ((dwFlags & COR_ILEXCEPTION_CLAUSE_FILTER) && PC == g_ehInfo[i].GetFilterOffset())
+ {
+ // Dump filter clause, {, increase indent
+ sprintf_s(szString,SZSTRING_SIZE, "%s%s", g_szAsmCodeIndent, KEYWORD("filter"));
+ printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+ }
+
+ if(PC == g_ehInfo[i].GetHandlerOffset())
+ {
+ if (dwFlags & COR_ILEXCEPTION_CLAUSE_FILTER)
+ {
+ // reduce indent, close } (of the filter block)
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE, "%s%s %s", g_szAsmCodeIndent, UNSCOPE(), COMMENT("// end filter"));
+
+ // Dump handler clause, {, increase indent
+ printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE, "%s%s %s", g_szAsmCodeIndent, SCOPE(), COMMENT("// handler"));
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+ }
+ else
+ {
+ // Dump catch or finally clause, {, increase indent
+ if (dwFlags & COR_ILEXCEPTION_CLAUSE_FAULT)
+ sprintf_s(szString,SZSTRING_SIZE, "%s%s", g_szAsmCodeIndent, KEYWORD("fault"));
+ else if (dwFlags & COR_ILEXCEPTION_CLAUSE_FINALLY || IsNilToken(g_ehInfo[i].GetClassToken()))
+ sprintf_s(szString,SZSTRING_SIZE, "%s%s", g_szAsmCodeIndent,KEYWORD("finally"));
+ else
+ {
+ CQuickBytes out;
+ sprintf_s(szString,SZSTRING_SIZE, "%s%s %s ",g_szAsmCodeIndent,KEYWORD("catch"),
+ PrettyPrintClass(&out, g_ehInfo[i].GetClassToken(), pImport));
+ REGISTER_REF(FuncToken,g_ehInfo[i].GetClassToken());
+ }
+ printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+ }
+ }
+ } // end if(g_ehInfo[i].Flags & PUT_INTO_CODE)
+ } // end for(i<g_ehCount)
+ } // end if(fTryInCode)
+ //----------------- lexical scope handling -----------------------------
+ if(ulScopes) // non-zero only if local var info present
+ {
+ for(i=0; i < ulScopes; i++)
+ {
+ if(daScope[i].pISymScope != pRootScope)
+ {
+ if(daScope[i].IsOpen())
+ {
+ if(!daScope[i].Covers(PC))
+ {
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
+ printLine(GUICookie,szString);
+ daScope[i].dwZOrder = 0;
+ dwScopeZOrder--;
+ if(PC > daScope[i].dwEnd)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,COMMENT("%s// PDB ERROR: scope end (0x%8.8X) is not opcode-aligned"),
+ g_szAsmCodeIndent,daScope[i].dwEnd);
+ printLine(GUICookie,szString);
+ }
+ } // end if(!daScope[i].Covers(PC))
+ }
+ else // i.e., if scope is not open
+ {
+ if(daScope[i].Covers(PC))
+ {
+ if(g_fShowBytes)
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s // 0x%8.8X - 0x%8.8X",g_szAsmCodeIndent,SCOPE(),
+ daScope[i].dwStart,daScope[i].dwEnd);
+ else
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+ OpenScope(daScope[i].pISymScope,pszLVname,ulVars);
+ DumpLocals(pImport,&method, szVarPrefix, GUICookie);
+ dwScopeZOrder++;
+ daScope[i].dwZOrder = dwScopeZOrder;
+ if(PC > daScope[i].dwStart)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,COMMENT("%s// PDB ERROR: scope start (0x%8.8X) is not opcode-aligned"),
+ g_szAsmCodeIndent,daScope[i].dwStart);
+ printLine(GUICookie,szString);
+ }
+ } // end if(daScope[i].Covers(PC))
+ } // end if(daScope[i].IsOpen()) -- else
+ } // end if(daScope[i].pISymScope != pRootScope)
+ } // end for(i=0; i < ulScopes; i++)
+ } // end if(ulScopes)
+
+#if defined(_DEBUG)
+ if (g_fPrettyPrint && &pCode[PC] >= curFormat) {
+ formatOut.clear();
+ curFormat = ilFormatter.formatStatement(curFormat, &formatOut);
+ char* ptr = const_cast<char*>(formatOut.val());
+ do {
+ char* newLine = strchr(ptr, '\n');
+ if (newLine)
+ *newLine++ = 0;
+ line.clear();
+ line << COMMENT((char*)0)<<"// **** " << ptr<<COMMENT((char*)-1);
+ printLine(GUICookie, const_cast<char*>(line.val()));
+ ptr = newLine;
+ } while (ptr != 0 && *ptr != 0);
+ }
+#endif
+
+ szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%sIL_%04x: ",g_szAsmCodeIndent, PC);
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s/* ",COMMENT((char*)0));
+ for(i=0; i<Len; i++) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%2.2X",pCode[PC+i]);
+ for(; i<2; i++) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," "); // 2 is max.opcode length
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," | ");
+ }
+
+ PC += Len;
+ Len = 0;
+
+ const char *pszInstrName = KEYWORD(OpcodeInfo[instr].pszName);
+
+ switch (OpcodeInfo[instr].Type)
+ {
+ DWORD tk;
+ DWORD tkType;
+ default:
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),RstrUTF(IDS_E_INSTRTYPE),
+ OpcodeInfo[instr].Type,instr);
+ printLine(GUICookie, szString);
+ return FALSE;
+ }
+
+#define PadTheString { if(Len < 16) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-*s", (16-Len), ""); \
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," */%s ",COMMENT((char*)-1)); }
+
+ case InlineNone:
+ {
+ if(g_fShowBytes)
+ PadTheString;
+
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), pszInstrName);
+
+ switch (instr)
+ {
+ case CEE_RET:
+ case CEE_THROW:
+ fNeedNewLine = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ break;
+ }
+
+ case ShortInlineI:
+ case ShortInlineVar:
+ {
+ unsigned char ch= pCode[PC];
+ short sh = OpcodeInfo[instr].Type==ShortInlineVar ? ch : (ch > 127 ? -(256-ch) : ch);
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X ", ch);
+ Len += 3;
+ PadTheString;
+ }
+ switch(instr)
+ {
+ case CEE_LDARG_S:
+ case CEE_LDARGA_S:
+ case CEE_STARG_S:
+ if(g_fThisIsInstanceMethod &&(ch==0))
+ { // instance methods have arg0="this", do not label it!
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %d", pszInstrName, ch);
+ }
+ else
+ {
+ if(pszArgname)
+ {
+ unsigned char ch1 = g_fThisIsInstanceMethod ? ch-1 : ch;
+ if(ch1 < ulArgs)
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%-10s %s",pszInstrName,
+ ProperLocalName(pszArgname[ch1].name));
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(RstrUTF(IDS_E_ARGINDEX)),pszInstrName, ch,ulArgs);
+ }
+ else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s A_%d",pszInstrName, ch);
+ }
+ break;
+
+ case CEE_LDLOC_S:
+ case CEE_LDLOCA_S:
+ case CEE_STLOC_S:
+ if(pszLVname)
+ {
+ if(ch < ulVars) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %s", pszInstrName,
+ ProperLocalName(pszLVname[ch].name));
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(RstrUTF(IDS_E_LVINDEX)),pszInstrName, ch, ulVars);
+ }
+ else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s V_%d",pszInstrName, ch);
+ break;
+
+ default:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %d", pszInstrName,sh);
+ }
+
+ PC++;
+ break;
+ }
+
+ case InlineVar:
+ {
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X ", pCode[PC], pCode[PC+1]);
+ Len += 5;
+ PadTheString;
+ }
+
+ USHORT v = pCode[PC] + (pCode[PC+1] << 8);
+ long l = OpcodeInfo[instr].Type==InlineVar ? v : (v > 0x7FFF ? -(0x10000 - v) : v);
+
+ switch(instr)
+ {
+ case CEE_LDARGA:
+ case CEE_LDARG:
+ case CEE_STARG:
+ if(g_fThisIsInstanceMethod &&(v==0))
+ { // instance methods have arg0="this", do not label it!
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %d", pszInstrName, v);
+ }
+ else
+ {
+ if(pszArgname)
+ {
+ USHORT v1 = g_fThisIsInstanceMethod ? v-1 : v;
+ if(v1 < ulArgs)
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%-10s %s",pszInstrName,
+ ProperLocalName(pszArgname[v1].name));
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(RstrUTF(IDS_E_ARGINDEX)),pszInstrName, v,ulArgs);
+ }
+ else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s A_%d",pszInstrName, v);
+ }
+ break;
+
+ case CEE_LDLOCA:
+ case CEE_LDLOC:
+ case CEE_STLOC:
+ if(pszLVname)
+ {
+ if(v < ulVars) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %s", pszInstrName,
+ ProperLocalName(pszLVname[v].name));
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(RstrUTF(IDS_E_LVINDEX)),pszInstrName, v,ulVars);
+ }
+ else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s V_%d",pszInstrName, v);
+ break;
+
+ default:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %d", pszInstrName, l);
+ break;
+ }
+ PC += 2;
+ break;
+ }
+
+ case InlineI:
+ case InlineRVA:
+ {
+ DWORD v = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X%2.2X%2.2X ", pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
+ Len += 9;
+ PadTheString;
+ }
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s 0x%x", pszInstrName, v);
+ PC += 4;
+ break;
+ }
+
+ case InlineI8:
+ {
+ __int64 v = (__int64) pCode[PC] +
+ (((__int64) pCode[PC+1]) << 8) +
+ (((__int64) pCode[PC+2]) << 16) +
+ (((__int64) pCode[PC+3]) << 24) +
+ (((__int64) pCode[PC+4]) << 32) +
+ (((__int64) pCode[PC+5]) << 40) +
+ (((__int64) pCode[PC+6]) << 48) +
+ (((__int64) pCode[PC+7]) << 56);
+
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),
+ "%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
+ pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3],
+ pCode[PC+4], pCode[PC+5], pCode[PC+6], pCode[PC+7]);
+ Len += 8*2;
+ PadTheString;
+ }
+
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s 0x%I64x", pszInstrName, v);
+ PC += 8;
+ break;
+ }
+
+ case ShortInlineR:
+ {
+ __int32 v = (__int32) pCode[PC] +
+ (((__int32) pCode[PC+1]) << 8) +
+ (((__int32) pCode[PC+2]) << 16) +
+ (((__int32) pCode[PC+3]) << 24);
+
+ float f = (float&)v;
+
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X%2.2X%2.2X ", pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
+ Len += 9;
+ PadTheString;
+ }
+
+ char szf[32];
+ if(f==0.0)
+ strcpy_s(szf,32,((v>>24)==0)? "0.0" : "-0.0");
+ else
+ _gcvt_s(szf,32,(double)f, 8);
+ float fd = (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(((__int32&)fd == v)&&(strchr(szf,'#') == NULL))
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %s", pszInstrName, szf);
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s (%2.2X %2.2X %2.2X %2.2X)",
+ pszInstrName, pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
+ PC += 4;
+ break;
+ }
+
+ case InlineR:
+ {
+ __int64 v = (__int64) pCode[PC] +
+ (((__int64) pCode[PC+1]) << 8) +
+ (((__int64) pCode[PC+2]) << 16) +
+ (((__int64) pCode[PC+3]) << 24) +
+ (((__int64) pCode[PC+4]) << 32) +
+ (((__int64) pCode[PC+5]) << 40) +
+ (((__int64) pCode[PC+6]) << 48) +
+ (((__int64) pCode[PC+7]) << 56);
+
+ double d = (double&)v;
+
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),
+ "%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
+ pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3],
+ pCode[PC+4], pCode[PC+5], pCode[PC+6], pCode[PC+7]);
+ Len += 8*2;
+ PadTheString;
+ }
+ char szf[32],*pch;
+ if(d==0.0)
+ strcpy_s(szf,32,((v>>56)==0)? "0.0" : "-0.0");
+ else
+ _gcvt_s(szf,32,d, 17);
+ double df = strtod(szf, &pch); //atof(szf);
+ // 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(((__int64&)df == v)&&(strchr(szf,'#') == NULL))
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %s", pszInstrName, szf);
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s (%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X)",
+ pszInstrName, pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3],
+ pCode[PC+4], pCode[PC+5], pCode[PC+6], pCode[PC+7]);
+ PC += 8;
+ break;
+ }
+
+ case ShortInlineBrTarget:
+ {
+ char offset = (char) pCode[PC];
+ long dest = (PC + 1) + (long) offset;
+
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X ", pCode[PC]);
+ Len += 3;
+ PadTheString;
+ }
+ PC++;
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s IL_%04x", pszInstrName, dest);
+
+ fNeedNewLine = TRUE;
+ break;
+ }
+
+ case InlineBrTarget:
+ {
+ long offset = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);
+ long dest = (PC + 4) + (long) offset;
+
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X%2.2X%2.2X ", pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
+ Len += 9;
+ PadTheString;
+ }
+ PC += 4;
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s IL_%04x", pszInstrName, dest);
+
+ fNeedNewLine = TRUE;
+ break;
+ }
+
+ case InlineSwitch:
+ {
+ DWORD cases = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);
+
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X%2.2X%2.2X ", pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
+ Len += 9;
+ PadTheString;
+ }
+ if(cases) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s ( ", pszInstrName);
+ else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s ( )", pszInstrName);
+ printLine(GUICookie, szString);
+ PC += 4;
+ DWORD PC_nextInstr = PC + 4 * cases;
+ for (i = 0; i < cases; i++)
+ {
+ long offset = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);
+ long dest = PC_nextInstr + (long) offset;
+ szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s ",g_szAsmCodeIndent); //indent+label
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"/* | %2.2X%2.2X%2.2X%2.2X ", // comment
+ pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
+ Len = 9;
+ PadTheString;
+ }
+
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," IL_%04x%s", dest,(i == cases-1)? ")" : ",");
+ PC += 4;
+ printLine(GUICookie, szString);
+ }
+ continue;
+ }
+
+ case InlinePhi:
+ {
+ DWORD cases = pCode[PC];
+ unsigned short *pus;
+ DWORD i;
+
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X", cases);
+ Len += 2;
+ for(i=0; i < cases*2; i++)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X", pCode[PC+1+i]);
+ Len += 2;
+ }
+ PadTheString;
+ }
+
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s", pszInstrName);
+ for(i=0, pus=(unsigned short *)(&pCode[PC+1]); i < cases; i++,pus++)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %d",*pus);
+ }
+ PC += 2 * cases + 1;
+ break;
+ }
+
+ case InlineString:
+ case InlineField:
+ case InlineType:
+ case InlineTok:
+ case InlineMethod:
+ {
+ tk = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);
+ tkType = TypeFromToken(tk);
+
+ // Backwards compatible ldstr instruction.
+ if (instr == CEE_LDSTR && TypeFromToken(tk) != mdtString)
+ {
+ WCHAR *v1 = L"";
+
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X%2.2X%2.2X ",
+ pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
+ Len += 9;
+ PadTheString;
+ }
+
+ if(!g_pPELoader->getVAforRVA(tk, (void**) &v1))
+ {
+ char szStr[256];
+ sprintf_s(szStr,256,RstrUTF(IDS_E_SECTHEADER),tk);
+ printLine(GUICookie,szStr);
+ }
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s ", pszInstrName);
+ ConvToLiteral(szptr, v1, 0xFFFF);
+ PC += 4;
+ break;
+ }
+
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "(%2.2X)%2.2X%2.2X%2.2X ",
+ pCode[PC+3], pCode[PC+2], pCode[PC+1], pCode[PC]);
+ Len += 11;
+ PadTheString;
+ }
+ PC += 4;
+
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s ", pszInstrName);
+
+ if ((tk & 0xFF000000) == 0)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%#x ", tk);
+ break;
+ }
+ if(!pImport->IsValidToken(tk))
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(" [ERROR: INVALID TOKEN 0x%8.8X] "),tk);
+ break;
+ }
+ if(OpcodeInfo[instr].Type== InlineTok)
+ {
+ switch (tkType)
+ {
+ default:
+ break;
+
+ case mdtMethodDef:
+ case mdtMethodSpec:
+ 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(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;
+ }
+ }
+ }
+ PrettyPrintToken(szString, tk, pImport,GUICookie,FuncToken); //TypeDef,TypeRef,TypeSpec,MethodDef,FieldDef,MemberRef,MethodSpec,String
+ break;
+ }
+
+ case InlineSig:
+ {
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X%2.2X%2.2X ",
+ pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
+ // output the offset and the raw bytes
+ Len += 9;
+ PadTheString;
+ }
+
+ // get the signature token
+ tk = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);
+ PC += 4;
+ tkType = TypeFromToken(tk);
+ if (tkType == mdtSignature)
+ {
+ // get the signature from the token
+ DWORD cbSigLen;
+ PCCOR_SIGNATURE pComSig;
+ CQuickBytes qbMemberSig;
+ if (FAILED(pImport->GetSigFromToken(tk, &cbSigLen, &pComSig)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, COMMENT("// ERROR: Invalid %08X record"), tk);
+ break;
+ }
+
+ qbMemberSig.Shrink(0);
+ const char* pszTailSig = PrettyPrintSig(pComSig, cbSigLen, "", &qbMemberSig, pImport,NULL);
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %s", pszInstrName, pszTailSig);
+ if (g_fDumpTokens)
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT(" /*%08X*/"),tk);
+ }
+ else
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), ERRORMSG(RstrUTF(IDS_E_BADTOKENTYPE)), pszInstrName, tk);
+ }
+ break;
+ }
+ }
+
+ printLine(GUICookie, szString);
+ } // end while (PC < method.CodeSize)
+
+ // We've finished looping over all the instructions,
+ // Close of anything that may still be open
+ // First, dump any remaining EH regions
+ if(g_ehCount)
+ {
+ g_tkRefUser = FuncToken;
+ DWORD i;
+ if(fTryInCode)
+ {
+ for (DWORD ii = g_ehCount; ii > 0; ii--)
+ {
+ i = g_ehCount - ii;
+ DWORD theEnd = g_ehInfo[i].GetHandlerOffset()+g_ehInfo[i].GetHandlerLength();
+ if(g_ehInfo[i].GetFlags() & PUT_INTO_CODE)
+ {
+ if(PC == theEnd)
+ {
+ // reduce indent, close }
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,UNSCOPE(),COMMENT("// end handler"));
+ printLine(GUICookie,szString);
+ if(g_fShowBytes)
+ DumpHexEHInfo(&g_ehInfo[i], GUICookie);
+ g_ehInfo[i].SetTryOffset(0xFF000000);
+ g_ehInfo[i].SetHandlerOffset(0xFF000000);
+ }
+ }
+ }
+ //dumpOneEHInfo(ehInfoToPutNext,pImport,GUICookie); //doesn't do anything if ehInfoToPutNext == NULL
+ }
+ bool fMoreToDisplay = false;
+ for (i = 0; i < g_ehCount && !fMoreToDisplay; i++)
+ fMoreToDisplay = !(g_ehInfo[i].GetTryOffset() == 0xFF000000 && g_ehInfo[i].GetHandlerOffset() == 0xFF000000);
+ if (fMoreToDisplay)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%sIL_%04x: ",g_szAsmCodeIndent, method.GetCodeSize()); //add dummy label
+ printLine(GUICookie, szString);
+ dumpEHInfo(pImport,GUICookie);
+ }
+ g_tkRefUser = 0;
+ }
+ //----------------- lexical scope handling -----------------------------
+ if(ulScopes) // non-zero only if local var info present
+ {
+ for(unsigned i=0; i < ulScopes; i++)
+ {
+ if(daScope[i].pISymScope != pRootScope)
+ {
+ if((daScope[i].dwZOrder > 0)&&(PC >= daScope[i].dwEnd))
+ {
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
+ printLine(GUICookie,szString);
+ daScope[i].dwZOrder = 0;
+ dwScopeZOrder--;
+ if(PC > daScope[i].dwEnd)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,COMMENT("%s// PDB ERROR: scope end (0x%8.8X) is not opcode-aligned"),
+ g_szAsmCodeIndent,daScope[i].dwEnd);
+ printLine(GUICookie,szString);
+ }
+ }
+ }
+ daScope[i].pISymScope->Release();
+ }
+ }
+ if(dwScopeZOrder != 0)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,COMMENT("%s// PDB ERROR: %d unclosed lexical scopes, forcing closure."),
+ g_szAsmCodeIndent,dwScopeZOrder);
+ printLine(GUICookie,szString);
+ for(DWORD i=0; i < dwScopeZOrder; i++)
+ {
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
+ printLine(GUICookie,szString);
+ }
+ }
+ if(pSymMethod) pSymMethod->Release();
+ if(LineCode) VDELETE(LineCode);
+ if(pszLVname)
+ {
+ for(ULONG i = 0; i < ulVars; i++) SDELETE(pszLVname[i].name);
+ VDELETE(pszLVname);
+ }
+// dumpEHInfo(pImport, GUICookie);
+
+ return TRUE;
+}
+#ifdef _PREFAST_
+#pragma warning(pop)
+#endif
+
+void SplitSignatureByCommas(__inout __nullterminated char* szString,
+ __inout __nullterminated char* pszTailSig,
+ mdToken tk,
+ size_t indent,
+ void* GUICookie)
+{
+ char chAfterComma;
+ char *pComma, *pch;
+ size_t i,j,k,l;
+ if(indent < strlen(pszTailSig))
+ {
+ pComma = pszTailSig+indent;
+ while((pComma = strchr(pComma,',')) != NULL)
+ {
+ for(pch = pszTailSig, i=0,j=0,k=0,l=0; pch < pComma; pch++)
+ {
+ if(*pch == '\'') j=1-j;
+ else if(j==0)
+ {
+ if(*pch == '[') i++;
+ else if(*pch == ']') i--;
+ else if(*pch == '(') k++;
+ else if(*pch == ')') k--;
+ 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<=1)&&(l==0)) // no brackets or all opened/closed
+ {
+ chAfterComma = *pComma;
+ *pComma = 0;
+ printLine(GUICookie,pszTailSig);
+ *pComma = chAfterComma;
+ strcpy_s(pszTailSig,strlen(g_szAsmCodeIndent)+1,g_szAsmCodeIndent);
+ for(i=(ULONG32)strlen(g_szAsmCodeIndent); i<indent; i++) pszTailSig[i] = ' ';
+ strcpy_s(&pszTailSig[indent],strlen(pComma)+1,pComma);
+ pComma = pszTailSig;
+ }
+ }
+ }
+ pch = szString;
+ pch+=sprintf_s(pch,SZSTRING_SIZE,"%s",pszTailSig);
+ if(g_fDumpTokens)
+ pch+=sprintf_s(pch,SZSTRING_REMAINING_SIZE(pch),COMMENT(" /* %08X */"),tk);
+}
+
+//#define TOKEN_SIG
+#ifdef TOKEN_SIG
+struct TokenSig
+{
+ size_t indent;
+ char* str;
+ TokenSig() { indent = 0; str = NULL; };
+ ~TokenSig() { if(str) VDELETE(str); };
+};
+struct TokenSigArray
+{
+ TokenSig* ptsArray;
+ ULONG ulCount;
+ mdToken tkType;
+ TokenSigArray(mdToken tk, IMDInternalImport *pImport)
+ {
+ HENUMInternal hEnum;
+ pImport->EnumAllInit(tk,&hEnum);
+ ulCount=pImport->EnumGetCount(&hEnum)+1;
+ pImport->EnumClose(&hEnum);
+ ptsArray = new TokenSig[ulCount];
+ tkType = tk;
+ };
+ ~TokenSigArray()
+ {
+ VDELETE(ptsArray);
+ }
+};
+
+TokenSigArray *TSA_TD = NULL;
+TokenSigArray *TSA_TR = NULL;
+TokenSigArray *TSA_TS = NULL;
+TokenSigArray *TSA_AR = NULL;
+TokenSigArray *TSA_MR = NULL;
+TokenSigArray *TSA_FD = NULL;
+TokenSigArray *TSA_MD = NULL;
+TokenSigArray *TSA_ME = NULL;
+TokenSigArray *TSA_MS = NULL;
+
+#endif
+void TokenSigInit(IMDInternalImport *pImport)
+{
+#ifdef TOKEN_SIG
+ TSA_TD = new TokenSigArray(mdtTypeDef,pImport);
+ TSA_TR = new TokenSigArray(mdtTypeRef,pImport);
+ TSA_TS = new TokenSigArray(mdtTypeSpec,pImport);
+ TSA_AR = new TokenSigArray(mdtAssemblyRef,pImport);
+ TSA_MR = new TokenSigArray(mdtModuleRef,pImport);
+ TSA_FD = new TokenSigArray(mdtFieldDef,pImport);
+ TSA_MD = new TokenSigArray(mdtMethodDef,pImport);
+ TSA_ME = new TokenSigArray(mdtMemberRef,pImport);
+ TSA_MS = new TokenSigArray(mdtMethodSpec,pImport);
+#endif
+}
+void TokenSigDelete()
+{
+#ifdef TOKEN_SIG
+ SDELETE(TSA_TD);
+ SDELETE(TSA_TR);
+ SDELETE(TSA_TS);
+ SDELETE(TSA_AR);
+ SDELETE(TSA_MR);
+ SDELETE(TSA_FD);
+ SDELETE(TSA_MD);
+ SDELETE(TSA_ME);
+ SDELETE(TSA_MS);
+#endif
+}
+
+// Returns S_OK as TRUE or S_FALSE as FALSE or error code
+HRESULT
+IsGenericInst(mdToken tk, IMDInternalImport *pImport)
+{
+ HRESULT hr;
+ if (TypeFromToken(tk) == mdtTypeSpec)
+ {
+ if (pImport->IsValidToken(tk))
+ {
+ ULONG cSig;
+ PCCOR_SIGNATURE sig;
+ IfFailRet(pImport->GetSigFromToken(tk, &cSig, &sig));
+
+ PCCOR_SIGNATURE sigEnd = sig + cSig;
+ while (sig < sigEnd)
+ {
+ unsigned t = (unsigned)*sig;
+ switch (t)
+ {
+ case ELEMENT_TYPE_PTR:
+ case ELEMENT_TYPE_SZARRAY:
+ case ELEMENT_TYPE_ARRAY:
+ case ELEMENT_TYPE_BYREF:
+ sig++;
+ break;
+ default:
+ {
+ if (*sig == ELEMENT_TYPE_GENERICINST)
+ {
+ return S_OK;
+ }
+ else
+ {
+ return S_FALSE;
+ }
+ }
+ }
+ }
+ }
+ }
+ return S_FALSE;
+}
+
+char* PrettyPrintMemberRef(__inout __nullterminated char* szString, mdToken tk, PCCOR_SIGNATURE pInstSig, ULONG cInstSig,
+ IMDInternalImport *pImport, void* GUICookie, size_t* pIndent,
+ CQuickBytes *pqbMemberSig)
+{
+ HRESULT hr;
+ mdTypeRef cr;
+ const char * pszMemberName;
+ char* curPos;
+ char* pszTailSig;
+ char* pszOffset;
+ PCCOR_SIGNATURE pComSig;
+ ULONG cComSig;
+ size_t L, indent;
+ mdToken tkVarOwner = g_tkVarOwner;
+ DWORD dwAttrs=0xFFFFFFFF; // used only if Parent==MethodDef
+ mdToken tkMethodDef = 0; // used only if Parent==MethodDef
+
+ L = strlen(szString);
+
+ if (FAILED(pImport->GetNameAndSigOfMemberRef(
+ tk,
+ &pComSig,
+ &cComSig,
+ &pszMemberName)))
+ {
+ pComSig = NULL;
+ cComSig = 0;
+ pszMemberName = "Invalid MemberRef record";
+ }
+ MAKE_NAME_IF_NONE(pszMemberName,tk);
+
+ curPos = &szString[L+1];
+ *curPos = 0;
+ if (FAILED(pImport->GetParentOfMemberRef(tk, &cr)))
+ {
+ curPos += sprintf_s(curPos, SZSTRING_REMAINING_SIZE(curPos), "Invalid MemberRef %08X record", tk);
+ cr = mdTypeRefNil;
+ }
+ if (TypeFromToken(cr) == mdtMethodDef) //get the parent's parent
+ {
+ if (FAILED(pImport->GetMethodDefProps(cr, &dwAttrs)))
+ {
+ curPos += sprintf_s(curPos, SZSTRING_REMAINING_SIZE(curPos), "Invalid MethodDef %08X record", cr);
+ }
+ tkMethodDef = cr;
+
+ mdTypeRef cr1;
+ if(FAILED(pImport->GetParentToken(cr,&cr1))) cr1 = mdTypeRefNil;
+ cr = cr1;
+ }
+ pqbMemberSig->Shrink(0);
+ if (RidFromToken(cr)&&(cr != 0x02000001))
+ {
+ const char* pszClass = PrettyPrintClass(pqbMemberSig,cr,pImport);
+ sprintf_s(curPos,SZSTRING_REMAINING_SIZE(curPos),"%s::",pszClass);
+ pqbMemberSig->Shrink(0);
+
+ hr = IsGenericInst(cr,pImport);
+ if (FAILED(hr))
+ {
+ sprintf_s(curPos, SZSTRING_REMAINING_SIZE(curPos), "Invalid token %08X record", cr);
+ }
+ if (hr == S_OK)
+ {
+ g_tkVarOwner = 0;
+ }
+ }
+ {
+ char* curPos1 = &curPos[strlen(curPos)];
+ if (IsMdPrivateScope(dwAttrs))
+ {
+ sprintf_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),"%s$PST%08X",pszMemberName,tkMethodDef);
+ }
+ else
+ {
+ strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),pszMemberName);
+ }
+ if (tkMethodDef != 0)
+ {
+ strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),JUMPPT(ProperName(curPos1),tkMethodDef));
+ }
+ else
+ {
+ strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),ProperName(curPos1));
+ }
+ }
+
+ appendStr(pqbMemberSig, szString);
+ if (pInstSig != NULL)
+ {
+ CQuickBytes qbInstSig;
+ qbInstSig.Shrink(0);
+ PrettyPrintSig(pInstSig, cInstSig, curPos, &qbInstSig, pImport, NULL);
+ strcat_s(curPos,SZSTRING_REMAINING_SIZE(curPos), (char*) qbInstSig.Ptr());
+ }
+ pszTailSig = (char*)PrettyPrintSig(pComSig, cComSig, curPos, pqbMemberSig, pImport,NULL,(pInstSig==NULL));
+ pszOffset = strstr(pszTailSig,curPos);
+ indent = pszOffset - pszTailSig + strlen(curPos) + 1;
+ if(pIndent) *pIndent = indent;
+ g_tkVarOwner = tkVarOwner;
+ return pszTailSig;
+}
+
+char* PrettyPrintMethodDef(__inout __nullterminated char* szString, mdToken tk, PCCOR_SIGNATURE pInstSig, ULONG cInstSig,
+ IMDInternalImport *pImport,void* GUICookie, size_t* pIndent,
+ CQuickBytes *pqbMemberSig)
+{
+ HRESULT hr;
+ mdTypeRef cr;
+ const char * pszMemberName;
+ char* curPos;
+ char* pszTailSig;
+ char* pszOffset;
+ DWORD dwAttrs;
+ PCCOR_SIGNATURE pComSig;
+ ULONG cComSig;
+ size_t L, indent;
+ mdToken tkVarOwner = g_tkVarOwner;
+
+ L = strlen(szString);
+ if (FAILED(pImport->GetNameOfMethodDef(tk, &pszMemberName)))
+ {
+ pszMemberName = "Invalid MethodDef record";
+ }
+ MAKE_NAME_IF_NONE(pszMemberName,tk);
+ if (FAILED(pImport->GetMethodDefProps(tk, &dwAttrs)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "Invalid MethodDef %08X record", tk);
+ return szString;
+ }
+
+ if (FAILED(pImport->GetSigOfMethodDef(tk, &cComSig, &pComSig)))
+ {
+ cComSig = 0;
+ pComSig = NULL;
+ }
+
+ hr = pImport->GetParentToken(
+ tk,
+ &cr
+ );
+ if (FAILED(hr))
+ {
+ strcat_s(szString, SZSTRING_SIZE, "??");
+ return szString;
+ }
+ // use the tail as a buffer
+ curPos = &szString[L+1];
+ *curPos=0;
+ pqbMemberSig->Shrink(0);
+ if(RidFromToken(cr)&&(cr != 0x02000001))
+ {
+ const char* pszClass = PrettyPrintClass(pqbMemberSig,cr,pImport);
+ sprintf_s(curPos,SZSTRING_REMAINING_SIZE(curPos),"%s::",pszClass);
+ pqbMemberSig->Shrink(0);
+
+ hr = IsGenericInst(cr,pImport);
+ if (FAILED(hr))
+ {
+ sprintf_s(curPos, SZSTRING_REMAINING_SIZE(curPos), "/*Invalid token %08X record*/", cr);
+ }
+ if (hr == S_OK)
+ {
+ g_tkVarOwner = 0;
+ }
+ }
+ {
+ char* curPos1 = &curPos[strlen(curPos)];
+ if(IsMdPrivateScope(dwAttrs))
+ sprintf_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),"%s$PST%08X",pszMemberName,tk);
+ else
+ strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),pszMemberName);
+ strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),JUMPPT(ProperName(curPos1),tk));
+ }
+ appendStr(pqbMemberSig, szString);
+ if (pInstSig)
+ {
+ CQuickBytes qbInstSig;
+ qbInstSig.Shrink(0);
+ pszTailSig = (char*)PrettyPrintSig(pInstSig, cInstSig, curPos, &qbInstSig, pImport, NULL);
+ strcat_s(curPos,SZSTRING_REMAINING_SIZE(curPos), (char*) qbInstSig.Ptr());
+ }
+
+ pszTailSig = (char*)PrettyPrintSig(pComSig, cComSig, curPos, pqbMemberSig, pImport, NULL, (pInstSig == NULL));
+ pszOffset = strstr(pszTailSig,curPos);
+ indent = pszOffset - pszTailSig + strlen(curPos) + 1;
+ if(pIndent) *pIndent = indent;
+ g_tkVarOwner = tkVarOwner;
+ return pszTailSig;
+}
+
+void PrettyPrintTokenWithSplit(__inout __nullterminated char* szString, mdToken tk, IMDInternalImport *pImport, void* GUICookie)
+{
+ CQuickBytes qbMemberSig;
+ char* pszTailSig = NULL;
+ size_t L, indent;
+
+ L = strlen(szString);
+
+#ifdef TOKEN_SIG
+ TokenSig* SigToken=NULL;
+ switch(TypeFromToken(tk))
+ {
+ case mdtMethodDef: SigToken = TSA_MD->ptsArray; break;
+ case mdtMethodSpec: SigToken = TSA_MS->ptsArray; break;
+ case mdtMemberRef: SigToken = TSA_ME->ptsArray; break;
+ default: return; // other token types aren't served
+ }
+ if(SigToken[RidFromToken(tk)].str)
+ {
+ qbMemberSig.Shrink(0);
+ appendStr(&qbMemberSig, szString);
+ appendStr(&qbMemberSig, SigToken[RidFromToken(tk)].str);
+ pszTailSig = asString(&qbMemberSig);
+ indent = SigToken[RidFromToken(tk)].indent + L;
+ }
+ else
+#endif
+ {
+ switch(TypeFromToken(tk))
+ {
+ case mdtMethodDef:
+ pszTailSig = PrettyPrintMethodDef(szString,tk,NULL,0,pImport,GUICookie,&indent,&qbMemberSig);
+ break;
+ case mdtMemberRef:
+ pszTailSig = PrettyPrintMemberRef(szString,tk,NULL,0,pImport,GUICookie,&indent,&qbMemberSig);
+ break;
+ case mdtMethodSpec:
+ {
+ mdToken meth=0;
+ PCCOR_SIGNATURE pSig=NULL;
+ ULONG cSig=0;
+ mdToken tkMVarOwner = g_tkMVarOwner;
+ g_tkMVarOwner = 0;
+ if (FAILED(pImport->GetMethodSpecProps(tk, &meth, &pSig, &cSig)))
+ {
+ return;
+ }
+ pszTailSig = (TypeFromToken(meth) == mdtMethodDef) ?
+ PrettyPrintMethodDef(szString,meth,pSig,cSig,pImport,GUICookie,&indent,&qbMemberSig) :
+ PrettyPrintMemberRef(szString,meth,pSig,cSig,pImport,GUICookie,&indent,&qbMemberSig);
+ g_tkMVarOwner = tkMVarOwner;
+ }
+ break;
+ default:
+ return;
+ }
+
+#ifdef TOKEN_SIG
+ SigToken[RidFromToken(tk)].str = new char[strlen(pszTailSig+L)+1];
+ if(SigToken[RidFromToken(tk)].str)
+ {
+ strcpy_s(SigToken[RidFromToken(tk)].str,strlen(pszTailSig+L)+1,pszTailSig+L);
+ SigToken[RidFromToken(tk)].indent = indent - L;
+ }
+#endif
+ }
+ SplitSignatureByCommas(szString,pszTailSig,tk,indent,GUICookie);
+}
+
+void PrettyPrintToken(__inout __nullterminated char* szString, mdToken tk, IMDInternalImport *pImport,void* GUICookie, mdToken FuncToken)
+{
+#ifdef TOKEN_SIG
+
+ TokenSig* SigToken=NULL;
+
+#endif
+ char *szptr = &szString[strlen(szString)];
+ if(!pImport->IsValidToken(tk))
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), ERRORMSG("<invalid token 0x%8.8x>"), tk);
+ return;
+ }
+ mdToken tkType = TypeFromToken(tk);
+
+ DWORD ix;
+ for(ix = 0; ix < g_NumTypedefs; ix++)
+ {
+ if((*g_typedefs)[ix].tkTypeSpec == tk) break;
+ }
+ if(ix < g_NumTypedefs)
+ {
+ REGISTER_REF(FuncToken,tk);
+ strcpy_s(szptr,SZSTRING_REMAINING_SIZE(szptr),JUMPPT(ProperName((*g_typedefs)[ix].szName),(*g_typedefs)[ix].tkSelf));
+ return;
+ }
+
+#ifdef TOKEN_SIG
+ switch (tkType)
+ {
+ case mdtTypeDef: SigToken = TSA_TD->ptsArray; break;
+ case mdtTypeRef: SigToken = TSA_TR->ptsArray; break;
+ case mdtTypeSpec: SigToken = TSA_TS->ptsArray; break;
+ case mdtAssemblyRef: SigToken = TSA_AR->ptsArray; break;
+ case mdtModuleRef: SigToken = TSA_MR->ptsArray; break;
+ case mdtFieldDef: SigToken = TSA_FD->ptsArray; break;
+ default: SigToken = NULL; break;
+ }
+
+ if(SigToken && SigToken[RidFromToken(tk)].str)
+ {
+ REGISTER_REF(FuncToken,tk);
+ strcpy_s(szptr,SZSTRING_REMAINING_SIZE(szptr),SigToken[RidFromToken(tk)].str);
+ return;
+ }
+#endif
+ CQuickBytes out;
+ char* pszForTokenSig = NULL;
+
+ switch (tkType)
+ {
+ default:
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), ERRORMSG("<unknown token type 0x%02x>"), (BYTE) (tkType >> 24));
+ pszForTokenSig = NULL;
+ break;
+ }
+
+ case mdtTypeDef:
+ case mdtTypeRef:
+ case mdtTypeSpec:
+ case mdtAssemblyRef:
+ case mdtAssembly:
+ case mdtModuleRef:
+ case mdtModule:
+ {
+ REGISTER_REF(FuncToken,tk);
+ strcpy_s(szptr,SZSTRING_REMAINING_SIZE(szptr), PrettyPrintClass(&out, tk, pImport));
+ pszForTokenSig = szptr;
+ break;
+ }
+
+ case mdtMethodDef:
+ case mdtMemberRef:
+ PrettyPrintTokenWithSplit(szString,tk,pImport,GUICookie);
+ REGISTER_REF(FuncToken,tk);
+ break;
+
+ case mdtMethodSpec:
+ {
+ mdToken meth=0;
+ PCCOR_SIGNATURE pSig;
+ ULONG cSig;
+ if (FAILED(pImport->GetMethodSpecProps(tk, &meth, &pSig, &cSig)))
+ {
+ meth = mdTokenNil;
+ }
+ //g_tkMVarOwner = 0;
+ PrettyPrintTokenWithSplit(szString,tk,pImport,GUICookie);
+ REGISTER_REF(FuncToken,meth);
+ break;
+ }
+
+ case mdtFieldDef:
+ {
+ HRESULT hr;
+ mdTypeRef cr=0;
+ const char * pszMemberName;
+ CQuickBytes qbMemberSig;
+ DWORD dwAttrs;
+
+ PCCOR_SIGNATURE pComSig;
+ ULONG cComSig;
+
+ REGISTER_REF(FuncToken,tk);
+ if (FAILED(pImport->GetNameOfFieldDef(tk, &pszMemberName)))
+ {
+ strcat_s(szString, SZSTRING_SIZE, "??");
+ break;
+ }
+ MAKE_NAME_IF_NONE(pszMemberName,tk);
+ if (FAILED(pImport->GetFieldDefProps(tk, &dwAttrs)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "Invalid FieldDef %08X record", tk);
+ break;
+ }
+
+ if (FAILED(pImport->GetSigOfFieldDef(tk, &cComSig, &pComSig)) ||
+ FAILED(pImport->GetParentToken(tk, &cr)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "Invalid FieldDef %08X record", tk);
+ break;
+ }
+
+ // use the tail as a buffer
+ char* curPos = &szString[strlen(szString)+1];
+ *curPos = 0;
+ if((cr != 0x02000001) && RidFromToken(cr))
+ {
+ const char* pszClass = PrettyPrintClass(&out, cr, pImport);
+ REGISTER_REF(FuncToken,cr);
+ sprintf_s(curPos,SZSTRING_REMAINING_SIZE(curPos),"%s::", pszClass);
+ }
+ char* curPos1 = &curPos[strlen(curPos)];
+ if(IsFdPrivateScope(dwAttrs))
+ sprintf_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),"%s$PST%08X",pszMemberName,tk);
+ else
+ strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),pszMemberName);
+ strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),JUMPPT(ProperName(curPos1),tk));
+ qbMemberSig.Shrink(0);
+ strcpy_s(curPos-1,SZSTRING_REMAINING_SIZE(curPos), PrettyPrintSig(pComSig, cComSig, curPos, &qbMemberSig, pImport,NULL));
+ curPos1 = &curPos[strlen(curPos)];
+ if(g_fDumpTokens)
+ sprintf_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),COMMENT(" /* %08X */"),tk);
+ pszForTokenSig = szptr;
+ break;
+ }
+
+ case mdtString:
+ {
+ const WCHAR *pszString = NULL;
+ ULONG cbString = 0;
+ if (pImport->IsValidToken(tk))
+ {
+ if (FAILED(pImport->GetUserString(tk, &cbString, NULL, &pszString)))
+ {
+ pszString = NULL;
+ }
+ }
+ if (pszString != NULL)
+ {
+ DumpUnicodeString(GUICookie,szString,(WCHAR *)pszString,cbString, true);
+ }
+ else
+ {
+ sprintf_s(szString,SZSTRING_SIZE,ERRORMSG("INVALID TOKEN: 0x%8.8X"),tk);
+ }
+ if (g_fDumpTokens)
+ sprintf_s(&szString[strlen(szString)],SZSTRING_SIZE-strlen(szString),COMMENT(" /* %08X */"),tk);
+ break;
+ }
+ } //end switch(TypeFromToken(tk))
+
+#ifdef TOKEN_SIG
+ if(SigToken && pszForTokenSig)
+ {
+ unsigned N = RidFromToken(tk);
+ SigToken[N].str = new char[strlen(pszForTokenSig)+1];
+ if(SigToken[N].str)
+ strcpy_s(SigToken[N].str,strlen(pszForTokenSig)+1,pszForTokenSig);
+ }
+#endif
+}
+
+/* not const char * const because it gets sorted at runtime; arguably a bad time to sort it. */
+static const char* keyword[] = {
+#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) s,
+#define OPALIAS(alias_c, s, c) s,
+#include "opcode.def"
+#undef OPALIAS
+#undef OPDEF
+#define KYWD(name, sym, val) name,
+#include "il_kywd.h"
+#undef KYWD
+};
+static bool KywdNotSorted = TRUE;
+static char* szAllowedSymbols = "#_@$.";
+static char DisallowedStarting[256];
+static char DisallowedCont[256];
+
+struct Indx
+{
+ void* table[128];
+ Indx() { memset(table,0,sizeof(table)); };
+ ~Indx()
+ {
+ for(int i = 1; i < 128; i++) delete ((Indx*)(table[i]));
+ };
+ void IndexString(__in __nullterminated const char* psz, __out const char** pkywd)
+ {
+ int i = (int) *psz;
+ if(i == 0)
+ table[0] = pkywd;
+ else
+ {
+ _ASSERTE((i > 0)&&(i <= 127));
+ Indx* pInd = (Indx*)(table[i]);
+ if(pInd == NULL)
+ {
+ pInd = new Indx;
+ _ASSERTE(pInd);
+ table[i] = pInd;
+ }
+ pInd->IndexString(psz+1,pkywd);
+ }
+ }
+ const char** FindString(__in __nullterminated const char* psz)
+ {
+ if(*psz == 0)
+ return (const char**)(table[0]);
+ if(*psz > 0)
+ {
+ Indx* pInd = (Indx*)(table[(unsigned char)*psz]);
+ return (pInd == NULL) ? NULL : pInd->FindString(psz+1);
+ }
+ return NULL;
+ }
+};
+
+/********************************************************************************/
+/* looks up the keyword 'name' Returns FALSE on failure */
+bool IsNameToQuote(const char *name)
+{
+ BYTE* p;
+ BOOL bStarting;
+ static Indx* indx;
+
+ if (indx==NULL)
+ indx = new Indx();
+
+ if((name==NULL)||(*name==0)) return TRUE;
+
+ if(g_fQuoteAllNames)
+ return ((strcmp(name,COR_CTOR_METHOD_NAME)!=0) && (strcmp(name,COR_CCTOR_METHOD_NAME)!=0));
+
+ if(KywdNotSorted)
+ {
+ int j;
+ const char** const low = keyword;
+ const char** const high = &keyword[sizeof(keyword) / sizeof(*keyword)];
+ const char** mid;
+ // name must start with alpha or one of allowed chars: #_$@.
+ memset(DisallowedStarting,1,256);
+ for(p = (BYTE*)szAllowedSymbols; *p; DisallowedStarting[*p]=0,p++);
+ for(j='a'; j<= 'z'; DisallowedStarting[j]=0,j++);
+ for(j='A'; j<= 'Z'; DisallowedStarting[j]=0,j++);
+ // name must continue with the same chars, plus digits, and ? instead of #
+ memcpy(DisallowedCont,DisallowedStarting,256);
+ for(j='0'; j<= '9'; DisallowedCont[j]=0,j++);
+ DisallowedCont[(unsigned char)'#'] = 1;
+ DisallowedCont[(unsigned char)'?'] = 0;
+ DisallowedCont[(unsigned char)'`'] = 0;
+ // Sort the keywords for fast lookup
+ for(mid = low; mid < high; mid++)
+ {
+ indx->IndexString(*mid,mid);
+ }
+ KywdNotSorted = FALSE;
+ }
+ //first, check for forbidden characters
+ for(p = (BYTE*)name, bStarting = TRUE; *p; p++)
+ {
+ if(bStarting)
+ {
+ if(DisallowedStarting[*p]) return TRUE;
+ }
+ else
+ {
+ if(DisallowedCont[*p]) return TRUE;
+ }
+ bStarting = (*p == '.');
+ if(bStarting && (*(p+1) == '.')) return TRUE;
+ }
+
+ //second, check for matching keywords (remember: .ctor and .cctor are names AND keywords)
+ if(indx->FindString((char*)name))
+ {
+ return ((strcmp(name,COR_CTOR_METHOD_NAME)!=0) && (strcmp(name,COR_CCTOR_METHOD_NAME)!=0));
+ }
+ //third, check if the name starts or ends with dot (.ctor and .cctor are out of the way)
+ return ((*name == '.') || (name[strlen(name)-1] == '.'));
+}
+
+/* Returns true if this name requires a single quote to be properly displayed as a local */
+bool IsLocalToQuote(const char *name)
+{
+ // Anything that would otherwise require a quote gets a quote
+ if (IsNameToQuote(name))
+ return true;
+ // No such thing as an empty name that doesn't require quoting (handled in IsNameToQuote)
+ _ASSERTE(*name);
+ // return true if there's a '.' anywhere in the name, after position 1
+ return !!strchr(name + 1, '.');
+}
+
+/********************************************************************/
+/*
+ * This is currently unused, with all calls to it commented out. In
+ * the event that those calls return, add this function back.
+static char* ConvNumericEscape(char* retBuff, unsigned val) {
+ _ASSERTE(val < 256);
+
+ // print as octal
+ *retBuff++ = '\\';
+ *retBuff++ = (val >> 6) + '0';
+ *retBuff++ = ((val >> 3) & 7) + '0';
+ *retBuff++ = (val & 7) + '0';
+ return(retBuff);
+}
+ */
+
+/********************************************************************/
+/* returns the quoted version of a string (including the quotes) */
+
+static BOOL ConvToLiteral(__inout __nullterminated char* retBuff, const WCHAR* str, int cbString)
+{
+ BOOL ret = TRUE;
+ char* was_retBuff = retBuff;
+
+ *retBuff++ = '"';
+
+ for(int tally=0; (tally < cbString)&&ret; tally++)
+ {
+ if (*str > 255)
+ {
+ //retBuff = ConvNumericEscape(retBuff, *str >> 8);
+ //retBuff = ConvNumericEscape(retBuff, *str & 0xFF);
+ ret = FALSE;
+ }
+ else if(!isprint(*str))
+ {
+ if (*str == '\n')
+ {
+ *retBuff++ = '\\';
+ *retBuff++ = 'n';
+ }
+ else
+ //retBuff = ConvNumericEscape(retBuff, *str);
+ ret = FALSE;
+ }
+ else if (*str == '"')
+ {
+ *retBuff++ = '\\';
+ *retBuff++ = '"';
+ }
+ else if (*str == '\\')
+ {
+ *retBuff++ = '\\';
+ *retBuff++ = '\\';
+ }
+ else if (*str == '\t')
+ {
+ *retBuff++ = '\\';
+ *retBuff++ = 't';
+ }
+ else
+ *retBuff++ = (char) *str;
+ str++;
+ }
+ *retBuff++ = '"';
+ *retBuff++ = 0;
+ if(!ret) *was_retBuff = 0;
+ return ret;
+}
+
diff --git a/src/ildasm/dis.h b/src/ildasm/dis.h
new file mode 100644
index 0000000000..1f807af0af
--- /dev/null
+++ b/src/ildasm/dis.h
@@ -0,0 +1,154 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include "formattype.h"
+
+#define MAX_INTERFACES_IMPLEMENTED 256 // unused
+#define MAX_CLASSNAME_LENGTH 1024 // single global buffer size
+#define MAX_MEMBER_LENGTH 1024 // single global buffer size
+#define MAX_SIGNATURE_LENGTH 2048 // single global buffer size
+#define DESCR_SIZE 8 // unused
+
+#define MAX_FILENAME_LENGTH 2048 //256
+
+#define MODE_DUMP_ALL 0
+#define MODE_DUMP_CLASS 1
+#define MODE_DUMP_CLASS_METHOD 2
+#define MODE_DUMP_CLASS_METHOD_SIG 3
+#define MODE_GUI 4
+
+BOOL Disassemble(IMDInternalImport *pImport, BYTE *pCode, void *GUICookie, mdToken FuncToken, ParamDescriptor* pszArgname, ULONG ulArgs);
+BOOL Decompile(IMDInternalImport *pImport, BYTE *pCode);
+OPCODE DecodeOpcode(const BYTE *pCode, DWORD *pdwLen);
+struct LineCodeDescr
+{
+ ULONG Line;
+ ULONG Column;
+ ULONG LineEnd;
+ ULONG ColumnEnd;
+ ULONG PC;
+ ULONG_PTR FileToken;
+};
+
+void printLine(void* GUICookie, __in __nullterminated const char* string);
+void printLineW(void* GUICookie, __in __nullterminated const WCHAR* string);
+void printError(void* GUICookie, __in __nullterminated const char* string);
+
+char* AnsiToUtf(__in __nullterminated const char* sz);
+char* UnicodeToAnsi(__in __nullterminated const WCHAR* wz);
+char* UnicodeToUtf(__in __nullterminated const WCHAR* wz);
+WCHAR* UtfToUnicode(__in __nullterminated const char* sz);
+WCHAR* AnsiToUnicode(__in __nullterminated const char* sz);
+void GetInputFileFullPath();
+
+char* RstrUTF(unsigned id);
+WCHAR* RstrW(unsigned id);
+char* RstrANSI(unsigned id);
+
+
+BOOL DumpMethod(mdToken FuncToken, const char *pszClassName, DWORD dwEntryPointToken,void *GUICookie,BOOL DumpBody);
+BOOL DumpField(mdToken FuncToken, const char *pszClassName,void *GUICookie, BOOL DumpBody);
+BOOL DumpEvent(mdToken FuncToken, const char *pszClassName, DWORD dwClassAttrs, void *GUICookie, BOOL DumpBody);
+BOOL DumpProp(mdToken FuncToken, const char *pszClassName, DWORD dwClassAttrs, void *GUICookie, BOOL DumpBody);
+void dumpEHInfo(IMDInternalImport *pImport, void *GUICookie);
+BOOL DumpClass(mdTypeDef cl, DWORD dwEntryPointToken, void* GUICookie, ULONG WhatToDump);
+// WhatToDump: 0-title only; 1-pack,size and custom attrs; 2-everything
+BOOL GetClassLayout(mdTypeDef cl, ULONG* pulPackSize, ULONG* pulClassSize);
+void DumpCustomAttribute(mdCustomAttribute tkCA, void *GUICookie, bool bWithOwner);
+void DumpCustomAttributes(mdToken tkOwner, void *GUICookie);
+void DumpByteArray(__inout __nullterminated char* szString, const BYTE* pBlob, ULONG ulLen, void* GUICookie);
+char* DumpDataPtr(__inout __nullterminated char* buffer, DWORD ptr, DWORD size);
+
+void PrettyPrintToken(__inout __nullterminated char* szString, mdToken tk, IMDInternalImport *pImport,void* GUICookie,mdToken FuncToken); //TypeDef,TypeRef,TypeSpec,MethodDef,FieldDef,MemberRef,MethodSpec,String
+void DumpPermissions(mdToken tkOwner, void* GUICookie);
+void DumpHeader(IMAGE_COR20_HEADER *CORHeader, void* GUICookie);
+void DumpHeaderDetails(IMAGE_COR20_HEADER *CORHeader, void* GUICookie);
+void DumpMetaInfo(__in __nullterminated const WCHAR* pszFileName, __in_opt __nullterminated const char* pszObjFileName, void* GUICookie);
+void DumpStatistics(IMAGE_COR20_HEADER *CORHeader, void* GUICookie);
+BOOL DumpFile();
+void Cleanup();
+void CreateProgressBar(LONG lRange);
+BOOL ProgressStep();
+void DestroyProgressBar();
+char * DumpQString(void* GUICookie,
+ __in __nullterminated const char* szToDump,
+ __in __nullterminated const char* szPrefix,
+ unsigned uMaxLen);
+void DumpVtable(void* GUICookie);
+char* DumpUnicodeString(void* GUICookie,
+ __inout __nullterminated char* szString,
+ __in_ecount(cbString) WCHAR* pszString,
+ ULONG cbString,
+ bool SwapString = false);
+
+void TokenSigInit(IMDInternalImport *pImport);
+void TokenSigDelete();
+
+
+//---------------- see DMAN.CPP--------------------------------------------------
+struct LocalComTypeDescr
+{
+ mdExportedType tkComTypeTok;
+ mdTypeDef tkTypeDef;
+ mdToken tkImplementation;
+ WCHAR* wzName;
+ DWORD dwFlags;
+ LocalComTypeDescr() { wzName=NULL; };
+ ~LocalComTypeDescr() { if(wzName) SDELETE(wzName); };
+};
+
+struct MTokName
+{
+ mdFile tok;
+ WCHAR* name;
+ MTokName() { tok = 0; name = NULL; };
+ ~MTokName() { if(name) SDELETE(name); };
+};
+extern BOOL g_fPrettyPrint;
+extern MTokName* rExeloc;
+extern ULONG nExelocs;
+void DumpImplementation(mdToken tkImplementation,
+ DWORD dwOffset,
+ __inout __nullterminated char* szString,
+ void* GUICookie);
+void DumpComType(LocalComTypeDescr* pCTD,
+ __inout __nullterminated char* szString,
+ void* GUICookie);
+void DumpManifest(void* GUICookie);
+void DumpTypedefs(void* GUICookie);
+IMetaDataAssemblyImport* GetAssemblyImport(void* GUICookie);
+
+void DumpRTFPrefix(void* GUICookie, BOOL fFontDefault);
+void DumpRTFPostfix(void* GUICookie);
+
+//-------------------------------------------------------------------------------
+#define NEW_TRY_BLOCK 0x80000000
+#define PUT_INTO_CODE 0x40000000
+#define ERR_OUT_OF_CODE 0x20000000
+#define SEH_NEW_PUT_MASK (NEW_TRY_BLOCK | PUT_INTO_CODE | ERR_OUT_OF_CODE)
+//-------------------------------------------------------------------------------
+
+// As much as 2 * SZSTRING_SIZE seems to be needed for some corner cases. ILDasm is
+// unfortunately full of constants and artificial limits, and may produce invalid
+// output or overrun a buffer when fed with something unusual (like a type with
+// thousands of generic parameters). Fixing all such problems effectively means
+// rewriting the tool from scratch. Until this happens, let's at least try to keep it
+// working for reasonable input.
+#define UNIBUF_SIZE 262144
+extern WCHAR wzUniBuf[]; // defined in dis.cpp
+
+#define SZSTRING_SIZE 131072
+extern char szString[]; // defined in dis.cpp
+
+char *DumpGenericPars(__inout_ecount(SZSTRING_SIZE) char* szString,
+ mdToken tok,
+ void* GUICookie=NULL,
+ BOOL fSplit=FALSE);
+
+#include "safemath.h"
+#define SZSTRING_SIZE_M4 (SZSTRING_SIZE - 4)
+#define CHECK_REMAINING_SIZE if(ovadd_le((size_t)szString, SZSTRING_SIZE_M4, (size_t)szptr)) break;
+#define SZSTRING_REMAINING_SIZE(x) (ovadd_le((size_t)szString,SZSTRING_SIZE,(size_t)(x))?0:(SZSTRING_SIZE-((size_t)(x)-(size_t)szString)))
+
diff --git a/src/ildasm/dman.cpp b/src/ildasm/dman.cpp
new file mode 100644
index 0000000000..917d3f467a
--- /dev/null
+++ b/src/ildasm/dman.cpp
@@ -0,0 +1,1073 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+//
+// Assembly and Manifest Disassembler
+//
+#include "ildasmpch.h"
+
+#include "debugmacros.h"
+#include "corpriv.h"
+#include "dasmenum.hpp"
+#include "dasmgui.h"
+#include "formattype.h"
+#include "dis.h"
+#include "mlang.h"
+
+#include "ceeload.h"
+#include "dynamicarray.h"
+#include "resource.h"
+
+#include "clrinternal.h"
+
+extern IMAGE_COR20_HEADER * g_CORHeader;
+extern IMDInternalImport* g_pImport;
+extern PELoader * g_pPELoader;
+extern IMetaDataImport2* g_pPubImport;
+extern void * g_pMetaData;
+IMetaDataAssemblyImport* g_pAssemblyImport=NULL;
+extern BOOL g_fDumpAsmCode;
+extern char g_szAsmCodeIndent[];
+extern char g_szOutputFile[];
+extern BOOL g_fDumpTokens;
+extern DWORD g_Mode;
+extern FILE* g_pFile;
+extern LPCSTR* rAsmRefName; // decl. in formatType.cpp -- for AsmRef aliases
+extern ULONG ulNumAsmRefs; // decl. in formatType.cpp -- for AsmRef aliases
+extern unsigned g_uConsoleCP;
+MTokName* rFile = NULL;
+ULONG nFiles = 0;
+void DumpFiles(void* GUICookie)
+{
+ static mdFile rFileTok[4096];
+ HCORENUM hEnum=NULL;
+ if(rFile) { VDELETE(rFile); nFiles = 0; }
+ if(SUCCEEDED(g_pAssemblyImport->EnumFiles(&hEnum,rFileTok,4096,&nFiles)))
+ {
+ if(nFiles)
+ {
+ static WCHAR wzName[1024];
+ ULONG ulNameLen;
+ const void* pHashValue;
+ ULONG cbHashValue;
+ DWORD dwFlags;
+ char* szptr;
+ rFile = new MTokName[nFiles];
+ for(ULONG ix = 0; ix < nFiles; ix++)
+ {
+ pHashValue=NULL;
+ cbHashValue=0;
+ ulNameLen=0;
+ if(SUCCEEDED(g_pAssemblyImport->GetFileProps(rFileTok[ix],wzName,1024,&ulNameLen,
+ &pHashValue,&cbHashValue,&dwFlags)))
+ {
+ szptr = &szString[0];
+ rFile[ix].tok = rFileTok[ix];
+ rFile[ix].name = new WCHAR[ulNameLen+1];
+ memcpy(rFile[ix].name,wzName,ulNameLen*sizeof(WCHAR));
+ rFile[ix].name[ulNameLen] = 0;
+
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s%s ",g_szAsmCodeIndent,KEYWORD(".file"));
+ if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),rFileTok[ix]);
+ if(IsFfContainsNoMetaData(dwFlags)) szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("nometadata "));
+ {
+ int L = ulNameLen*3+3;
+ char* sz = new char[L];
+ memset(sz,0,L);
+ WszWideCharToMultiByte(CP_UTF8,0,rFile[ix].name,-1,sz,L,NULL,NULL);
+ strcpy_s(szptr,SZSTRING_REMAINING_SIZE(szptr), ANCHORPT(ProperName(sz),rFileTok[ix]));
+ VDELETE(sz);
+ }
+ printLine(GUICookie,szString);
+ if(VAL32(IMAGE_COR20_HEADER_FIELD(*g_CORHeader, EntryPointToken)) == rFileTok[ix])
+ {
+ printLine(GUICookie, KEYWORD(" .entrypoint"));
+ }
+ if(pHashValue && cbHashValue)
+ {
+ sprintf_s(szString,SZSTRING_SIZE," %s = (",KEYWORD(".hash"));
+ DumpByteArray(szString,(BYTE*)pHashValue,cbHashValue,GUICookie);
+ printLine(GUICookie,szString);
+ }
+ DumpCustomAttributes(rFile[ix].tok, GUICookie);
+ }
+ }
+ }
+ g_pAssemblyImport->CloseEnum(hEnum);
+ }
+ else nFiles=0;
+}
+
+void DumpAssemblyMetaData(ASSEMBLYMETADATA* pmd, void* GUICookie)
+{
+ if(pmd)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s %d:%d:%d:%d",g_szAsmCodeIndent,KEYWORD(".ver"),pmd->usMajorVersion,
+ pmd->usMinorVersion,pmd->usBuildNumber,pmd->usRevisionNumber);
+ printLine(GUICookie,szString);
+ if(pmd->szLocale && pmd->cbLocale)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s = (",g_szAsmCodeIndent,KEYWORD(".locale"));
+ DumpByteArray(szString,(BYTE*)(pmd->szLocale),pmd->cbLocale*sizeof(WCHAR),GUICookie);
+ printLine(GUICookie,szString);
+ }
+ }
+}
+void DumpScope(void* GUICookie)
+{
+ mdModule mdm;
+ GUID mvid;
+ WCHAR scopeName[1024];
+ WCHAR guidString[1024];
+ memset(scopeName,0,1024*sizeof(WCHAR));
+ if(SUCCEEDED(g_pPubImport->GetScopeProps( scopeName, 1024, NULL, &mvid))&& scopeName[0])
+ {
+ {
+ UINT32 L = (UINT32)wcslen(scopeName)*3+3;
+ char* sz = new char[L];
+ memset(sz,0,L);
+ WszWideCharToMultiByte(CP_UTF8,0,scopeName,-1,sz,L,NULL,NULL);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,KEYWORD(".module"),ProperName(sz));
+ VDELETE(sz);
+ }
+ printLine(GUICookie,szString);
+ StringFromGUID2(mvid, guidString, 1024);
+ {
+ UINT32 L = (UINT32)wcslen(guidString)*3+3;
+ char* sz = new char[L];
+ memset(sz,0,L);
+ WszWideCharToMultiByte(CP_UTF8,0,guidString,-1,sz,L,NULL,NULL);
+ sprintf_s(szString,SZSTRING_SIZE,COMMENT("%s// MVID: %s"),g_szAsmCodeIndent,sz);
+ VDELETE(sz);
+ }
+ printLine(GUICookie,szString);
+ if(SUCCEEDED(g_pPubImport->GetModuleFromScope(&mdm)))
+ {
+ DumpCustomAttributes(mdm, GUICookie);
+ DumpPermissions(mdm, GUICookie);
+ }
+ }
+}
+
+void DumpModuleRefs(void *GUICookie)
+{
+ HCORENUM hEnum=NULL;
+ ULONG N;
+ static mdToken tk[4096];
+ char* szptr;
+ LPCSTR szName;
+
+ g_pPubImport->EnumModuleRefs(&hEnum,tk,4096,&N);
+ for(ULONG i = 0; i < N; i++)
+ {
+ if(RidFromToken(tk[i]))
+ {
+ if (FAILED(g_pImport->GetModuleRefProps(tk[i],&szName)))
+ {
+ continue;
+ }
+ if (*szName != 0) // ignore the no-name ModuleRef: it's an IJW artifact
+ {
+ szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,KEYWORD(".module extern"),
+ ANCHORPT(ProperName((char*)szName),tk[i]));
+ if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT(" /*%08X*/"),tk[i]);
+ printLine(GUICookie,szString);
+ DumpCustomAttributes(tk[i], GUICookie);
+ DumpPermissions(tk[i], GUICookie);
+ }
+ }
+ }
+ g_pPubImport->CloseEnum(hEnum);
+}
+
+void DumpAssembly(void* GUICookie, BOOL fFullDump)
+{
+ 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[MAX_LOCALE_NAME];
+ DWORD dwFlags;
+ char* szptr;
+
+ md.szLocale = wzLocale;
+ md.cbLocale = MAX_LOCALE_NAME;
+ 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(ulNameLen >= 1024)
+ {
+ strcpy_s(szString,SZSTRING_SIZE,RstrUTF(IDS_ASSEMNAMETOOLONG));
+ printError(GUICookie,szString);
+ ulNameLen = 1023;
+ }
+ szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".assembly"));
+ if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),tkAsm);
+
+ if(IsAfRetargetable(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("retargetable "));
+ if(IsAfContentType_WindowsRuntime(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("windowsruntime "));
+ if(IsAfPA_NoPlatform(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("noplatform "));
+ if(IsAfPA_MSIL(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("cil "));
+ if(IsAfPA_x86(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("x86 "));
+ if(IsAfPA_IA64(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("ia64 "));
+ if(IsAfPA_AMD64(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("amd64 "));
+
+
+ wzName[ulNameLen] = 0;
+ {
+ char* sz = new char[3*ulNameLen+3];
+ memset(sz,0,3*ulNameLen+3);
+ WszWideCharToMultiByte(CP_UTF8,0,wzName,-1,sz,3*ulNameLen+3,NULL,NULL);
+ strcat_s(szString,SZSTRING_SIZE,ANCHORPT(ProperName(sz),tkAsm));
+ VDELETE(sz);
+ }
+ printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+ if(fFullDump)
+ {
+ DumpCustomAttributes(tkAsm, GUICookie);
+ DumpPermissions(tkAsm, GUICookie);
+ }
+
+ if(fFullDump)
+ {
+ if(pPublicKey && cbPublicKey)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s = (",g_szAsmCodeIndent,KEYWORD(".publickey"));
+ DumpByteArray(szString,(BYTE*)pPublicKey,cbPublicKey,GUICookie);
+ printLine(GUICookie,szString);
+ }
+ if(ulHashAlgId)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%08X",g_szAsmCodeIndent,KEYWORD(".hash algorithm"),ulHashAlgId);
+ printLine(GUICookie,szString);
+ }
+ }
+ DumpAssemblyMetaData(&md,GUICookie);
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
+ printLine(GUICookie,szString);
+ } //end if(OK(GetAssemblyProps))
+ } //end if(OK(GetAssemblyFromScope))
+}
+
+MTokName* rAsmRef = NULL;
+ULONG nAsmRefs = 0;
+
+void DumpAssemblyRefs(void* GUICookie)
+{
+ static mdAssemblyRef rAsmRefTok[4096];
+ HCORENUM hEnum=NULL;
+ ULONG ix = 0;
+ if(rAsmRef) { VDELETE(rAsmRef); nAsmRefs = 0; }
+ if(rAsmRefName)
+ {
+ for(ix=0; ix < ulNumAsmRefs; ix++)
+ {
+ if(rAsmRefName[ix]) VDELETE(rAsmRefName[ix]);
+ }
+ VDELETE(rAsmRefName);
+ rAsmRefName = NULL;
+ ulNumAsmRefs = 0;
+ }
+ if(SUCCEEDED(g_pAssemblyImport->EnumAssemblyRefs(&hEnum,rAsmRefTok,4096,&nAsmRefs)))
+ {
+ if(nAsmRefs)
+ {
+ const void* pPublicKeyOrToken;
+ ULONG cbPublicKeyOrToken = 0;
+ const void* pHashValue;
+ ULONG cbHashValue;
+ static WCHAR wzName[1024];
+ ULONG ulNameLen=0;
+ ASSEMBLYMETADATA md;
+ WCHAR wzLocale[MAX_LOCALE_NAME];
+ DWORD dwFlags;
+
+ rAsmRef = new MTokName[nAsmRefs];
+ rAsmRefName = new LPCSTR[nAsmRefs];
+ ulNumAsmRefs = nAsmRefs;
+
+ for(ix = 0; ix < nAsmRefs; ix++)
+ {
+ md.szLocale = wzLocale;
+ md.cbLocale = MAX_LOCALE_NAME;
+ md.rProcessor = NULL;
+ md.ulProcessor = 0;
+ md.rOS = NULL;
+ md.ulOS = 0;
+
+ ulNameLen=cbHashValue=0;
+ pHashValue = NULL;
+ if(SUCCEEDED(g_pAssemblyImport->GetAssemblyRefProps( // S_OK or error.
+ rAsmRefTok[ix], // [IN] The Assembly for which to get the properties.
+ &pPublicKeyOrToken, // [OUT] Pointer to the public key or token.
+ &cbPublicKeyOrToken,// [OUT] Count of bytes in the public key or token.
+ 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.
+ &pHashValue, // [OUT] Hash blob.
+ &cbHashValue,// [OUT] Count of bytes in the hash blob.
+ &dwFlags))) // [OUT] Flags.
+ {
+ ULONG ixx;
+ rAsmRef[ix].tok = rAsmRefTok[ix];
+ rAsmRef[ix].name = new WCHAR[ulNameLen+16];
+ memcpy(rAsmRef[ix].name,wzName,ulNameLen*sizeof(WCHAR));
+ rAsmRef[ix].name[ulNameLen] = 0;
+ if(ulNameLen >= 1024)
+ {
+ strcpy_s(szString,SZSTRING_SIZE,RstrUTF(IDS_ASMREFNAMETOOLONG));
+ printError(GUICookie,szString);
+ wzName[1023] = 0;
+ }
+
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".assembly extern"));
+ if(g_fDumpTokens) sprintf_s(&szString[strlen(szString)],SZSTRING_SIZE-strlen(szString),COMMENT("/*%08X*/ "),rAsmRefTok[ix]);
+
+ if(IsAfRetargetable(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("retargetable "));
+ if(IsAfContentType_WindowsRuntime(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("windowsruntime "));
+ if(IsAfPA_MSIL(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("cil "));
+ if(IsAfPA_x86(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("x86 "));
+ if(IsAfPA_IA64(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("ia64 "));
+ if(IsAfPA_AMD64(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("amd64 "));
+
+ {
+ char* sz = new char[3*ulNameLen+32];
+ memset(sz,0,3*ulNameLen+3);
+ WszWideCharToMultiByte(CP_UTF8,0,rAsmRef[ix].name,-1,sz,3*ulNameLen+3,NULL,NULL);
+ // check for name duplication and introduce alias if needed
+ for(ixx = 0; ixx < ix; ixx++)
+ {
+ if(!wcscmp(rAsmRef[ixx].name,rAsmRef[ix].name)) break;
+ }
+ if(ixx < ix)
+ {
+ strcat_s(szString,SZSTRING_SIZE, ProperName(sz));
+ char* pc=&szString[strlen(szString)];
+ sprintf_s(&sz[strlen(sz)],3*ulNameLen+32-strlen(sz),"_%d",ix);
+ sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc)," %s %s", KEYWORD("as"),ANCHORPT(ProperName(sz),rAsmRefTok[ix]));
+ }
+ else
+ strcat_s(szString,SZSTRING_SIZE, ANCHORPT(ProperName(sz),rAsmRefTok[ix]));
+ rAsmRefName[ix] = sz;
+ }
+ printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+ DumpCustomAttributes(rAsmRefTok[ix], GUICookie);
+ if(pPublicKeyOrToken && cbPublicKeyOrToken)
+ {
+ if (IsAfPublicKey(dwFlags))
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s = (",g_szAsmCodeIndent,KEYWORD(".publickey"));
+ else
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s = (",g_szAsmCodeIndent,KEYWORD(".publickeytoken"));
+ DumpByteArray(szString,(BYTE*)pPublicKeyOrToken,cbPublicKeyOrToken,GUICookie);
+ printLine(GUICookie,szString);
+ }
+ if(pHashValue && cbHashValue)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s = (",g_szAsmCodeIndent,KEYWORD(".hash"));
+ DumpByteArray(szString,(BYTE*)pHashValue,cbHashValue,GUICookie);
+ printLine(GUICookie,szString);
+ }
+ DumpAssemblyMetaData(&md,GUICookie);
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
+ printLine(GUICookie,szString);
+ } //end if(OK(GetAssemblyRefProps))
+ }//end for(all assembly refs)
+ }//end if(nAsmRefs
+ g_pAssemblyImport->CloseEnum(hEnum);
+ }//end if OK(EnumAssemblyRefs)
+ else nAsmRefs=0;
+}
+
+DynamicArray<LocalComTypeDescr*> *g_pLocalComType = NULL;
+ULONG g_LocalComTypeNum = 0;
+
+void DumpComTypeFQN(
+ LocalComTypeDescr* pCTD,
+ __inout __nullterminated char* szName)
+{
+ if(TypeFromToken(pCTD->tkImplementation) == mdtExportedType)
+ {
+ ULONG i;
+ for(i = 0; (i < g_LocalComTypeNum) && ((*g_pLocalComType)[i]->tkComTypeTok != pCTD->tkImplementation); i++);
+ if(i < g_LocalComTypeNum)
+ {
+ DumpComTypeFQN((*g_pLocalComType)[i], szName);
+ strcat_s(szName, SZSTRING_SIZE, "/");
+ }
+ }
+
+ UINT32 L = (UINT32)wcslen(pCTD->wzName)*3+3;
+ char* sz = new char[L];
+ memset(sz,0,L);
+ WszWideCharToMultiByte(CP_UTF8,0,pCTD->wzName,-1,sz,L,NULL,NULL);
+ strcat_s(szName, SZSTRING_SIZE, JUMPPT(ProperName(sz), pCTD->tkComTypeTok));
+ VDELETE(sz);
+}
+
+void DumpImplementation(mdToken tkImplementation,
+ DWORD dwOffset,
+ __inout __nullterminated char* szString,
+ void* GUICookie)
+{
+ ULONG i;
+ char* pc;
+ if(RidFromToken(tkImplementation))
+ {
+ if(TypeFromToken(tkImplementation) == mdtFile)
+ {
+ for(i=0; (i < nFiles)&&(rFile[i].tok != tkImplementation); i++);
+ if(i < nFiles)
+ {
+ {
+ UINT32 L = (UINT32)wcslen(rFile[i].name)*3+3;
+ char* sz = new char[L];
+ memset(sz,0,L);
+ WszWideCharToMultiByte(CP_UTF8,0,rFile[i].name,-1,sz,L,NULL,NULL);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,KEYWORD(".file"),
+ JUMPPT(ProperName(sz),tkImplementation));
+ VDELETE(sz);
+ }
+ pc=&szString[strlen(szString)];
+ if(g_fDumpTokens) pc+=sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc),COMMENT("/*%08X*/ "),tkImplementation);
+ if(dwOffset != 0xFFFFFFFF) sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc)," %s 0x%08X",KEYWORD("at"),dwOffset);
+ printLine(GUICookie,szString);
+ }
+ }
+ else if(TypeFromToken(tkImplementation) == mdtAssemblyRef)
+ {
+ for(i=0; (i < nAsmRefs)&&(rAsmRef[i].tok != tkImplementation); i++);
+ if(i < nAsmRefs)
+ {
+ {
+ UINT32 L = (UINT32)wcslen(rAsmRef[i].name)*3+3;
+ char* sz = new char[L];
+ memset(sz,0,L);
+ WszWideCharToMultiByte(CP_UTF8,0,rAsmRef[i].name,-1,sz,L,NULL,NULL);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,KEYWORD(".assembly extern"),
+ JUMPPT(ProperName(sz),tkImplementation));
+ VDELETE(sz);
+ }
+ pc=&szString[strlen(szString)];
+ if(g_fDumpTokens) sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc),COMMENT(" /*%08X*/ "),tkImplementation);
+ printLine(GUICookie,szString);
+ }
+ }
+ else if(TypeFromToken(tkImplementation) == mdtExportedType)
+ {
+ // Find the type structure corresponding to this token
+ for(i=0; (i < g_LocalComTypeNum)&&((*g_pLocalComType)[i]->tkComTypeTok != tkImplementation); i++);
+ if(i < g_LocalComTypeNum)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".class extern"));
+ DumpComTypeFQN((*g_pLocalComType)[i], szString);
+
+ pc=&szString[strlen(szString)];
+ if(g_fDumpTokens) sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc),COMMENT(" /*%08X*/ "),tkImplementation);
+ printLine(GUICookie,szString);
+ }
+ }
+ }
+}
+
+void DumpComType(LocalComTypeDescr* pCTD,
+ __inout __nullterminated char* szString,
+ void* GUICookie)
+{
+ if(g_fDumpTokens) sprintf_s(&szString[strlen(szString)],SZSTRING_SIZE-strlen(szString),COMMENT("/*%08X*/ "),pCTD->tkComTypeTok);
+ if (IsTdPublic(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("public "));
+ if (IsTdForwarder(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("forwarder "));
+ if (IsTdNestedPublic(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("nested public "));
+ if (IsTdNestedPrivate(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("nested private "));
+ if (IsTdNestedFamily(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("nested family "));
+ if (IsTdNestedAssembly(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("nested assembly "));
+ if (IsTdNestedFamANDAssem(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("nested famandassem "));
+ if (IsTdNestedFamORAssem(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("nested famorassem "));
+
+ char* pc=&szString[strlen(szString)];
+ {
+ UINT32 L = (UINT32)wcslen(pCTD->wzName)*3+3;
+ char* sz = new char[L];
+ memset(sz,0,L);
+ WszWideCharToMultiByte(CP_UTF8,0,pCTD->wzName,-1,sz,L,NULL,NULL);
+ strcpy_s(pc,SZSTRING_REMAINING_SIZE(pc),ANCHORPT(ProperName(sz),pCTD->tkComTypeTok));
+ VDELETE(sz);
+ }
+ printLine(GUICookie,szString);
+
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+ DumpCustomAttributes(pCTD->tkComTypeTok, GUICookie);
+ DumpImplementation(pCTD->tkImplementation,0xFFFFFFFF,szString,GUICookie);
+ if(RidFromToken(pCTD->tkTypeDef))
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%08X",g_szAsmCodeIndent,KEYWORD(".class"),pCTD->tkTypeDef);
+ printLine(GUICookie,szString);
+ }
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
+ printLine(GUICookie,szString);
+}
+
+
+void DumpComTypes(void* GUICookie)
+{
+ static mdExportedType rComTypeTok[4096];
+ ULONG nComTypes;
+ HCORENUM hEnum=NULL;
+
+ g_LocalComTypeNum = 0;
+ if(SUCCEEDED(g_pAssemblyImport->EnumExportedTypes(&hEnum,rComTypeTok,4096,&nComTypes)))
+ {
+ if(nComTypes)
+ {
+ static WCHAR wzName[1024];
+ ULONG ulNameLen=0;
+ DWORD dwFlags;
+ mdToken tkImplementation;
+ mdTypeDef tkTypeDef;
+
+ ULONG ix;
+ for(ix = 0; ix < nComTypes; ix++)
+ {
+ ulNameLen=0;
+ if(SUCCEEDED(g_pAssemblyImport->GetExportedTypeProps( // S_OK or error.
+ rComTypeTok[ix], // [IN] The ComType for which to get the properties.
+ wzName, // [OUT] Buffer to fill with name.
+ 1024, // [IN] Size of buffer in wide chars.
+ &ulNameLen, // [OUT] Actual # of wide chars in name.
+ &tkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ComType.
+ &tkTypeDef, // [OUT] TypeDef token within the file.
+ &dwFlags))) // [OUT] Flags.
+ {
+ LocalComTypeDescr* pCTD = new LocalComTypeDescr;
+ memset(pCTD,0,sizeof(LocalComTypeDescr));
+ pCTD->tkComTypeTok = rComTypeTok[ix];
+ pCTD->tkTypeDef = tkTypeDef;
+ pCTD->tkImplementation = tkImplementation;
+ pCTD->wzName = new WCHAR[ulNameLen+1];
+ memcpy(pCTD->wzName,wzName,ulNameLen*sizeof(WCHAR));
+ pCTD->wzName[ulNameLen] = 0;
+ pCTD->dwFlags = dwFlags;
+
+ if (g_pLocalComType == NULL)
+ {
+ g_pLocalComType = new DynamicArray<LocalComTypeDescr*>;
+ }
+
+ (*g_pLocalComType)[g_LocalComTypeNum] = pCTD;
+ g_LocalComTypeNum++;
+ } //end if(OK(GetComTypeProps))
+ }//end for(all com types)
+
+ // now, print all "external" com types
+ for(ix = 0; ix < nComTypes; ix++)
+ {
+ tkImplementation = (*g_pLocalComType)[ix]->tkImplementation;
+ // ComType of a nested class has its nester's ComType as implementation
+ while(TypeFromToken(tkImplementation)==mdtExportedType)
+ {
+ unsigned k;
+ for(k=0; k<g_LocalComTypeNum; k++)
+ {
+ if((*g_pLocalComType)[k]->tkComTypeTok == tkImplementation)
+ {
+ tkImplementation = (*g_pLocalComType)[k]->tkImplementation;
+ break;
+ }
+ }
+ if(k==g_LocalComTypeNum) break;
+ }
+ // At this moment, tkImplementation is impl.of top nester
+ if(RidFromToken(tkImplementation))
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".class extern"));
+ DumpComType((*g_pLocalComType)[ix],szString,GUICookie);
+ (*g_pLocalComType)[ix]->tkTypeDef = 0;
+ }
+ }
+ }//end if(nComTypes)
+ g_pAssemblyImport->CloseEnum(hEnum);
+ }//end if OK(EnumComTypes)
+ else nComTypes=0;
+}
+
+// Replaces invalid characters and neutralizes reserved file names.
+// Returns TRUE if the string was modified, FALSE otherwise.
+static BOOL ConvertToLegalFileNameInPlace(__inout LPWSTR wzName)
+{
+ BOOL fAlias = FALSE;
+
+ // neutralize reserved names
+ static const WCHAR * const rwzReserved[] =
+ {
+ L"COM", L"LPT", // '1' - '9' must follow after these
+ L"CON", L"PRN", L"AUX", L"NUL"
+ };
+
+ for (size_t i = 0; i < (sizeof(rwzReserved) / sizeof(WCHAR *)); i++)
+ {
+ _ASSERTE(wcslen(rwzReserved[i]) == 3);
+ if (_wcsnicmp(wzName, rwzReserved[i], 3) == 0)
+ {
+ LPWSTR pwc = wzName + 3;
+
+ if (i <= 1) // COM, LPT
+ {
+ if (*pwc >= L'1' && *pwc <= L'9')
+ {
+ // skip the digit
+ pwc++;
+ }
+ else continue;
+ }
+
+ // check for . or end of string
+ if (*pwc == L'.' || *pwc == 0)
+ {
+ *wzName = L'_';
+ fAlias = TRUE;
+ break;
+ }
+ }
+ }
+
+ // replace invalid characters
+ for (;; wzName++)
+ {
+ WCHAR wch = *wzName;
+
+ if (wch > 0 && wch < 32)
+ {
+ *wzName = '~';
+ fAlias = TRUE;
+ }
+ else
+ {
+ switch (wch)
+ {
+#define REPLACE_CH(oldCh, newCh) \
+ case oldCh: *wzName = newCh; \
+ fAlias = TRUE; \
+ break;
+
+ REPLACE_CH(L':', L'!')
+ REPLACE_CH(L'\\', L'$')
+ REPLACE_CH(L',', L'&') // not necessary but keeping for back compat
+ REPLACE_CH(L';', L'@') // not necessary but keeping for back compat
+ REPLACE_CH(L'<', L'(')
+ REPLACE_CH(L'>', L')')
+ REPLACE_CH(L'"', L'`')
+ REPLACE_CH(L'/', L'_')
+ REPLACE_CH(L'|', L'-')
+ REPLACE_CH(L'*', L'+') // disallowed wildcard
+ REPLACE_CH(L'?', L'=') // disallowed wildcard
+
+ case 0: return fAlias;
+#undef REPLACE_CH
+ }
+ }
+ }
+}
+
+// Dumps managed resource at pRes + dwOffset to a file.
+static void DumpResourceFile(void *GUICookie, BYTE *pRes, DWORD dwOffset, LPCWSTR wzName,
+ LPCWSTR wzFileName, LPCUTF8 sz)
+{
+ struct Param
+ {
+ BYTE *pRes;
+ DWORD dwOffset;
+ LPCUTF8 sz;
+ void *GUICookie;
+ const WCHAR *wzFileName;
+ } param;
+ param.pRes = pRes;
+ param.dwOffset = dwOffset;
+ param.sz = sz;
+ param.GUICookie = GUICookie;
+ param.wzFileName = wzFileName;
+
+ PAL_TRY(Param *, pParam, &param)
+ {
+ DWORD L;
+ memcpy(&L,pParam->pRes+pParam->dwOffset,sizeof(DWORD));
+ sprintf_s(szString,SZSTRING_SIZE,COMMENT("%s// Offset: 0x%8.8X Length: 0x%8.8X"), g_szAsmCodeIndent,pParam->dwOffset,L);
+ printLine(pParam->GUICookie,szString);
+ if ((!(g_Mode & MODE_GUI)) && (g_pFile != NULL)) // embedded resource -- dump as .resources file
+ {
+ FILE *pF = NULL;
+ _wfopen_s(&pF, pParam->wzFileName, L"wb");
+ if (pF)
+ {
+ struct Param
+ {
+ BYTE *pRes;
+ DWORD dwOffset;
+ DWORD L;
+ FILE *pF;
+ LPCUTF8 sz;
+ void *GUICookie;
+ } param;
+ param.pRes = pParam->pRes;
+ param.dwOffset = pParam->dwOffset;
+ param.L = L;
+ param.pF = pF;
+ param.sz = pParam->sz;
+ param.GUICookie = pParam->GUICookie;
+
+ PAL_TRY(Param *, pParam, &param) {
+ fwrite((pParam->pRes+pParam->dwOffset+sizeof(DWORD)),pParam->L,1,pParam->pF);
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_W_CREATEDMRES),g_szAsmCodeIndent,ProperName(pParam->sz));
+ printLine(pParam->GUICookie,COMMENT(szString));
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_READINGMRES),g_szAsmCodeIndent,ProperName(pParam->sz),pParam->dwOffset);
+ printError(pParam->GUICookie,szString);
+ }
+ PAL_ENDTRY
+ fclose(pF);
+ }
+ }
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ sprintf_s(szString, SZSTRING_SIZE,
+ "ERROR retrieving/saving embedded managed resource '%s' at offset 0x%8.8X",
+ UnicodeToUtf(wzName), dwOffset);
+ printError(GUICookie, szString);
+ }
+ PAL_ENDTRY
+}
+
+void DumpManifestResources(void* GUICookie)
+{
+ static mdManifestResource rManResTok[4096];
+ ULONG nManRes = 0;
+ HCORENUM hEnum=NULL;
+ BYTE* pRes = NULL;
+ if(SUCCEEDED(g_pAssemblyImport->EnumManifestResources(&hEnum,rManResTok,4096,&nManRes)))
+ {
+ if(nManRes)
+ {
+ WCHAR* wzName = NULL;
+ ULONG ulNameLen=0;
+ DWORD dwFlags;
+ static char sz[4096];
+ mdToken tkImplementation;
+ DWORD dwOffset;
+
+ static WCHAR wzFileName[2048];
+
+ WszMultiByteToWideChar(CP_UTF8,0,g_szOutputFile,-1,wzFileName,2048);
+ wzName = wcsrchr(wzFileName,'\\');
+ if(wzName == NULL) wzName = wcsrchr(wzFileName,':');
+ if (wzName == NULL) wzName = wzFileName;
+ else wzName++;
+
+ // remember the file names created so far to avoid duplicates
+ CQuickArray<CQuickWSTRBase> qbNameArray;
+ if (!qbNameArray.AllocNoThrow(nManRes + 2))
+ {
+ sprintf_s(szString, SZSTRING_SIZE,
+ "ERROR retrieving/saving embedded managed resource '%s'", UnicodeToUtf(wzName));
+ printError(GUICookie, szString);
+ return;
+ }
+
+#define NAME_ARRAY_ADD(index, str) \
+ { \
+ size_t __dwBufLen = wcslen(str) + 1; \
+ \
+ qbNameArray[index].Init(); \
+ WCHAR *__wpc = (WCHAR *)qbNameArray[index].AllocNoThrow(__dwBufLen); \
+ if (__wpc) wcscpy_s(__wpc, __dwBufLen, str); \
+ }
+
+ // add the output file name to avoid conflict between the IL file and a resource file
+ NAME_ARRAY_ADD(0, wzName);
+
+ // add the Win32 resource file name to avoid conflict between the native and a managed resource file
+ WCHAR *pwc = wcsrchr(wzName, L'.');
+ if (pwc == NULL) pwc = &wzName[wcslen(wzName)];
+ wcscpy_s(pwc, 2048 - (pwc - wzFileName), L".res");
+
+ NAME_ARRAY_ADD(1, wzName);
+
+ for(ULONG ix = 0; ix < nManRes; ix++)
+ {
+ ulNameLen=0;
+ if(SUCCEEDED(g_pAssemblyImport->GetManifestResourceProps( // S_OK or error.
+ rManResTok[ix], // [IN] The ManifestResource for which to get the properties.
+ wzName, // [OUT] Buffer to fill with name.
+ 1024, // [IN] Size of buffer in wide chars.
+ &ulNameLen, // [OUT] Actual # of wide chars in name.
+ &tkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ComType.
+ &dwOffset, // [OUT] Offset to the beginning of the resource within the file.
+ &dwFlags))) // [OUT] Flags.
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".mresource"));
+ if(g_fDumpTokens) sprintf_s(&szString[strlen(szString)],SZSTRING_SIZE-strlen(szString),COMMENT("/*%08X*/ "),rManResTok[ix]);
+ if(IsMrPublic(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("public "));
+ if(IsMrPrivate(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("private "));
+
+ char* pc = szString + strlen(szString);
+ wzName[ulNameLen]=0;
+
+ WszWideCharToMultiByte(CP_UTF8,0,wzName,-1,sz,sizeof(sz),NULL,NULL);
+ strcpy_s(pc,SZSTRING_REMAINING_SIZE(pc),ProperName(sz));
+
+ // get rid of invalid characters and reserved names
+ BOOL fAlias = ConvertToLegalFileNameInPlace(wzName);
+
+ // check for duplicate file name
+ WCHAR *wpc = wzName + wcslen(wzName);
+ for (int iIndex = 1;; iIndex++)
+ {
+ BOOL fConflict = FALSE;
+ if (*wzName == 0)
+ {
+ // resource with an empty name
+ fConflict = TRUE;
+ }
+ else
+ {
+ for (ULONG i = 0; i < (ix + 2); i++)
+ {
+ WCHAR *wzPreviousName = (WCHAR *)qbNameArray[i].Ptr();
+ if (wzPreviousName && _wcsicmp(wzName, wzPreviousName) == 0)
+ {
+ // resource with the same name as another resource
+ // or with the same name as the output IL/RES file
+ fConflict = TRUE;
+ break;
+ }
+ }
+ }
+
+ // if we have a conflict, add a number suffix to the file name
+ if (!fConflict ||
+ swprintf_s(wpc, 2048 - (wpc - wzFileName), L"%d", iIndex) <= 0)
+ {
+ // no conflict or unable to add index
+ break;
+ }
+
+ // try again with this new number suffix
+ fAlias = TRUE;
+ }
+
+ // add this unique file name to the list
+ NAME_ARRAY_ADD(ix + 2, wzName);
+
+ if(fAlias)
+ {
+ // update sz with the aliased name and print the 'as' keyword
+ if (WszWideCharToMultiByte(CP_UTF8, 0, wzName, -1, sz, sizeof(sz), NULL, NULL) == 0)
+ {
+ sz[sizeof(sz) - 1] = 0;
+ }
+
+ pc=&szString[strlen(szString)];
+ sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc)," %s %s",KEYWORD("as"),ProperName(sz));
+ }
+
+ printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+ DumpCustomAttributes(rManResTok[ix], GUICookie);
+
+ if(tkImplementation == mdFileNil) // embedded resource -- dump as .resources file
+ {
+ if(pRes == NULL)
+ {
+ // get the resource VA
+ if (g_pPELoader->getVAforRVA((DWORD) VAL32(g_CORHeader->Resources.VirtualAddress), (void **) &pRes) == FALSE)
+ {
+ printError(GUICookie,RstrUTF(IDS_E_IMPORTDATA));
+ }
+ }
+ if(pRes)
+ {
+ DumpResourceFile(GUICookie, pRes, dwOffset, wzName, wzFileName, sz);
+ }
+ }
+ else DumpImplementation(tkImplementation,dwOffset,szString,GUICookie);
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
+ printLine(GUICookie,szString);
+ } //end if(OK(GetManifestResourceProps))
+ }//end for(all manifest resources)
+
+#undef NAME_ARRAY_ADD
+
+ }//end if(nManRes)
+ g_pAssemblyImport->CloseEnum(hEnum);
+ }//end if OK(EnumManifestResources)
+ else nManRes=0;
+}
+
+// CLR internal hosting API
+extern ICLRRuntimeHostInternal *g_pCLRRuntimeHostInternal;
+
+IMetaDataAssemblyImport* GetAssemblyImport(void* GUICookie)
+{
+ struct Param
+ {
+ void* GUICookie;
+ IMetaDataAssemblyImport* pAssemblyImport;
+ IMDInternalImport* pImport;
+ mdToken tkManifest;
+ } param;
+ param.GUICookie = GUICookie;
+ param.pAssemblyImport = NULL;
+ param.pImport = NULL;
+
+ HRESULT hr;
+
+ hr=g_pPubImport->QueryInterface(IID_IMetaDataAssemblyImport, (void**) &param.pAssemblyImport);
+ if(SUCCEEDED(hr))
+ {
+ static mdAssemblyRef rAsmRefTok[4096];
+ HCORENUM hEnum=NULL;
+ ULONG nAsmRefs = 0;
+ if(SUCCEEDED(param.pAssemblyImport->GetAssemblyFromScope(&param.tkManifest))) return param.pAssemblyImport;
+ if(SUCCEEDED(param.pAssemblyImport->EnumAssemblyRefs(&hEnum,rAsmRefTok,4096,&nAsmRefs)))
+ {
+ param.pAssemblyImport->CloseEnum(hEnum);
+ if(nAsmRefs) return param.pAssemblyImport;
+ }
+ param.pAssemblyImport->Release();
+ }
+ else
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_MDAIMPORT),hr);
+ printLine(GUICookie,COMMENT(szString));
+ }
+ param.pAssemblyImport = NULL;
+ // OK, let's do it hard way: check if the manifest is hidden somewhere else
+ PAL_TRY(Param *, pParam, &param)
+ {
+ if(g_CORHeader->Resources.Size)
+ {
+ DWORD* pdwSize = NULL;
+ BYTE* pbManifest = NULL;
+ HRESULT hr;
+
+ pbManifest = (BYTE*)(g_pPELoader->base() + (DWORD)VAL32(g_CORHeader->Resources.VirtualAddress));
+ pdwSize = (DWORD*)pbManifest;
+ if(pdwSize && *pdwSize)
+ {
+ pbManifest += sizeof(DWORD);
+ if (SUCCEEDED(hr = g_pCLRRuntimeHostInternal->GetMetaDataInternalInterface(
+ pbManifest,
+ VAL32(*pdwSize),
+ ofRead,
+ IID_IMDInternalImport,
+ (LPVOID *)&pParam->pImport)))
+ {
+ if (FAILED(hr = g_pCLRRuntimeHostInternal->GetMetaDataPublicInterfaceFromInternal(
+ pParam->pImport,
+ IID_IMetaDataAssemblyImport,
+ (LPVOID *)&pParam->pAssemblyImport)))
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_MDAFROMMDI),hr);
+ printLine(pParam->GUICookie,COMMENT(szString));
+ pParam->pAssemblyImport = NULL;
+ }
+ else
+ {
+ mdAssemblyRef rAsmRefTok[4096];
+ HCORENUM hEnum=NULL;
+ ULONG nAsmRefs = 0;
+ if(FAILED(pParam->pAssemblyImport->GetAssemblyFromScope(&pParam->tkManifest))
+ && (FAILED(pParam->pAssemblyImport->EnumAssemblyRefs(&hEnum,rAsmRefTok,4096,&nAsmRefs))
+ || (nAsmRefs ==0)))
+ {
+ pParam->pAssemblyImport->CloseEnum(hEnum);
+ pParam->pAssemblyImport->Release();
+ pParam->pAssemblyImport = NULL;
+ }
+ }
+ pParam->pImport->Release();
+ }
+ else
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_MDIIMPORT),hr);
+ printLine(pParam->GUICookie,COMMENT(szString));
+ }
+ }
+ }
+ } // end try
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if(param.pAssemblyImport) param.pAssemblyImport->Release();
+ param.pAssemblyImport = NULL;
+ if(param.pImport) param.pImport->Release();
+ }
+ PAL_ENDTRY
+ return param.pAssemblyImport;
+}
+
+static void DumpMetadataVersion(void* GUICookie)
+{
+ LPCSTR pVersionStr;
+ if (g_pImport == NULL || FAILED(g_pImport->GetVersionString(&pVersionStr)))
+ {
+ pVersionStr = "**Unavailable**";
+ }
+ sprintf_s(szString,SZSTRING_SIZE,"// Metadata version: %s",pVersionStr);
+ printLine(GUICookie,szString);
+}
+
+void DumpManifest(void* GUICookie)
+{
+ DumpMetadataVersion(GUICookie);
+ DumpModuleRefs(GUICookie);
+ if(g_pAssemblyImport==NULL) g_pAssemblyImport = GetAssemblyImport(GUICookie);
+ if(g_pAssemblyImport)
+ {
+ DumpAssemblyRefs(GUICookie);
+ DumpAssembly(GUICookie,TRUE);
+ DumpFiles(GUICookie);
+ DumpComTypes(GUICookie);
+ DumpManifestResources(GUICookie);
+ }
+ else printLine(GUICookie,COMMENT(RstrUTF(IDS_E_NOMANIFEST)));
+ DumpScope(GUICookie);
+ DumpVtable(GUICookie);
+
+}
diff --git a/src/ildasm/dres.cpp b/src/ildasm/dres.cpp
new file mode 100644
index 0000000000..d2c4191bf2
--- /dev/null
+++ b/src/ildasm/dres.cpp
@@ -0,0 +1,315 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+//
+// Win32 Resource extractor
+//
+#include "ildasmpch.h"
+
+#include "debugmacros.h"
+#include "corpriv.h"
+#include "dasmenum.hpp"
+#include "dasmgui.h"
+#include "formattype.h"
+#include "dis.h"
+#include "resource.h"
+#include "ilformatter.h"
+#include "outstring.h"
+
+#include "ceeload.h"
+#include "dynamicarray.h"
+extern IMAGE_COR20_HEADER * g_CORHeader;
+extern IMDInternalImport* g_pImport;
+extern PELoader * g_pPELoader;
+extern IMetaDataImport2* g_pPubImport;
+extern char g_szAsmCodeIndent[];
+extern unsigned g_uConsoleCP;
+
+struct ResourceHeader
+{
+ DWORD dwDataSize;
+ DWORD dwHeaderSize;
+ DWORD dwTypeID;
+ DWORD dwNameID;
+ DWORD dwDataVersion;
+ WORD wMemFlags;
+ WORD wLangID;
+ DWORD dwVersion;
+ DWORD dwCharacteristics;
+ ResourceHeader()
+ {
+ memset(this,0,sizeof(ResourceHeader));
+ dwHeaderSize = sizeof(ResourceHeader);
+ dwTypeID = dwNameID = 0xFFFF;
+ };
+};
+
+struct ResourceNode
+{
+ ResourceHeader ResHdr;
+ IMAGE_RESOURCE_DATA_ENTRY DataEntry;
+ WCHAR* wzType;
+ WCHAR* wzName;
+ ResourceNode(DWORD tid, DWORD nid, DWORD lid, DWORD dataOffset, BYTE* ptrBase)
+ {
+ if(tid & 0x80000000)
+ {
+ ResHdr.dwTypeID = 0;
+ tid &= 0x7FFFFFFF;
+ WORD L = *((WORD*)(ptrBase+tid));
+ wzType = new WCHAR[L+1];
+ memcpy(wzType,ptrBase+tid+sizeof(WORD),L*sizeof(WCHAR));
+ wzType[L]=0;
+ }
+ else
+ {
+ ResHdr.dwTypeID = (0xFFFF |((tid & 0xFFFF)<<16));
+ wzType = NULL;
+ }
+
+ if(nid & 0x80000000)
+ {
+ ResHdr.dwNameID = 0;
+ nid &= 0x7FFFFFFF;
+ WORD L = *((WORD*)(ptrBase+nid));
+ wzName = new WCHAR[L+1];
+ memcpy(wzName, ptrBase+nid+sizeof(WORD), L*sizeof(WCHAR));
+ wzName[L]=0;
+ }
+ else
+ {
+ ResHdr.dwNameID = (0xFFFF |((nid & 0xFFFF)<<16));
+ wzName = NULL;
+ }
+
+ //ResHdr.dwTypeID = (tid & 0x80000000) ? tid : (0xFFFF |((tid & 0xFFFF)<<16));
+ //ResHdr.dwNameID = (nid & 0x80000000) ? nid : (0xFFFF |((nid & 0xFFFF)<<16));
+ ResHdr.wLangID = (WORD)lid;
+ if(ptrBase) memcpy(&DataEntry,(ptrBase+dataOffset),sizeof(IMAGE_RESOURCE_DATA_ENTRY));
+ ResHdr.dwDataSize = DataEntry.Size;
+ };
+ ~ResourceNode()
+ {
+ if(wzType) VDELETE(wzType);
+ if(wzName) VDELETE(wzName);
+ };
+ void Save(FILE* pF)
+ {
+ // Dump them to pF
+ BYTE* pbData;
+ DWORD dwFiller = 0;
+ BYTE bNil[3] = {0,0,0};
+ // For each resource write header and data
+ if(g_pPELoader->getVAforRVA(VAL32(DataEntry.OffsetToData), (void **) &pbData))
+ {
+ //fwrite(&(g_prResNodePtr[i]->ResHdr),g_prResNodePtr[i]->ResHdr.dwHeaderSize,1,pF);
+ ResHdr.dwHeaderSize = sizeof(ResourceHeader);
+ if(wzType) ResHdr.dwHeaderSize += (DWORD)((wcslen(wzType) + 1)*sizeof(WCHAR) - sizeof(DWORD));
+ if(wzName) ResHdr.dwHeaderSize += (DWORD)((wcslen(wzName) + 1)*sizeof(WCHAR) - sizeof(DWORD));
+
+ //---- Constant part of the header: DWORD,DWORD
+ fwrite(&ResHdr.dwDataSize, sizeof(DWORD),1,pF);
+ fwrite(&ResHdr.dwHeaderSize, sizeof(DWORD),1,pF);
+ //--- Variable part of header: type and name
+ if(wzType)
+ {
+ fwrite(wzType,(wcslen(wzType) + 1)*sizeof(WCHAR), 1, pF);
+ dwFiller += (DWORD)wcslen(wzType) + 1;
+ }
+ else
+ fwrite(&ResHdr.dwTypeID,sizeof(DWORD),1,pF);
+ if(wzName)
+ {
+ fwrite(wzName,(wcslen(wzName) + 1)*sizeof(WCHAR), 1, pF);
+ dwFiller += (DWORD)wcslen(wzName) + 1;
+ }
+ else
+ fwrite(&ResHdr.dwNameID,sizeof(DWORD),1,pF);
+
+ // Align remaining fields on DWORD
+ if(dwFiller & 1)
+ fwrite(bNil,2,1,pF);
+
+ //---- Constant part of the header: DWORD,WORD,WORD,DWORD,DWORD
+ fwrite(&ResHdr.dwDataVersion,8*sizeof(WORD),1,pF);
+ //---- Header done, now data
+ fwrite(pbData,VAL32(DataEntry.Size),1,pF);
+ dwFiller = VAL32(DataEntry.Size) & 3;
+ if(dwFiller)
+ {
+ dwFiller = 4 - dwFiller;
+ fwrite(bNil,dwFiller,1,pF);
+ }
+ }
+ };
+};
+
+
+#define RES_FILE_DUMP_ENABLED
+
+DWORD DumpResourceToFile(__in __nullterminated WCHAR* wzFileName)
+{
+
+ BYTE* pbResBase;
+ FILE* pF = NULL;
+ DWORD ret = 0;
+ DWORD dwResDirRVA;
+ DWORD dwResDirSize;
+ unsigned ulNumResNodes=0;
+ DynamicArray<ResourceNode*> g_prResNodePtr;
+
+ if (g_pPELoader->IsPE32())
+ {
+ IMAGE_OPTIONAL_HEADER32 *pOptHeader = &(g_pPELoader->ntHeaders32()->OptionalHeader);
+
+ dwResDirRVA = VAL32(pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress);
+ dwResDirSize = VAL32(pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size);
+ }
+ else
+ {
+ IMAGE_OPTIONAL_HEADER64 *pOptHeader = &(g_pPELoader->ntHeaders64()->OptionalHeader);
+
+ dwResDirRVA = VAL32(pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress);
+ dwResDirSize = VAL32(pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size);
+ }
+
+ if(dwResDirRVA && dwResDirSize)
+ {
+ if(g_pPELoader->getVAforRVA(dwResDirRVA, (void **) &pbResBase))
+ {
+ // First, pull out all resource nodes (tree leaves), see ResourceNode struct
+ PIMAGE_RESOURCE_DIRECTORY pirdType = (PIMAGE_RESOURCE_DIRECTORY)pbResBase;
+ PIMAGE_RESOURCE_DIRECTORY_ENTRY pirdeType = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pbResBase+sizeof(IMAGE_RESOURCE_DIRECTORY));
+ DWORD dwTypeID;
+ unsigned short i = 0,N = pirdType->NumberOfNamedEntries+pirdType->NumberOfIdEntries;
+ PAL_CPP_TRY {
+ for(i=0; i < N; i++, pirdeType++)
+ {
+ dwTypeID = VAL32(IMAGE_RDE_NAME(pirdeType));
+ if(IMAGE_RDE_OFFSET_FIELD(pirdeType, DataIsDirectory))
+ {
+ BYTE* pbNameBase = pbResBase + VAL32(IMAGE_RDE_OFFSET_FIELD(pirdeType, OffsetToDirectory));
+ PIMAGE_RESOURCE_DIRECTORY pirdName = (PIMAGE_RESOURCE_DIRECTORY)pbNameBase;
+ PIMAGE_RESOURCE_DIRECTORY_ENTRY pirdeName = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pbNameBase+sizeof(IMAGE_RESOURCE_DIRECTORY));
+ DWORD dwNameID;
+ unsigned short i,N = VAL16(pirdName->NumberOfNamedEntries)+VAL16(pirdName->NumberOfIdEntries);
+
+ for(i=0; i < N; i++, pirdeName++)
+ {
+ dwNameID = VAL32(IMAGE_RDE_NAME(pirdeName));
+ if(IMAGE_RDE_OFFSET_FIELD(pirdeName, DataIsDirectory))
+ {
+ BYTE* pbLangBase = pbResBase + VAL32(IMAGE_RDE_OFFSET_FIELD(pirdeName, OffsetToDirectory));
+ PIMAGE_RESOURCE_DIRECTORY pirdLang = (PIMAGE_RESOURCE_DIRECTORY)pbLangBase;
+ PIMAGE_RESOURCE_DIRECTORY_ENTRY pirdeLang = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pbLangBase+sizeof(IMAGE_RESOURCE_DIRECTORY));
+ DWORD dwLangID;
+ unsigned short i,N = VAL16(pirdLang->NumberOfNamedEntries)+VAL16(pirdLang->NumberOfIdEntries);
+
+ for(i=0; i < N; i++, pirdeLang++)
+ {
+ dwLangID = VAL32(IMAGE_RDE_NAME(pirdeLang));
+ if(IMAGE_RDE_OFFSET_FIELD(pirdeLang, DataIsDirectory))
+ {
+ _ASSERTE(!"Resource hierarchy exceeds three levels");
+ }
+ else
+ {
+ g_prResNodePtr[ulNumResNodes++] = new ResourceNode(dwTypeID,dwNameID,dwLangID, VAL32(IMAGE_RDE_OFFSET(pirdeLang)),pbResBase);
+ }
+ }
+ }
+ else
+ {
+ g_prResNodePtr[ulNumResNodes++] = new ResourceNode(dwTypeID,dwNameID,0,VAL32(IMAGE_RDE_OFFSET(pirdeName)),pbResBase);
+ }
+ }
+ }
+ else
+ {
+ g_prResNodePtr[ulNumResNodes++] = new ResourceNode(dwTypeID,0,0,VAL32(IMAGE_RDE_OFFSET(pirdeType)),pbResBase);
+ }
+ }
+ } PAL_CPP_CATCH_ALL {
+ ret= 0xDFFFFFFF;
+ ulNumResNodes = 0;
+ }
+ PAL_CPP_ENDTRY
+ // OK, all tree leaves are in ResourceNode structs, and ulNumResNodes ptrs are in g_prResNodePtr
+ if(ulNumResNodes)
+ {
+ ret = 1;
+#ifdef RES_FILE_DUMP_ENABLED
+
+ _wfopen_s(&pF,wzFileName,L"wb");
+ if(pF)
+ {
+ // Dump them to pF
+ // Write dummy header
+ ResourceHeader *pRH = new ResourceHeader();
+ fwrite(pRH,sizeof(ResourceHeader),1,pF);
+ SDELETE(pRH);
+ // For each resource write header and data
+ PAL_CPP_TRY {
+ for(i=0; i < ulNumResNodes; i++)
+ {
+ /*
+ sprintf_s(szString,SZSTRING_SIZE,"// Res.# %d Type=0x%X Name=0x%X Lang=0x%X DataOffset=0x%X DataLength=%d",
+ i+1,
+ g_prResNodePtr[i]->ResHdr.dwTypeID,
+ g_prResNodePtr[i]->ResHdr.dwNameID,
+ g_prResNodePtr[i]->ResHdr.wLangID,
+ VAL32(g_prResNodePtr[i]->DataEntry.OffsetToData),
+ VAL32(g_prResNodePtr[i]->DataEntry.Size));
+ printLine(NULL,szString);
+ */
+ g_prResNodePtr[i]->Save(pF);
+ SDELETE(g_prResNodePtr[i]);
+ }
+ }
+ PAL_CPP_CATCH_ALL {
+ ret= 0xDFFFFFFF;
+ }
+ PAL_CPP_ENDTRY
+ fclose(pF);
+ }// end if file opened
+ else ret = 0xEFFFFFFF;
+#else
+ // Dump to text, using wzFileName as GUICookie
+ //char szString[4096];
+ void* GUICookie = (void*)wzFileName;
+ BYTE* pbData;
+ printLine(GUICookie,"");
+ sprintf(szString,"// ========== Win32 Resource Entries (%d) ========",ulNumResNodes);
+ for(i=0; i < ulNumResNodes; i++)
+ {
+ printLine(GUICookie,"");
+ sprintf(szString,"// Res.# %d Type=0x%X Name=0x%X Lang=0x%X DataOffset=0x%X DataLength=%d",
+ i+1,
+ g_prResNodePtr[i]->ResHdr.dwTypeID,
+ g_prResNodePtr[i]->ResHdr.dwNameID,
+ g_prResNodePtr[i]->ResHdr.wLangID,
+ VAL32(g_prResNodePtr[i]->DataEntry.OffsetToData),
+ VAL32(g_prResNodePtr[i]->DataEntry.Size));
+ printLine(GUICookie,szString);
+ if(g_pPELoader->getVAforRVA(VAL32(g_prResNodePtr[i]->DataEntry.OffsetToData), (void **) &pbData))
+ {
+ strcat(g_szAsmCodeIndent,"// ");
+ strcpy(szString,g_szAsmCodeIndent);
+ DumpByteArray(szString,pbData,VAL32(g_prResNodePtr[i]->DataEntry.Size),GUICookie);
+ printLine(GUICookie,szString);
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-4] = 0;
+ }
+ SDELETE(g_prResNodePtr[i]);
+ }
+ ret = 1;
+#endif
+ } // end if there are nodes
+ }// end if got ptr to resource
+ else ret = 0xFFFFFFFF;
+ } // end if there is resource
+ else ret = 0;
+
+ return ret;
+}
diff --git a/src/ildasm/event.bmp b/src/ildasm/event.bmp
new file mode 100644
index 0000000000..99c3357d95
--- /dev/null
+++ b/src/ildasm/event.bmp
Binary files differ
diff --git a/src/ildasm/exe/ildasm.nativeproj b/src/ildasm/exe/ildasm.nativeproj
new file mode 100644
index 0000000000..01a18a174c
--- /dev/null
+++ b/src/ildasm/exe/ildasm.nativeproj
@@ -0,0 +1,71 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="dogfood">
+ <!--Modify this before importing the clr-wide settings-->
+ <PropertyGroup>
+ <ClrDontIncludeAllInterfaces>true</ClrDontIncludeAllInterfaces>
+ </PropertyGroup>
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.props" />
+ <!--Leaf project Properties-->
+ <PropertyGroup>
+ <UseAtl>true</UseAtl>
+ <AtlVer>mfc</AtlVer>
+ <EntryPoint>winmain</EntryPoint>
+ <LinkSubsystem>console</LinkSubsystem>
+
+ <!-- PCH baloney -->
+ <EnableCxxPCHHeaders>true</EnableCxxPCHHeaders>
+ <PCHCompile>..\ildasmpch.cpp</PCHCompile>
+ <PCHHeader>ildasmpch.h</PCHHeader>
+
+ <CDefines>$(CDefines);__TODO_PORT_TO_WRAPPERS__</CDefines>
+ <LinkUseCMT>true</LinkUseCMT>
+ <UseMsvcrt>false</UseMsvcrt>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <UserIncludes>$(UserIncludes);.;$(_NTDRIVE)$(_NTROOT)\ndp\clr\src\tools\metainfo</UserIncludes>
+ <CDefines>$(CDefines);UNICODE;_UNICODE;FEATURE_NO_HOST;__ILDASM__</CDefines>
+ <OutputName>ildasm</OutputName>
+ <FileToMarkForSigning>$(BinariesDirectory)\ildasm.exe</FileToMarkForSigning>
+ <TargetType>PROGRAM</TargetType>
+ <LinkGenerateManifest/>
+ </PropertyGroup>
+
+ <!--Leaf Project Items-->
+ <ItemGroup>
+ <LinkPreCrtLibs Include="$(ClrLibPath)\utilcodestaticnohost.lib">
+ <ProjectReference>$(ClrSrcDirectory)utilcode\staticnohost\staticnohost.nativeproj</ProjectReference>
+ </LinkPreCrtLibs>
+ <LinkPreCrtLibs Include="$(ClrLibPath)\MDHotData.lib">
+ <ProjectReference>$(ClrSrcDirectory)md\hotdata\full\mdhotdata.nativeproj</ProjectReference>
+ </LinkPreCrtLibs>
+ <TargetLib Include="$(ClrLibPath)\corguids.lib">
+ <ProjectReference>$(ClrSrcDirectory)inc\corguids.nativeproj</ProjectReference>
+ </TargetLib>
+ <TargetLib Include="$(SdkLibPath)\mscoree.lib" />
+ <TargetLib Include="$(SdkLibPath)\gdi32.lib" />
+ <TargetLib Include="$(SdkLibPath)\comctl32.lib" />
+ <TargetLib Include="$(SdkLibPath)\comdlg32.lib" />
+ <TargetLib Include="$(SdkLibPath)\ole32.lib" />
+ <TargetLib Include="$(SdkLibPath)\uuid.lib" />
+ <TargetLib Include="$(SdkLibPath)\user32.lib" />
+ <TargetLib Include="$(SdkLibPath)\shell32.lib" />
+ <TargetLib Include="$(SdkLibPath)\oleaut32.lib" />
+ <TargetLib Include="$(SdkLibPath)\htmlhelp.lib" />
+ </ItemGroup>
+ <ItemGroup>
+ <RCResourceFile Include="..\dasm.rc" />
+ <CppCompile Include="..\dasm_pr.cpp" />
+ <CppCompile Include="..\gui.cpp" />
+ <CppCompile Include="..\dis.cpp" />
+ <CppCompile Include="..\dman.cpp" />
+ <CppCompile Include="..\dres.cpp" />
+ <CppCompile Include="..\ceeload.cpp" />
+ <CppCompile Include="..\dasm_formatType.cpp" />
+ <CppCompile Include="..\dasm_mi.cpp" />
+ <CppCompile Include="..\dasm_sz.cpp" />
+ <CppCompile Include="..\dasm.cpp" />
+ <CppCompile Include="..\windasm.cpp" />
+ <DataFile Include="..\ildasm.chm" />
+ </ItemGroup>
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.targets" />
+</Project>
diff --git a/src/ildasm/field.bmp b/src/ildasm/field.bmp
new file mode 100644
index 0000000000..aa09fb2f54
--- /dev/null
+++ b/src/ildasm/field.bmp
Binary files differ
diff --git a/src/ildasm/gui.cpp b/src/ildasm/gui.cpp
new file mode 100644
index 0000000000..14131a83a3
--- /dev/null
+++ b/src/ildasm/gui.cpp
@@ -0,0 +1,4013 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include "ildasmpch.h"
+
+#include "debugmacros.h"
+#include "corpriv.h"
+#include "ceeload.h"
+#include "dasmgui.h"
+#include "dasmenum.hpp"
+#include "dis.h"
+#include "resource.h"
+#include "gui.h"
+#include "formattype.h"
+#include "..\tools\metainfo\mdinfo.h"
+#include <NdpVersion.h>
+
+struct MemberInfo {
+ const char *pszMemberName;
+ DWORD dwAttrs;
+ ULONG cComSig;
+ PCCOR_SIGNATURE pComSig;
+ mdToken token;
+};
+
+int __cdecl memberCmp(const void *elem1, const void *elem2 ) {
+ MemberInfo* mem1 = (MemberInfo*) elem1;
+ MemberInfo* mem2 = (MemberInfo*) elem2;
+ return(strcmp(mem1->pszMemberName, mem2->pszMemberName));
+}
+
+//
+// Global buffer, filled by AddOPCode
+//
+char *GlobalBuffer = new (nothrow) char[65535];
+ULONG GlobalBufferLen = 65535;
+ULONG InGlobalBuffer;
+//
+// Global HINSTANCE
+//
+extern HINSTANCE g_hInstance;
+HINSTANCE g_hResources;
+
+//
+// Main window
+//
+HWND g_hwndMain;
+
+//
+// Treeview for main window
+//
+HWND g_hwndTreeView;
+
+//
+// Treeview class full name / partial name switch
+//
+BOOL g_fTreeViewFCN = TRUE;
+
+//
+// Assembly info window (child of main)
+//
+HWND g_hwndAsmInfo;
+extern IMetaDataAssemblyImport* g_pAssemblyImport;
+void DumpAssembly(void* GUICookie, BOOL fFullDump);
+IMetaDataAssemblyImport* GetAssemblyImport(void* GUICookie);
+
+//
+// Global image list
+//
+HIMAGELIST g_hImageList;
+
+//
+// Menu for main window
+//
+HMENU g_hMenu, g_hMetaInfoMenu, g_hFileMenu, g_hViewMenu, g_hFontMenu;
+
+//
+// Flags
+//
+BOOL g_fFullMemberInfo = FALSE; // Show member type? (method, field, event, prop)
+BOOL g_fSortByName = TRUE; // Sort members in tree?
+//
+// Module name of loaded DLL/EXE
+//
+const char *g_pszModule;
+
+//
+// Interlocked variable for setting char dimensions once
+//
+long g_SetCharDimensions = 0;
+
+unsigned g_uFindReplaceMsg = 0;
+HWND g_hFindText = NULL;
+//
+// Bitmap handles
+//
+HBITMAP g_hBitmaps[LAST_IMAGE_INDEX];
+
+//
+// Root item for listview
+//
+HTREEITEM g_hRoot;
+
+// Global graphics
+HBRUSH g_hWhiteBrush;
+HFONT g_hFixedFont;
+HFONT g_hSmallFont;
+HBITMAP g_hMethodBmp, g_hFieldBmp, g_hClassBmp, g_hStaticMethodBmp, g_hStaticFieldBmp, g_hQuestionBmp;
+LOGFONTW g_strLogFontTree, g_strLogFontDasm;
+CHOOSEFONTW g_strChFontTree, g_strChFontDasm;
+
+struct GUI_Info
+{
+ LOGFONTW* plfTree;
+ LOGFONTW* plfDasm;
+ int x;
+ int y;
+ int w;
+ int h;
+};
+
+GUI_Info guiInfo = {&g_strLogFontTree, &g_strLogFontDasm, CW_USEDEFAULT, CW_USEDEFAULT, 400,600};
+
+// Text info
+long g_Height;
+long g_MaxCharWidth;
+
+// Currently selected treeview item
+HTREEITEM g_CurSelItem;
+
+extern IMAGE_COR20_HEADER * g_CORHeader;
+extern BOOL g_fDumpTokens;
+extern BOOL g_fShowBytes;
+extern BOOL g_fShowSource;
+extern BOOL g_fTryInCode;
+extern BOOL g_fQuoteAllNames;
+extern BOOL g_fCAVerbal;
+extern BOOL g_fShowProgressBar;
+extern BOOL g_fDumpHeader;
+extern BOOL g_fDumpAsmCode;
+extern BOOL g_fDumpTokens;
+extern BOOL g_fDumpStats;
+extern BOOL g_fDumpMetaInfo;
+extern BOOL g_fDumpClassList;
+extern BOOL g_fInsertSourceLines;
+
+extern BOOL g_fLimitedVisibility;
+extern BOOL g_fHidePub;
+extern BOOL g_fHidePriv;
+extern BOOL g_fHideFam;
+extern BOOL g_fHideAsm;
+extern BOOL g_fHideFAA;
+extern BOOL g_fHideFOA;
+extern BOOL g_fHidePrivScope;
+extern BOOL g_fTDC;
+
+extern char g_szInputFile[]; // in UTF-8
+extern WCHAR g_wszFullInputFile[]; // in UTF-16
+extern ULONG g_ulMetaInfoFilter;
+extern char g_szOutputFile[]; // in UTF-8
+extern DWORD g_Mode;
+extern FILE* g_pFile;
+extern HINSTANCE g_hInstance;
+
+extern unsigned g_uCodePage;
+extern unsigned g_uConsoleCP;
+DWORD DumpResourceToFile(__in __nullterminated WCHAR* wzFileName); // see DRES.CPP
+//
+// Functions
+//
+BOOL RegisterWindowClasses();
+HWND CreateTreeView(HWND hwndParent);
+HTREEITEM AddOneItem(HTREEITEM hParent, const char *pszText, HTREEITEM hInsAfter, int iImage, HWND hwndTree, BOOL fExpanded);
+HWND GUIDisassemble(mdTypeDef cl, mdToken mbMember, __in __nullterminated char *pszWindowTitle);
+HTREEITEM AddClassToTreeView(HTREEITEM hParent, mdTypeDef cl);
+void AddGlobalFunctions();
+void CreateMenus();
+Namespace_t* FindNamespace(const char *pszNamespace);
+void GUICleanupClassItems();
+void SelectClassByName(__in __nullterminated char *pszFQName);
+void SelectClassByToken(mdToken tk);
+void DumpTreeItem(HTREEITEM hItem, FILE* pFile, __inout __nullterminated WCHAR* szIndent);
+HTREEITEM FindCreateNamespaceRoot(const char *pszNamespace);
+FILE* OpenOutput(__in __nullterminated const char* szFileName);
+FILE* OpenOutput(__in __nullterminated const WCHAR* wzFileName);
+
+#undef SendMessageW
+#undef PostMessageW
+#undef CreateWindowExW
+#undef DefWindowProcW
+#undef RegisterClassExW
+#undef RegisterClassW
+#undef SetWindowTextW
+#undef GetWindowTextW
+#undef MessageBoxW
+
+char* UtfToAnsi(__in __nullterminated const char* sz) { return UnicodeToAnsi(UtfToUnicode(sz));}
+
+LRESULT CALLBACK DisassemblyWndProc(
+ HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam
+);
+
+LRESULT CALLBACK MainWndProc(
+ HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam
+);
+
+ClassItem_t *AddClassToGUI(mdTypeDef cl, UINT uImageIndex,
+ const char *pszNamespace, const char *pszClassName, DWORD cSubItems, HTREEITEM *phRoot);
+
+void AddMethodToGUI(
+ mdTypeDef cl,
+ ClassItem_t * pClassItem,
+ const char *pszNamespace,
+ const char *pszClassName,
+ const char *pszMethodName,
+ PCCOR_SIGNATURE pComSig,
+ unsigned cComSig,
+ mdMethodDef mbMethod,
+ DWORD dwAttrs
+);
+
+void AddFieldToGUI(
+ mdTypeDef cl,
+ ClassItem_t *pClassItem,
+ const char *pszNamespace,
+ const char *pszClassName,
+ const char *pszFieldName,
+ const char *pszSignature,
+ mdFieldDef mbField,
+ DWORD dwAttrs
+);
+
+void AddEventToGUI(
+ mdTypeDef cl,
+ ClassItem_t *pClassItem,
+ const char *pszNamespace,
+ const char *pszClassName,
+ DWORD dwClassAttrs,
+ mdEvent mbEvent
+);
+
+void AddPropToGUI(
+ mdTypeDef cl,
+ ClassItem_t *pClassItem,
+ const char *pszNamespace,
+ const char *pszClassName,
+ DWORD dwClassAttrs,
+ mdProperty mbProp
+);
+
+DynamicArray<DisasmBox_t> *g_DisasmBox;
+DWORD g_NumDisasmBoxes=0;
+
+DynamicArray<ClassItem_t> *g_ClassItemList;
+DWORD g_NumClassItems=0;
+
+DynamicArray<Namespace_t> *g_NamespaceList;
+DWORD g_NumNamespaces=0;
+
+
+ClassItem_t *FindClassItem(HTREEITEM hItem);
+ClassItem_t *FindClassItem(mdTypeDef cl);
+ClassItem_t *FindClassItem(__in_opt __nullterminated char *pszNamespace, __in __nullterminated char *pszName);
+
+// Find disasm box among opened by class and member tokens
+DisasmBox_t* FindDisasmBox(mdToken tkClass, mdToken tkMember)
+{
+ for (DWORD i = 0; i < g_NumDisasmBoxes; i++)
+ {
+ if (((*g_DisasmBox)[i].tkClass == tkClass)
+ &&((*g_DisasmBox)[i].tkMember == tkMember))
+ return &(*g_DisasmBox)[i];
+ }
+ return NULL;
+}
+// Find disasm box among opened by the container hwnd
+DisasmBox_t* FindDisasmBoxByHwnd(HWND hwndContainer)
+{
+ for (DWORD i = 0; i < g_NumDisasmBoxes; i++)
+ {
+ if ((*g_DisasmBox)[i].hwndContainer == hwndContainer)
+ return &(*g_DisasmBox)[i];
+ }
+ return NULL;
+}
+//
+// Add a new disassembly box to the global list of them
+//
+// hwndContainer - parent window
+// hwndChild - listview
+//
+void AddDisasmBox(HWND hwndContainer, HWND hwndChild, HMENU hMenu, mdToken tkClass, mdToken tkMember)
+{
+ (*g_DisasmBox)[g_NumDisasmBoxes].hwndContainer = hwndContainer;
+ (*g_DisasmBox)[g_NumDisasmBoxes].hwndChild = hwndChild;
+ (*g_DisasmBox)[g_NumDisasmBoxes].hMenu = hMenu;
+ (*g_DisasmBox)[g_NumDisasmBoxes].tkClass = tkClass;
+ (*g_DisasmBox)[g_NumDisasmBoxes].tkMember = tkMember;
+ (*g_DisasmBox)[g_NumDisasmBoxes].strFR.lStructSize = sizeof(FINDREPLACEW);
+ (*g_DisasmBox)[g_NumDisasmBoxes].strFR.hwndOwner = hwndContainer;
+ (*g_DisasmBox)[g_NumDisasmBoxes].strFR.Flags = FR_DOWN|FR_DIALOGTERM;
+ (*g_DisasmBox)[g_NumDisasmBoxes].strFR.lpstrFindWhat = (LPWSTR)((*g_DisasmBox)[g_NumDisasmBoxes].wzFind);
+ (*g_DisasmBox)[g_NumDisasmBoxes].strFR.lpstrReplaceWith = NULL;
+ (*g_DisasmBox)[g_NumDisasmBoxes].strFR.wFindWhatLen = 120;
+ (*g_DisasmBox)[g_NumDisasmBoxes].strFR.wReplaceWithLen = 0;
+ (*g_DisasmBox)[g_NumDisasmBoxes].strFR.lCustData = 0;
+ (*g_DisasmBox)[g_NumDisasmBoxes].strFR.lpfnHook = NULL;
+ (*g_DisasmBox)[g_NumDisasmBoxes].strFR.lpTemplateName = NULL;
+ g_NumDisasmBoxes++;
+}
+
+void UpdateDisasmBox(DisasmBox_t* pBox, HWND hwndContainer, HWND hwndChild, HMENU hMenu)
+{
+ pBox->hwndContainer = hwndContainer;
+ pBox->hwndChild = hwndChild;
+ pBox->hMenu = hMenu;
+ pBox->strFR.hwndOwner = hwndContainer;
+}
+//
+// Given a container window, find the associated disassembly window
+//
+HWND FindAssociatedDisassemblyListBox(HWND hwndContainer)
+{
+ DWORD i;
+
+ for (i = 0; i < g_NumDisasmBoxes; i++)
+ {
+ if ((*g_DisasmBox)[i].hwndContainer == hwndContainer)
+ return (*g_DisasmBox)[i].hwndChild;
+ }
+
+ return NULL;
+}
+
+//
+// Given a disassembly window, find the associated container window
+//
+HWND FindAssociatedDisassemblyContainer(HWND hwndChild)
+{
+ DWORD i;
+
+ for (i = 0; i < g_NumDisasmBoxes; i++)
+ {
+ if ((*g_DisasmBox)[i].hwndChild == hwndChild)
+ return (*g_DisasmBox)[i].hwndContainer;
+ }
+
+ return NULL;
+}
+
+
+void RemoveDisasmBox(HWND hwndContainer)
+{
+ DWORD i;
+
+ for (i = 0; i < g_NumDisasmBoxes; i++)
+ {
+ if ((*g_DisasmBox)[i].hwndContainer == hwndContainer)
+ {
+ memcpy(&(*g_DisasmBox)[i], &(*g_DisasmBox)[i+1], (g_NumDisasmBoxes-i-1)*sizeof(DisasmBox_t));
+ g_NumDisasmBoxes--;
+ break;
+ }
+ }
+}
+
+
+void RemoveItemsFromList()
+{
+ TreeView_DeleteAllItems(g_hwndTreeView);
+}
+
+
+BOOL RefreshList()
+{
+ GUICleanupClassItems();
+ return GUIAddItemsToList();
+}
+
+
+void GUISetModule(__in __nullterminated const char *pszModule)
+{
+ g_pszModule = pszModule;
+}
+
+
+TreeItem_t *FindClassMemberByName(ClassItem_t *pClassItem,
+ __in __nullterminated char *pszFindName,
+ __in __nullterminated char *pszFindSig)
+{
+ HRESULT hr;
+ DWORD i;
+
+ // do in two passes, fields first
+ for (i = 0; i < pClassItem->SubItems; i++)
+ {
+ TreeItem_t *pItem;
+ const char *pszMemberName;
+ const char *pszMemberSig;
+ DWORD dwAttrs;
+
+ CQuickBytes qbMemberSig;
+
+ PCCOR_SIGNATURE pComSig;
+ ULONG cComSig;
+
+
+ pItem = &pClassItem->pMembers[i];
+ if (pItem->Discriminator != TREEITEM_TYPE_MEMBER)
+ continue;
+
+ if (TypeFromToken(pItem->mbMember) == mdtMethodDef)
+ {
+ if (FAILED(g_pImport->GetMethodDefProps(pItem->mbMember, &dwAttrs)))
+ {
+ continue;
+ }
+ if (FAILED(g_pImport->GetNameOfMethodDef(pItem->mbMember, &pszMemberName)))
+ {
+ continue;
+ }
+ if (FAILED(g_pImport->GetSigOfMethodDef(pItem->mbMember, &cComSig, &pComSig)))
+ {
+ continue;
+ }
+ }
+ else
+ {
+ if (FAILED(g_pImport->GetFieldDefProps(pItem->mbMember, &dwAttrs)))
+ {
+ continue;
+ }
+ if (FAILED(g_pImport->GetNameOfFieldDef(pItem->mbMember, &pszMemberName)))
+ {
+ continue;
+ }
+ if (FAILED(g_pImport->GetSigOfFieldDef(pItem->mbMember, &cComSig, &pComSig)))
+ {
+ continue;
+ }
+ }
+ MAKE_NAME_IF_NONE(pszMemberName,pItem->mbMember);
+ qbMemberSig.Shrink(0);
+ pszMemberSig = PrettyPrintSig(pComSig, cComSig, "", &qbMemberSig, g_pImport,NULL);
+
+ // @todo: GUI IL is so that NDView can call into DASM with/GUI; NDView uses Reflection API
+ // which doesn't let us get a valid signature.
+ // If GUI IL only, then ignore signature if it's NULL
+ if (IsGuiILOnly()) {
+ if (!strcmp(pszMemberName, pszFindName)) {
+ if ((pszFindSig != NULL) && strcmp(pszMemberSig, pszFindSig)) continue;
+ return pItem;
+ }
+ } else {
+ if (!strcmp(pszMemberName, pszFindName) && !strcmp(pszMemberSig, pszFindSig))
+ return pItem;
+ }
+ }
+
+ return NULL;
+}
+
+// Kick of a disassembly window
+// Return TRUE if window opened ok, and FALSE if there's an error
+BOOL DisassembleMemberByName(__in __nullterminated char *pszClassName,
+ __in __nullterminated char *pszMemberName,
+ __in_opt __nullterminated char *pszSig)
+{
+ char szClassName[MAX_CLASSNAME_LENGTH];
+ char szClassNamespace[MAX_CLASSNAME_LENGTH];
+ char *pszClassNamespace;
+ char *p;
+
+ p = ns::FindSep(pszClassName);
+ if (p == NULL)
+ {
+ strcpy_s(szClassName, MAX_CLASSNAME_LENGTH,pszClassName);
+ pszClassNamespace = NULL;
+ }
+ else
+ {
+ strncpy_s(szClassNamespace, MAX_CLASSNAME_LENGTH, pszClassName, p - pszClassName);
+ szClassNamespace[ p - pszClassName ] = '\0';
+ pszClassNamespace = szClassNamespace;
+
+ strcpy_s(szClassName, MAX_CLASSNAME_LENGTH, p+1);
+ }
+
+ ClassItem_t *pClassItem = FindClassItem(pszClassNamespace, szClassName);
+
+ if (pClassItem != NULL)
+ {
+ TreeItem_t *pTreeItem;
+
+ pTreeItem = FindClassMemberByName(pClassItem, pszMemberName, pszSig);
+
+ if (pTreeItem != NULL)
+ {
+ DWORD dwAttrs;
+ DWORD dwImplAttrs;
+
+ // What is this member?
+
+ if (TypeFromToken(pTreeItem->mbMember) == mdtMethodDef)
+ {
+ char* szText;
+ HWND fOK=NULL;
+ if (FAILED(g_pImport->GetMethodDefProps(pTreeItem->mbMember, &dwAttrs)))
+ {
+ goto ErrorHere;
+ }
+ if (FAILED(g_pImport->GetMethodImplProps(pTreeItem->mbMember, NULL, &dwImplAttrs)))
+ {
+ goto ErrorHere;
+ }
+
+ // Can't be abstract or native
+ if (IsMdAbstract(dwAttrs) || IsMiInternalCall(dwImplAttrs))
+ return FALSE;
+
+ szText = new (nothrow) char[4096];
+ if(szText)
+ {
+ TVITEMA SelItem;
+
+ // Get the name of this item so that we can title the disassembly window
+ memset(&SelItem, 0, sizeof(SelItem));
+ SelItem.mask = TVIF_TEXT;
+ SelItem.pszText = szText;
+ SelItem.hItem = pTreeItem->hItem;
+ SelItem.cchTextMax = 4095;
+
+ WCHAR* wzText = (WCHAR*)szText;
+ SendMessageW(g_hwndTreeView, TVM_GETITEMW, 0, (LPARAM) (LPTVITEMW) &SelItem);
+ unsigned L = ((unsigned)wcslen(wzText)+1)*3;
+ char* szUTFText = new (nothrow) char[L];
+ if(szUTFText)
+ {
+ memset(szUTFText,0,L);
+ WszWideCharToMultiByte(CP_UTF8,0,wzText,-1,szUTFText,L,NULL,NULL);
+ delete[] wzText;
+ szText = szUTFText;
+ }
+
+ fOK = GUIDisassemble(pClassItem->cl, pTreeItem->mbMember, szText);
+ delete[] szText;
+ }
+ if (fOK == NULL) {
+ goto ErrorHere;
+ }
+ }
+ } // endif (pTreeItem != NULL)
+ else {
+ goto ErrorHere;
+ }
+
+ } else {
+ goto ErrorHere;
+ }
+
+ return TRUE;
+
+ErrorHere:
+ char pzText[300];
+ sprintf_s(pzText, 300,RstrUTF(IDS_CANTVIEW_TX) /*"Can't view %s::%s(%s)"*/, pszClassName, pszMemberName, pszSig);
+
+ WszMessageBox(g_hwndMain, UtfToUnicode(pzText), RstrW(IDS_CANTVIEW_HD) /*"Can't View IL"*/, MB_OK | MB_ICONERROR | GetDasmMBRTLStyle() );
+
+
+ return FALSE;
+}
+
+//HTREEITEM AddInfoItemToClass(HTREEITEM hParent, ClassItem_t *pClassItem, const char *pszText, const char *pszStoredInfoText)
+HTREEITEM AddInfoItemToClass(HTREEITEM hParent, ClassItem_t *pClassItem, const char *pszText, mdToken tk)
+{
+ _ASSERTE(pClassItem->CurMember < pClassItem->SubItems);
+ pClassItem->pMembers[pClassItem->CurMember].hItem = AddOneItem(
+ pClassItem->hItem, pszText, hParent, RED_ARROW_IMAGE_INDEX, g_hwndTreeView, FALSE
+ );
+ pClassItem->pMembers[pClassItem->CurMember].Discriminator = TREEITEM_TYPE_INFO;
+ //pClassItem->pMembers[pClassItem->CurMember].pszText = (char *) pszStoredInfoText;
+ pClassItem->pMembers[pClassItem->CurMember].mbMember = tk;
+ pClassItem->CurMember++;
+
+ return pClassItem->pMembers[pClassItem->CurMember-1].hItem;
+}
+
+struct ClassDescr
+{
+ mdToken tk;
+ const char* szName;
+};
+static int __cdecl classDescrCmp(const void *op1, const void *op2)
+{
+ return strcmp(((ClassDescr*)op1)->szName,((ClassDescr*)op2)->szName);
+}
+
+unsigned AddClassesWithEncloser(mdToken tkEncloser, HTREEITEM hParent)
+{
+ unsigned i, N=0;
+ for (i = 0; i < g_NumClasses; i++)
+ {
+ if(g_cl_enclosing[i] == tkEncloser) N++;
+ }
+
+ if(N)
+ {
+ ClassDescr* rClassDescr = new (nothrow) ClassDescr[N];
+ const char *pszClassName,*pszNamespace;
+ for (i = 0, N = 0; i < g_NumClasses; i++)
+ {
+ if(g_cl_enclosing[i] == tkEncloser)
+ {
+ rClassDescr[N].tk = g_cl_list[i];
+ if (FAILED(g_pImport->GetNameOfTypeDef(g_cl_list[i], &pszClassName, &pszNamespace)))
+ {
+ pszClassName = pszNamespace = "Invalid TypeDef record";
+ }
+ // doesn't throw here, so rClassDescr doesn't leak
+ MAKE_NAME_IF_NONE(pszClassName,g_cl_list[i]);
+ rClassDescr[N].szName = pszClassName;
+ N++;
+ }
+ }
+ if(g_fSortByName) qsort(&rClassDescr[0],N,sizeof(ClassDescr),classDescrCmp);
+ for(i = 0; i < N; i++) AddClassToTreeView(hParent,rClassDescr[i].tk);
+ delete[] rClassDescr;
+ }
+ return N;
+}
+
+static int __cdecl stringCmp(const void *op1, const void *op2)
+{
+ return strcmp(*((char**)op1), *((char**)op2));
+ //return(strlen(*((char**)op1)) - strlen(*((char**)op2)));
+}
+
+UINT GetDasmMBRTLStyle() {
+ UINT RTLMessageBoxStyle = 0;
+ WCHAR* pwStr = RstrW(IDS_RTL);
+ if( wcscmp(pwStr, L"RTL_True") == 0) {
+ RTLMessageBoxStyle = 0x00080000 |0x00100000; // MB_RIGHT || MB_RTLREADING
+ }
+ return RTLMessageBoxStyle;
+}
+
+void GUIDumpAssemblyInfo()
+{
+ memset(GlobalBuffer,0,GlobalBufferLen);
+ InGlobalBuffer = 0;
+ if(g_pAssemblyImport==NULL) g_pAssemblyImport = GetAssemblyImport((void*)g_hwndAsmInfo);
+ if(g_pAssemblyImport)
+ {
+ if(g_fDumpRTF) DumpRTFPrefix((void *)g_hwndAsmInfo,FALSE);
+ DumpAssembly((void *)g_hwndAsmInfo,FALSE);
+ if(g_fDumpRTF) DumpRTFPostfix((void *)g_hwndAsmInfo);
+ }
+
+ if(g_uCodePage == 0xFFFFFFFF)
+ SendMessageW((HWND)g_hwndAsmInfo,WM_SETTEXT,0, (LPARAM)GlobalBuffer);
+ else
+ {
+ UINT32 L = (UINT32)strlen(GlobalBuffer);
+ WCHAR* wz = new (nothrow) WCHAR[L+4];
+ if(wz)
+ {
+ memset(wz,0,sizeof(WCHAR)*(L+2));
+ int x = WszMultiByteToWideChar(CP_UTF8,0,GlobalBuffer,-1,wz,L+2);
+ if(g_fDumpRTF)
+ {
+ x = (int)SendMessageA((HWND)g_hwndAsmInfo,WM_SETTEXT,0, (LPARAM)UnicodeToAnsi(wz));
+ }
+ else
+ {
+ x = (int)WszSendMessage((HWND)g_hwndAsmInfo,WM_SETTEXT,0, (LPARAM)wz);
+ }
+ delete[] wz;
+ }
+ }
+}
+
+BOOL GUIAddItemsToList()
+{
+ DWORD i,NumGlobals=0;
+ HENUMInternal hEnumMethod;
+
+ RemoveItemsFromList();
+ g_NumClassItems = 0;
+ g_NumNamespaces = 0;
+
+ g_hRoot = AddOneItem(
+ (HTREEITEM)NULL,
+ g_pszModule,
+ (HTREEITEM)TVI_ROOT,
+ FIELD_IMAGE_INDEX,
+ g_hwndTreeView,
+ TRUE
+ );
+
+ if (SUCCEEDED(g_pImport->EnumGlobalFunctionsInit(&hEnumMethod)))
+ {
+ NumGlobals = g_pImport->EnumGetCount(&hEnumMethod);
+ g_pImport->EnumClose(&hEnumMethod);
+ }
+ if (SUCCEEDED(g_pImport->EnumGlobalFieldsInit(&hEnumMethod)))
+ {
+ NumGlobals += g_pImport->EnumGetCount(&hEnumMethod);
+ g_pImport->EnumClose(&hEnumMethod);
+ }
+ (*g_ClassItemList)[0].hItem = g_hRoot;
+ (*g_ClassItemList)[0].cl = 0;
+ (*g_ClassItemList)[0].SubItems = NumGlobals+1;
+ (*g_ClassItemList)[0].CurMember = 0;
+ (*g_ClassItemList)[0].pMembers = new (nothrow) TreeItem_t[NumGlobals+1];
+ g_NumClassItems++;
+
+ //AddInfoItemToClass((HTREEITEM)TVI_ROOT, &(*g_ClassItemList)[0], " M A N I F E S T", "__MANIFEST__");
+ AddInfoItemToClass((HTREEITEM)TVI_ROOT, &(*g_ClassItemList)[0], " M A N I F E S T", 0xFFFFFFFF);
+
+ if (g_NumClasses != 0)
+ {
+ //create root namespaces
+ {
+ char** rszNamespace = new (nothrow) char*[g_NumClasses];
+ ULONG ulNamespaces=0;
+ for (i = 0; i < g_NumClasses; i++)
+ {
+ if (g_cl_enclosing[i] == mdTypeDefNil) // nested classes don't have separate namespaces
+ {
+ const char *pszClassName, *pszNameSpace;
+ if (FAILED(g_pImport->GetNameOfTypeDef(
+ g_cl_list[i],
+ &pszClassName,
+ &pszNameSpace)))
+ {
+ pszClassName = pszNameSpace = "Invalid TypeDef record";
+ }
+ if ((pszNameSpace != NULL) && (*pszNameSpace != 0))
+ {
+ rszNamespace[ulNamespaces++] = (char*)pszNameSpace;
+ }
+ }
+ }
+ if (ulNamespaces != 0)
+ {
+ qsort(&rszNamespace[0],ulNamespaces,sizeof(char*),stringCmp);
+ for(i = 0; i < ulNamespaces; i++) FindCreateNamespaceRoot(rszNamespace[i]);
+ }
+ delete[] rszNamespace;
+ }
+ AddClassesWithEncloser(mdTypeDefNil,NULL);
+ }// end if (g_NumClasses)
+ AddGlobalFunctions();
+
+ WszSendMessage(g_hwndTreeView, TVM_EXPAND, TVE_EXPAND, (LPARAM)g_hRoot);
+ EnableMenuItem(g_hMenu,(UINT)(UINT_PTR)g_hViewMenu, MF_ENABLED);
+ EnableMenuItem(g_hFileMenu,IDM_DUMP,MF_ENABLED);
+ EnableMenuItem(g_hFileMenu,IDM_DUMP_TREE,MF_ENABLED);
+ DrawMenuBar(g_hwndMain);
+
+ {
+ WszMultiByteToWideChar(CP_UTF8,0,g_szInputFile,-1,wzUniBuf,2048);
+ wcscat_s(wzUniBuf,2048,L" - IL DASM");
+ for(int cnt=0; cnt<100; cnt++)
+ {
+ SendMessageW(g_hwndMain,WM_SETTEXT, 0, (LPARAM)wzUniBuf);
+ SendMessageW(g_hwndMain,WM_GETTEXT, 2048, (LPARAM)&wzUniBuf[2048]);
+ wzUniBuf[2047]=0;
+ if(0 == wcscmp(wzUniBuf,&wzUniBuf[2048])) break;
+ }
+ }
+
+ if (IsGuiILOnly()) {
+ ShowWindow(g_hwndMain, SW_HIDE);
+ } else {
+ ShowWindow(g_hwndMain, SW_SHOW);
+ }
+ UpdateWindow(g_hwndMain);
+ //GUIDisassemble(0,0,"MANIFEST");
+ g_Mode &= ~MODE_GUI;
+ DumpManifest(NULL);
+ g_Mode |= MODE_GUI;
+
+ GUIDumpAssemblyInfo();
+
+ TreeView_SelectItem(g_hwndTreeView,g_hRoot);
+ SetFocus(g_hwndTreeView);
+ return TRUE;
+}
+
+
+//
+// Find class item by class token
+//
+ClassItem_t* ClassItemByToken(mdTypeDef cl)
+{
+ for(ULONG i=0; i < g_NumClassItems; i++)
+ {
+ if((*g_ClassItemList)[i].cl == cl) return &(*g_ClassItemList)[i];
+ }
+ return NULL;
+}
+
+// Factored out of AddClassToTreeView for its big stack consumption (AddClassToTreeView is
+// called recursively via AddClassesWithEncloser).
+static void AddClassToTreeView_PrettyPrintClass(mdTypeRef crType, LPCUTF8 pszFormat, __out_ecount(cBufferSize) char *pszBuffer, size_t cBufferSize)
+{
+ CQuickBytes out;
+ sprintf_s(pszBuffer, cBufferSize, pszFormat, PrettyPrintClass(&out, crType, g_pImport));
+}
+
+//
+// Add a class and its members
+//
+#ifdef _PREFAST_
+#pragma warning(push)
+#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
+#endif
+HTREEITEM AddClassToTreeView(HTREEITEM hParent, mdTypeDef cl)
+{
+ HRESULT hr;
+ ClassItem_t *pClassItem;
+ HTREEITEM hClassRoot;
+ HTREEITEM hNamespaceRoot = hParent;
+ HTREEITEM hPrimaryInfo;
+ HTREEITEM hLast;
+ mdToken *pMemberList = NULL;
+ HENUMInternal hEnumMethod; // enumerator for method defs
+ HENUMInternal hEnumField; // enumerator for fields
+ HENUMInternal hEnumEvent; // enumerator for events
+ HENUMInternal hEnumProp; // enumerator for properties
+ DWORD NumMembers;
+ const char *pszClassName; // name associated with this CL
+ const char *pszNamespace;
+ DWORD dwClassAttrs;
+ mdTypeRef crExtends;
+ mdInterfaceImpl ii;
+ DWORD NumInterfaces;
+ DWORD i;
+ char *szPrimaryInfo; // public class foo extends bar
+// char *szFullClassName;
+ DWORD SubItems;
+ const char *pszSuperName = NULL;
+ HENUMInternal hEnumII; // enumerator for interface impl
+ mdCustomAttribute *rCA;
+ ULONG ulCAs;
+ UINT uImageIndex = CLASS_IMAGE_INDEX;
+ BOOL bIsEnum = FALSE;
+ BOOL bIsValueType = FALSE;
+ BOOL bExtendsSysObject=FALSE;
+
+ if (FAILED(g_pImport->GetNameOfTypeDef(
+ cl,
+ &pszClassName,
+ &pszNamespace)))
+ {
+ return FALSE;
+ }
+ MAKE_NAME_IF_NONE(pszClassName,cl);
+ g_pImport->GetTypeDefProps(
+ cl,
+ &dwClassAttrs,
+ &crExtends
+ );
+ if(g_fLimitedVisibility)
+ {
+ if(g_fHidePub && (IsTdPublic(dwClassAttrs)||IsTdNestedPublic(dwClassAttrs))) return NULL;
+ if(g_fHidePriv && (IsTdNotPublic(dwClassAttrs)||IsTdNestedPrivate(dwClassAttrs))) return NULL;
+ if(g_fHideFam && IsTdNestedFamily(dwClassAttrs)) return NULL;
+ if(g_fHideAsm && IsTdNestedAssembly(dwClassAttrs)) return NULL;
+ if(g_fHideFOA && IsTdNestedFamORAssem(dwClassAttrs)) return NULL;
+ if(g_fHideFAA && IsTdNestedFamANDAssem(dwClassAttrs)) return NULL;
+ }
+ hr = g_pImport->EnumInit(
+ mdtInterfaceImpl,
+ cl,
+ &hEnumII);
+ if (FAILED(hr))
+ return FALSE;
+
+ NumInterfaces = g_pImport->EnumGetCount(&hEnumII);
+ hr = g_pImport->EnumInit(mdtMethodDef, cl, &hEnumMethod);
+ if (FAILED(hr))
+ {
+ printf("Unable to enum methods\n");
+ return FALSE;
+ }
+ NumMembers = g_pImport->EnumGetCount(&hEnumMethod);
+
+ hr = g_pImport->EnumInit(mdtFieldDef, cl, &hEnumField);
+ if (FAILED(hr))
+ {
+ g_pImport->EnumClose(&hEnumMethod);
+ printf("Unable to enum fields\n");
+ return FALSE;
+ }
+ NumMembers += g_pImport->EnumGetCount(&hEnumField);
+
+ hr = g_pImport->EnumInit(mdtEvent, cl, &hEnumEvent);
+ if (FAILED(hr))
+ {
+ g_pImport->EnumClose(&hEnumMethod);
+ g_pImport->EnumClose(&hEnumField);
+ printf("Unable to enum events\n");
+ return FALSE;
+ }
+ NumMembers += g_pImport->EnumGetCount(&hEnumEvent);
+
+ hr = g_pImport->EnumInit(mdtProperty, cl, &hEnumProp);
+ if (FAILED(hr))
+ {
+ g_pImport->EnumClose(&hEnumMethod);
+ g_pImport->EnumClose(&hEnumField);
+ g_pImport->EnumClose(&hEnumEvent);
+ printf("Unable to enum properties\n");
+ return FALSE;
+ }
+ NumMembers += g_pImport->EnumGetCount(&hEnumProp);
+ if (NumMembers > 0)
+ {
+ pMemberList = new (nothrow) mdToken[NumMembers];
+ if (pMemberList == NULL)
+ {
+ // close enum before return
+ g_pImport->EnumClose(&hEnumMethod);
+ g_pImport->EnumClose(&hEnumField);
+ g_pImport->EnumClose(&hEnumEvent);
+ g_pImport->EnumClose(&hEnumProp);
+ return FALSE;
+ }
+
+ 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);
+
+ }
+ else
+ {
+ pMemberList = NULL;
+ }
+
+ // Add class root to treeview
+ SubItems = NumMembers + NumInterfaces + 3;
+ if (!IsNilToken(crExtends))
+ {
+ LPCSTR szClassName="";
+ LPCSTR szNameSpace="";
+ SubItems++;
+ if(TypeFromToken(crExtends)==mdtTypeRef)
+ {
+ if (FAILED(g_pImport->GetNameOfTypeRef(crExtends, &szNameSpace, &szClassName)))
+ {
+ return FALSE;
+ }
+ if(!(strcmp(szNameSpace,"System") || strcmp(szClassName, "Object")))
+ {
+ SubItems--;
+ bExtendsSysObject = TRUE;
+ }
+ }
+ else if (TypeFromToken(crExtends) == mdtTypeDef)
+ {
+ if (FAILED(g_pImport->GetNameOfTypeDef(crExtends, &szClassName, &szNameSpace)))
+ {
+ return FALSE;
+ }
+ }
+
+ bIsEnum = (!strcmp(szNameSpace,"System"))&&(!strcmp(szClassName,"Enum"));
+
+ bIsValueType = (!strcmp(szNameSpace,"System"))&&(!strcmp(szClassName,"ValueType"))
+ && (strcmp(pszNamespace,"System") || strcmp(pszClassName,"Enum"));
+ }
+ {
+ HCORENUM hEnum = NULL;
+ rCA = new (nothrow) mdCustomAttribute[4096];
+ g_pPubImport->EnumCustomAttributes(&hEnum, cl, 0, rCA, 4096, &ulCAs);
+ SubItems += ulCAs;
+ g_pPubImport->CloseEnum( hEnum);
+ }
+ for (i = 0; i < g_NumClasses; i++)
+ {
+ if(g_cl_enclosing[i] == cl) SubItems++;
+ }
+
+ if(IsTdInterface(dwClassAttrs)) uImageIndex = CLASSINT_IMAGE_INDEX;
+ if(bIsValueType) uImageIndex = CLASSVAL_IMAGE_INDEX;
+ if(bIsEnum) uImageIndex = CLASSENUM_IMAGE_INDEX;
+ char *szptr1;
+ if((*pszNamespace != 0) && g_fTreeViewFCN)
+ sprintf_s(szString,SZSTRING_SIZE,"%s.",pszNamespace);
+ else
+ szString[0] = 0;
+ strcat_s(szString,SZSTRING_SIZE,pszClassName);
+ szptr1 = &szString[strlen(szString)];
+ // Count the type parameters -- could be too many for GUI
+ DWORD NumTyPars;
+ mdGenericParam tkTyPar;
+ HCORENUM hEnumTyPar = NULL;
+ unsigned jj;
+
+ for(jj=0;
+ SUCCEEDED(g_pPubImport->EnumGenericParams(&hEnumTyPar, cl, &tkTyPar, 1, &NumTyPars))
+ && (NumTyPars != 0); jj++);
+
+ if (jj > 0)
+ {
+ if(jj > 16)
+ szptr1 += sprintf_s(szptr1,SZSTRING_REMAINING_SIZE(szptr1),"%s%d type parameters%s",LTN(),jj,GTN());
+ else
+ DumpGenericPars(szString,cl);
+
+ uImageIndex = CLASS_GEN_IMAGE_INDEX;
+ if(IsTdInterface(dwClassAttrs)) uImageIndex = CLASSINT_GEN_IMAGE_INDEX;
+ if(bIsValueType) uImageIndex = CLASSVAL_GEN_IMAGE_INDEX;
+ if(bIsEnum) uImageIndex = CLASSENUM_GEN_IMAGE_INDEX;
+ }
+
+ pClassItem = AddClassToGUI(cl, uImageIndex, pszNamespace, szString, SubItems, &hNamespaceRoot);
+ if (pClassItem == NULL)
+ return FALSE;
+
+ hClassRoot = pClassItem->hItem;
+
+ const size_t BUFFER_SIZE = 8192;
+ szPrimaryInfo = new (nothrow) char[BUFFER_SIZE];
+ strcpy_s(szPrimaryInfo, BUFFER_SIZE,".class ");
+
+ if (IsTdInterface(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "interface ");
+ //else if (IsTdUnmanagedValueType(dwClassAttrs)) strcat(szPrimaryInfo, "not_in_gc_heap value ");
+ else if (bIsValueType) strcat_s(szPrimaryInfo, BUFFER_SIZE, "value ");
+ else if (bIsEnum) strcat_s(szPrimaryInfo, BUFFER_SIZE, "enum ");
+
+ if (IsTdPublic(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "public ");
+ if (IsTdNotPublic(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "private ");
+ if (IsTdNestedPublic(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "nested public ");
+ if (IsTdNestedPrivate(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "nested private ");
+ if (IsTdNestedFamily(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "nested family ");
+ if (IsTdNestedAssembly(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "nested assembly ");
+ if (IsTdNestedFamANDAssem(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "nested famandassem ");
+ if (IsTdNestedFamORAssem(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "nested famorassem ");
+ if (IsTdAbstract(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "abstract ");
+ if (IsTdAutoLayout(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "auto ");
+ if (IsTdSequentialLayout(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "sequential ");
+ if (IsTdExplicitLayout(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "explicit ");
+ if (IsTdAnsiClass(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "ansi ");
+ if (IsTdUnicodeClass(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "unicode ");
+ if (IsTdAutoClass(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "autochar ");
+ if (IsTdImport(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "import ");
+ if (IsTdWindowsRuntime(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "windowsruntime ");
+ if (IsTdSerializable(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "serializable ");
+// if (IsTdEnum(dwClassAttrs)) strcat(szPrimaryInfo, "enum ");
+ if (IsTdSealed(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "sealed ");
+ if (IsTdBeforeFieldInit(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "beforefieldinit ");
+ if (IsTdSpecialName(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "specialname ");
+ if (IsTdRTSpecialName(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "rtspecialname ");
+
+ if(g_fDumpTokens) sprintf_s(&szPrimaryInfo[strlen(szPrimaryInfo)], BUFFER_SIZE - strlen(szPrimaryInfo)," /*%08X*/",cl);
+ hPrimaryInfo = AddInfoItemToClass(hClassRoot, pClassItem, szPrimaryInfo, NULL);
+ hLast = hPrimaryInfo;
+ // Now add nodes for extends, implements
+ if (!IsNilToken(crExtends))
+ {
+ if (!bExtendsSysObject)
+ {
+ AddClassToTreeView_PrettyPrintClass(crExtends, " extends %s ", szPrimaryInfo, BUFFER_SIZE);
+ hLast = AddInfoItemToClass(hLast, pClassItem, szPrimaryInfo, crExtends);
+ }
+ }
+
+ if (NumInterfaces > 0)
+ {
+ for (i=0; g_pImport->EnumNext(&hEnumII, &ii); i++)
+ {
+ mdTypeRef crInterface;
+
+ if (FAILED(g_pImport->GetTypeOfInterfaceImpl(ii, &crInterface)))
+ {
+ printf("Unable to get information about interface implementation\n");
+ return FALSE;
+ }
+ {
+ AddClassToTreeView_PrettyPrintClass(crInterface, " implements %s ", szPrimaryInfo, BUFFER_SIZE);
+ hLast = AddInfoItemToClass(hLast, pClassItem, szPrimaryInfo, crInterface);
+ }
+ }
+
+ // The assertion will fire if the enumerator is bad
+ _ASSERTE(NumInterfaces == i);
+
+ // close the enumerator
+ g_pImport->EnumClose(&hEnumII);
+ }
+ delete[] szPrimaryInfo;
+
+ BOOL fDumpRTF = g_fDumpRTF;
+ g_fDumpRTF = FALSE;
+ // add info entries for custom attributes
+ for(i = 0; i < ulCAs; i++)
+ {
+ char* pc;
+ memset(GlobalBuffer,0,GlobalBufferLen);
+ InGlobalBuffer = 0;
+ DumpCustomAttribute(rCA[i],(void *)g_hwndTreeView,false);
+ if(pc = strchr(GlobalBuffer,'\r')) strcpy_s(pc,6," ..."); // until the first <CR> only
+ //hLast = AddInfoItemToClass(hLast, pClassItem, GlobalBuffer, "#####"); // this "name" is guaranteed to be unique!
+ hLast = AddInfoItemToClass(hLast, pClassItem, GlobalBuffer, rCA[i]);
+ }
+ delete[] rCA;
+
+ // Re-fetch the current class item ptr, dynamic array may have shifted
+ pClassItem = ClassItemByToken(cl);
+
+ // Add nested classes
+ AddClassesWithEncloser(cl,pClassItem->hItem);
+ pClassItem = ClassItemByToken(cl);
+
+ MemberInfo* members = NULL;
+ if (NumMembers != 0)
+ {
+ members = new (nothrow) MemberInfo[NumMembers];
+ if (members == NULL)
+ {
+ if (pMemberList != NULL) delete[] pMemberList;
+ return FALSE;
+ }
+ }
+ // do in four passes, fields first
+ MemberInfo* curMem = members;
+ for (i = 0; i < NumMembers; i++)
+ {
+ if (TypeFromToken(pMemberList[i]) == mdtFieldDef)
+ {
+ curMem->token = pMemberList[i];
+ if (FAILED(g_pImport->GetFieldDefProps(pMemberList[i], &curMem->dwAttrs)))
+ {
+ printf("Invalid FieldDef %08X record\n", pMemberList[i]);
+ delete []members;
+ delete []pMemberList;
+ return FALSE;
+ }
+ if (FAILED(g_pImport->GetNameOfFieldDef(pMemberList[i], &curMem->pszMemberName)))
+ {
+ printf("Invalid FieldDef %08X record\n", pMemberList[i]);
+ delete []members;
+ delete []pMemberList;
+ return FALSE;
+ }
+ MAKE_NAME_IF_NONE(curMem->pszMemberName,pMemberList[i]);
+ if (FAILED(g_pImport->GetSigOfFieldDef(pMemberList[i], &curMem->cComSig, &curMem->pComSig)))
+ {
+ printf("Invalid FieldDef %08X record\n", pMemberList[i]);
+ delete []members;
+ delete []pMemberList;
+ return FALSE;
+ }
+ curMem++;
+ }
+ else break;
+ }
+
+ MemberInfo* endMem = curMem;
+ if (g_fSortByName) qsort(members, endMem - members, sizeof MemberInfo, memberCmp);
+
+ for (curMem = members; curMem < endMem;curMem++)
+ {
+ if (g_fLimitedVisibility)
+ {
+ if(g_fHidePub && IsFdPublic(curMem->dwAttrs)) continue;
+ if(g_fHidePriv && IsFdPrivate(curMem->dwAttrs)) continue;
+ if(g_fHideFam && IsFdFamily(curMem->dwAttrs)) continue;
+ if(g_fHideAsm && IsFdAssembly(curMem->dwAttrs)) continue;
+ if(g_fHideFOA && IsFdFamORAssem(curMem->dwAttrs)) continue;
+ if(g_fHideFAA && IsFdFamANDAssem(curMem->dwAttrs)) continue;
+ if(g_fHidePrivScope && IsFdPrivateScope(curMem->dwAttrs)) continue;
+ }
+ AddFieldToGUI(cl, pClassItem, pszNamespace, pszClassName, curMem->pszMemberName, NULL, curMem->token, curMem->dwAttrs);
+ }
+
+ // methods second
+ curMem = members;
+ for (; i < NumMembers; i++)
+ {
+ if (TypeFromToken(pMemberList[i]) == mdtMethodDef)
+ {
+ curMem->token = pMemberList[i];
+ if (FAILED(g_pImport->GetMethodDefProps(pMemberList[i], &curMem->dwAttrs)))
+ {
+ printf("Invalid MethodDef %08X record\n", pMemberList[i]);
+ delete []members;
+ delete []pMemberList;
+ return FALSE;
+ }
+
+ if (FAILED(g_pImport->GetNameOfMethodDef(pMemberList[i], &curMem->pszMemberName)))
+ {
+ printf("Invalid MethodDef %08X record\n", pMemberList[i]);
+ delete []members;
+ delete []pMemberList;
+ return FALSE;
+ }
+ MAKE_NAME_IF_NONE(curMem->pszMemberName,pMemberList[i]);
+ if (FAILED(g_pImport->GetSigOfMethodDef(pMemberList[i], &curMem->cComSig, &curMem->pComSig)))
+ {
+ printf("Invalid MethodDef %08X record\n", pMemberList[i]);
+ delete []members;
+ delete []pMemberList;
+ return FALSE;
+ }
+ curMem++;
+ }
+ else break;
+ }
+
+ endMem = curMem;
+ if (g_fSortByName) qsort(members, endMem - members, sizeof MemberInfo, memberCmp);
+
+ for (curMem = members; curMem < endMem;curMem++)
+ {
+ if (g_fLimitedVisibility)
+ {
+ if(g_fHidePub && IsMdPublic(curMem->dwAttrs)) continue;
+ if(g_fHidePriv && IsMdPrivate(curMem->dwAttrs)) continue;
+ if(g_fHideFam && IsMdFamily(curMem->dwAttrs)) continue;
+ if(g_fHideAsm && IsMdAssem(curMem->dwAttrs)) continue;
+ if(g_fHideAsm && g_fHideFam && IsMdFamORAssem(curMem->dwAttrs)) continue;
+ if(g_fHideFAA && IsMdFamANDAssem(curMem->dwAttrs)) continue;
+ if(g_fHidePrivScope && IsMdPrivateScope(curMem->dwAttrs)) continue;
+ }
+ AddMethodToGUI(cl, pClassItem, pszNamespace, pszClassName, curMem->pszMemberName, curMem->pComSig, curMem->cComSig, curMem->token, curMem->dwAttrs);
+ }
+ // events third
+ curMem = members;
+ for (; i < NumMembers; i++)
+ {
+ if (TypeFromToken(pMemberList[i]) == mdtEvent)
+ {
+ curMem->token = pMemberList[i];
+ if (FAILED(g_pImport->GetEventProps(
+ curMem->token,
+ &curMem->pszMemberName,
+ &curMem->dwAttrs,
+ (mdToken *)&curMem->pComSig)))
+ {
+ curMem->pszMemberName = "Invalid Event record";
+ curMem->dwAttrs = 0;
+ curMem->pComSig = (PCCOR_SIGNATURE)mdTypeDefNil;
+ }
+ MAKE_NAME_IF_NONE(curMem->pszMemberName,pMemberList[i]);
+ curMem++;
+ }
+ else break;
+ }
+
+ endMem = curMem;
+ if (g_fSortByName) qsort(members, endMem - members, sizeof MemberInfo, memberCmp);
+ curMem = members;
+ while (curMem < endMem)
+ {
+ if (g_fLimitedVisibility)
+ {
+ HENUMInternal hAssoc;
+ unsigned nAssoc;
+ if (FAILED(g_pImport->EnumAssociateInit(curMem->token,&hAssoc)))
+ {
+ continue;
+ }
+ if (nAssoc = hAssoc.m_ulCount)
+ {
+ NewArrayHolder<ASSOCIATE_RECORD> rAssoc = new (nothrow) ASSOCIATE_RECORD[nAssoc];
+ if (FAILED(g_pImport->GetAllAssociates(&hAssoc,rAssoc,nAssoc)))
+ {
+ continue;
+ }
+
+ for (unsigned i=0; i < nAssoc;i++)
+ {
+ if (TypeFromToken(rAssoc[i].m_memberdef) == mdtMethodDef)
+ {
+ DWORD dwAttrs;
+ if (FAILED(g_pImport->GetMethodDefProps(rAssoc[i].m_memberdef, &dwAttrs)))
+ {
+ continue;
+ }
+ if(g_fHidePub && IsMdPublic(dwAttrs)) continue;
+ if(g_fHidePriv && IsMdPrivate(dwAttrs)) continue;
+ if(g_fHideFam && IsMdFamily(dwAttrs)) continue;
+ if(g_fHideAsm && IsMdAssem(dwAttrs)) continue;
+ if(g_fHideFOA && IsMdFamORAssem(dwAttrs)) continue;
+ if(g_fHideFAA && IsMdFamANDAssem(dwAttrs)) continue;
+ if(g_fHidePrivScope && IsMdPrivateScope(dwAttrs)) continue;
+ }
+ AddEventToGUI(cl, pClassItem, pszNamespace, pszClassName, dwClassAttrs, curMem->token);
+ break;
+ }
+ }
+ g_pImport->EnumClose(&hAssoc);
+ }
+ else AddEventToGUI(cl, pClassItem, pszNamespace, pszClassName, dwClassAttrs, curMem->token);
+ curMem++;
+ }
+ // properties fourth
+ curMem = members;
+ for (; i < NumMembers; i++)
+ {
+ if (TypeFromToken(pMemberList[i]) == mdtProperty)
+ {
+ curMem->token = pMemberList[i];
+ if (FAILED(g_pImport->GetPropertyProps(
+ curMem->token,
+ &curMem->pszMemberName,
+ &curMem->dwAttrs,
+ &curMem->pComSig,
+ &curMem->cComSig)))
+ {
+ curMem->pszMemberName = "Invalid Property record";
+ curMem->dwAttrs = 0;
+ curMem->pComSig = NULL;
+ curMem->cComSig = 0;
+ }
+ MAKE_NAME_IF_NONE(curMem->pszMemberName,pMemberList[i]);
+ curMem++;
+ }
+ }
+
+ endMem = curMem;
+ if(g_fSortByName) qsort(members, endMem - members, sizeof MemberInfo, memberCmp);
+ curMem = members;
+ while(curMem < endMem)
+ {
+ if (g_fLimitedVisibility)
+ {
+ HENUMInternal hAssoc;
+ unsigned nAssoc;
+ if (FAILED(g_pImport->EnumAssociateInit(curMem->token,&hAssoc)))
+ {
+ continue;
+ }
+ if (nAssoc = hAssoc.m_ulCount)
+ {
+ NewArrayHolder<ASSOCIATE_RECORD> rAssoc = new (nothrow) ASSOCIATE_RECORD[nAssoc];
+ if (FAILED(g_pImport->GetAllAssociates(&hAssoc,rAssoc,nAssoc)))
+ {
+ continue;
+ }
+
+ for (unsigned i=0; i < nAssoc;i++)
+ {
+ if (TypeFromToken(rAssoc[i].m_memberdef) == mdtMethodDef)
+ {
+ DWORD dwAttrs;
+ if (FAILED(g_pImport->GetMethodDefProps(rAssoc[i].m_memberdef, &dwAttrs)))
+ {
+ continue;
+ }
+ if(g_fHidePub && IsMdPublic(dwAttrs)) continue;
+ if(g_fHidePriv && IsMdPrivate(dwAttrs)) continue;
+ if(g_fHideFam && IsMdFamily(dwAttrs)) continue;
+ if(g_fHideAsm && IsMdAssem(dwAttrs)) continue;
+ if(g_fHideFOA && IsMdFamORAssem(dwAttrs)) continue;
+ if(g_fHideFAA && IsMdFamANDAssem(dwAttrs)) continue;
+ if(g_fHidePrivScope && IsMdPrivateScope(dwAttrs)) continue;
+ }
+ AddPropToGUI(cl, pClassItem, pszNamespace, pszClassName, dwClassAttrs, curMem->token);
+ break;
+ }
+ }
+ g_pImport->EnumClose(&hAssoc);
+ }
+ else AddPropToGUI(cl, pClassItem, pszNamespace, pszClassName, dwClassAttrs, curMem->token);
+ curMem++;
+ }
+ g_fDumpRTF = fDumpRTF;
+ if(pMemberList) delete[] pMemberList;
+ if(members) delete[] members;
+#ifdef _PREFAST_
+#pragma warning(pop)
+#endif
+ return hClassRoot;
+}
+#ifdef _PREFAST_
+#pragma warning(pop)
+#endif
+
+void CreateMenus()
+{
+ HMENU hMenuPopup;
+
+ g_hMenu = CreateMenu();
+
+ hMenuPopup = CreateMenu();
+ WszAppendMenu(hMenuPopup, MF_STRING, IDM_OPEN, RstrW(IDS_OPEN));
+ WszAppendMenu(hMenuPopup, MF_STRING|MF_GRAYED, IDM_DUMP, RstrW(IDS_DUMP));
+ WszAppendMenu(hMenuPopup, MF_STRING|MF_GRAYED, IDM_DUMP_TREE, RstrW(IDS_DUMPTREE));
+ WszAppendMenu(hMenuPopup, MF_STRING, IDM_EXIT, RstrW(IDS_EXIT));
+ WszAppendMenu(g_hMenu, MF_POPUP, (UINT)(UINT_PTR)hMenuPopup, RstrW(IDS_FILE));
+ g_hFileMenu = hMenuPopup;
+
+ hMenuPopup = CreateMenu();
+ g_hFontMenu = CreateMenu();
+ WszAppendMenu(hMenuPopup,MF_POPUP,(UINT)(UINT_PTR)g_hFontMenu,RstrW(IDS_FONTS));
+ WszAppendMenu(g_hFontMenu,MF_STRING,IDM_FONT_TREE,RstrW(IDS_FONT_TREE));
+ WszAppendMenu(g_hFontMenu,MF_STRING,IDM_FONT_DASM,RstrW(IDS_FONT_DASM));
+ WszAppendMenu(hMenuPopup, MF_STRING|(g_fSortByName ? MF_CHECKED : MF_UNCHECKED), IDM_SORT_BY_NAME, RstrW(IDS_SORT_BY_NAME));
+ WszAppendMenu(hMenuPopup, MF_STRING|(g_fTreeViewFCN ? MF_CHECKED : MF_UNCHECKED), IDM_TREEVIEWFCN, RstrW(IDS_TREEVIEWFCN));
+ WszAppendMenu(hMenuPopup, MF_STRING|(g_fCAVerbal ? MF_CHECKED : MF_UNCHECKED), IDM_CAVERBAL, RstrW(IDS_CAVERBAL));
+ //WszAppendMenu(hMenuPopup, MF_STRING|(g_fDumpRTF ? MF_CHECKED : MF_UNCHECKED), IDM_DUMPRTF, RstrW(IDS_DUMPRTF));
+ // MF_SEPARATOR ==> last 2 params ignored
+ WszAppendMenu(hMenuPopup, MF_SEPARATOR,0,NULL);
+ WszAppendMenu(hMenuPopup, MF_STRING|(g_fHidePub ? MF_CHECKED : MF_UNCHECKED), IDM_SHOW_PUB, RstrW(IDS_SHOW_PUB));
+ WszAppendMenu(hMenuPopup, MF_STRING|(g_fHidePriv ? MF_CHECKED : MF_UNCHECKED), IDM_SHOW_PRIV, RstrW(IDS_SHOW_PRIV));
+ WszAppendMenu(hMenuPopup, MF_STRING|(g_fHideFam ? MF_CHECKED : MF_UNCHECKED), IDM_SHOW_FAM, RstrW(IDS_SHOW_FAM));
+ WszAppendMenu(hMenuPopup, MF_STRING|(g_fHideAsm ? MF_CHECKED : MF_UNCHECKED), IDM_SHOW_ASM, RstrW(IDS_SHOW_ASM));
+ WszAppendMenu(hMenuPopup, MF_STRING|(g_fHideFAA ? MF_CHECKED : MF_UNCHECKED), IDM_SHOW_FAA, RstrW(IDS_SHOW_FAA));
+ WszAppendMenu(hMenuPopup, MF_STRING|(g_fHideFOA ? MF_CHECKED : MF_UNCHECKED), IDM_SHOW_FOA, RstrW(IDS_SHOW_FOA));
+ WszAppendMenu(hMenuPopup, MF_STRING|(g_fHidePrivScope ? MF_CHECKED : MF_UNCHECKED), IDM_SHOW_PSCOPE, RstrW(IDS_SHOW_PSCOPE));
+ WszAppendMenu(hMenuPopup, MF_SEPARATOR,0,NULL);
+ WszAppendMenu(hMenuPopup, MF_STRING|(g_fFullMemberInfo ? MF_CHECKED : MF_UNCHECKED), IDM_FULL_INFO, RstrW(IDS_FULL_INFO));
+ WszAppendMenu(hMenuPopup, MF_STRING|(g_fShowBytes ? MF_CHECKED : MF_UNCHECKED), IDM_BYTES, RstrW(IDS_BYTES));
+ WszAppendMenu(hMenuPopup, MF_STRING|(g_fDumpTokens ? MF_CHECKED : MF_UNCHECKED), IDM_TOKENS, RstrW(IDS_TOKENS));
+ WszAppendMenu(hMenuPopup, MF_STRING|(g_fShowSource ? MF_CHECKED : MF_UNCHECKED), IDM_SOURCELINES, RstrW(IDS_SOURCELINES));
+ WszAppendMenu(hMenuPopup, MF_STRING|(g_fQuoteAllNames ? MF_CHECKED : MF_UNCHECKED), IDM_QUOTEALLNAMES, RstrW(IDS_QUOTEALLNAMES));
+ WszAppendMenu(hMenuPopup, MF_STRING|(g_fTryInCode ? MF_CHECKED : MF_UNCHECKED), IDM_EXPANDTRY, RstrW(IDS_EXPANDTRY));
+ if(g_fTDC)
+ {
+
+ WszAppendMenu(hMenuPopup, MF_STRING, IDM_SHOW_HEADER, RstrW(IDS_SHOW_HEADER));
+ WszAppendMenu(hMenuPopup, MF_STRING, IDM_SHOW_STAT, RstrW(IDS_SHOW_STAT));
+ g_hMetaInfoMenu = CreateMenu();
+ //MENUINFO mi;
+ //GetMenuInfo(g_hMetaInfoMenu,&mi);
+ //mi.dwStyle |= MNS_MODELESS;
+ //SetMenuInfo(g_hMetaInfoMenu,&mi);
+ WszAppendMenu(hMenuPopup, MF_POPUP, (UINT)(UINT_PTR)g_hMetaInfoMenu, RstrW(IDS_METAINFO));
+
+ WszAppendMenu(g_hMetaInfoMenu,MF_STRING|(g_ulMetaInfoFilter & MDInfo::dumpMoreHex ? MF_CHECKED : MF_UNCHECKED),IDM_MI_HEX,RstrW(IDS_MI_HEX));
+ WszAppendMenu(g_hMetaInfoMenu,MF_SEPARATOR,0,NULL);
+ WszAppendMenu(g_hMetaInfoMenu,MF_STRING|(g_ulMetaInfoFilter & MDInfo::dumpCSV ? MF_CHECKED : MF_UNCHECKED),IDM_MI_CSV,RstrW(IDS_MI_CSV));
+ WszAppendMenu(g_hMetaInfoMenu,MF_STRING|(g_ulMetaInfoFilter & MDInfo::dumpHeader ? MF_CHECKED : MF_UNCHECKED),IDM_MI_HEADER,RstrW(IDS_MI_HEADER));
+ WszAppendMenu(g_hMetaInfoMenu,MF_STRING|(g_ulMetaInfoFilter & MDInfo::dumpSchema ? MF_CHECKED : MF_UNCHECKED),IDM_MI_SCHEMA,RstrW(IDS_MI_SCHEMA));
+ WszAppendMenu(g_hMetaInfoMenu,MF_STRING|(g_ulMetaInfoFilter & MDInfo::dumpRaw ? MF_CHECKED : MF_UNCHECKED),IDM_MI_RAW,RstrW(IDS_MI_RAW));
+ WszAppendMenu(g_hMetaInfoMenu,MF_STRING|(g_ulMetaInfoFilter & MDInfo::dumpRawHeaps ? MF_CHECKED : MF_UNCHECKED),IDM_MI_HEAPS,RstrW(IDS_MI_HEAPS));
+ WszAppendMenu(g_hMetaInfoMenu,MF_SEPARATOR,0,NULL);
+ WszAppendMenu(g_hMetaInfoMenu,MF_STRING|(g_ulMetaInfoFilter & MDInfo::dumpUnsat ? MF_CHECKED : MF_UNCHECKED),IDM_MI_UNREX,RstrW(IDS_MI_UNREX));
+ WszAppendMenu(g_hMetaInfoMenu,MF_STRING|(g_ulMetaInfoFilter & MDInfo::dumpValidate ? MF_CHECKED : MF_UNCHECKED),IDM_MI_VALIDATE,RstrW(IDS_MI_VALIDATE));
+ WszAppendMenu(g_hMetaInfoMenu,MF_STRING,IDM_SHOW_METAINFO,RstrW(IDS_SHOW_METAINFO));
+ }
+ WszAppendMenu(g_hMenu, MF_POPUP|MF_GRAYED, (UINT)(UINT_PTR)hMenuPopup, RstrW(IDS_VIEW));
+ g_hViewMenu = hMenuPopup;
+ hMenuPopup = CreateMenu();
+ WszAppendMenu(hMenuPopup, MF_STRING, IDM_HELP,RstrW(IDS_HELP));
+ WszAppendMenu(hMenuPopup, MF_STRING, IDM_ABOUT,RstrW(IDS_ABOUT));
+ WszAppendMenu(g_hMenu, MF_POPUP, (UINT)(UINT_PTR)hMenuPopup, RstrW(IDS_HELP));
+}
+
+BOOL LoadImages()
+{
+ int i;
+
+ g_hImageList = ImageList_Create(BITMAP_WIDTH, BITMAP_HEIGHT, ILC_COLOR8, LAST_IMAGE_INDEX, 1);
+ if (g_hImageList == NULL)
+ return FALSE;
+
+ _ASSERTE(g_hResources != NULL);
+ for (i = 0; i < LAST_IMAGE_INDEX; i++)
+ {
+ g_hBitmaps[i] = (HBITMAP) WszLoadImage(
+ g_hResources,
+ MAKEINTRESOURCE(i + IDB_CLASS),
+ IMAGE_BITMAP,
+ 15,
+ 15,
+ LR_LOADTRANSPARENT //LR_DEFAULTCOLOR
+ );
+ if (g_hBitmaps[i] == NULL)
+ return FALSE;
+ int index = ImageList_Add(g_hImageList, g_hBitmaps[i], NULL);
+ if (index != i)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+// Local functions for font persistence:
+char* FontSaveFileName()
+{
+ static char szFileName[MAX_PATH];
+ static BOOL bInit = TRUE;
+ if(bInit)
+ {
+ (void)GetWindowsDirectoryA(szFileName,MAX_PATH);
+ if(szFileName[strlen(szFileName)-1]!='\\') strcat_s(szFileName,MAX_PATH,"\\");
+ strcat_s(szFileName,MAX_PATH,"ildasmfnt.bin");
+ bInit = FALSE;
+ }
+ return szFileName;
+}
+BOOL LoadGUIFonts(GUI_Info* pguiInfo)
+{
+ FILE* pF = NULL;
+ BOOL ret = FALSE;
+ int dummy;
+ if(fopen_s(&pF,FontSaveFileName(),"rb")==0)
+ {
+ ret = (fread(pguiInfo->plfDasm,sizeof(LOGFONTW),1,pF) && fread(pguiInfo->plfTree,sizeof(LOGFONTW),1,pF));
+ if(fread(&dummy,sizeof(int),1,pF)) pguiInfo->x = dummy;
+ if(fread(&dummy,sizeof(int),1,pF)) pguiInfo->y = dummy;
+ if(fread(&dummy,sizeof(int),1,pF)) pguiInfo->w = dummy;
+ if(fread(&dummy,sizeof(int),1,pF)) pguiInfo->h = dummy;
+ if(fread(&dummy,sizeof(int),1,pF)) g_fTreeViewFCN = (dummy != 0);
+ if(fread(&dummy,sizeof(int),1,pF)) g_fSortByName = (dummy != 0);
+ if(fread(&dummy,sizeof(int),1,pF)) g_fFullMemberInfo = (dummy != 0);
+
+ fclose(pF);
+ }
+ return ret;
+}
+BOOL SaveGUIFonts(GUI_Info* pguiInfo)
+{
+ FILE* pF=NULL;
+ BOOL ret = FALSE;
+ int dummyFCN = (g_fTreeViewFCN ? 1:0);
+ int dummySBN = (g_fSortByName ? 1:0);
+ int dummyFMI = (g_fFullMemberInfo ? 1:0);
+ if(fopen_s(&pF,FontSaveFileName(),"wb")==0)
+ {
+ ret = (fwrite(pguiInfo->plfDasm,sizeof(LOGFONTW),1,pF)
+ && fwrite(pguiInfo->plfTree,sizeof(LOGFONTW),1,pF)
+ && fwrite(&(pguiInfo->x),sizeof(int),1,pF)
+ && fwrite(&(pguiInfo->y),sizeof(int),1,pF)
+ && fwrite(&(pguiInfo->w),sizeof(int),1,pF)
+ && fwrite(&(pguiInfo->h),sizeof(int),1,pF)
+ && fwrite(&dummyFCN,sizeof(int),1,pF)
+ && fwrite(&dummySBN,sizeof(int),1,pF)
+ && fwrite(&dummyFMI,sizeof(int),1,pF)
+ );
+ fclose(pF);
+ }
+ return ret;
+}
+// Init various GUI variables, get handles
+// if InitGUI returns FALSE, ildasm exits
+#define DEFAULT_FONTS
+BOOL InitGUI()
+{
+ INITCOMMONCONTROLSEX InitInfo;
+#ifdef DEFAULT_FONTS
+ LOGFONTW strDefaultLogFontDasm = {-14,0,0,0,FW_REGULAR,0,0,0,ANSI_CHARSET,
+ OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,FIXED_PITCH | FF_MODERN,L"Fixedsys"};
+ LOGFONTW strDefaultLogFontTree = {-11,0,0,0,FW_REGULAR,0,0,0,ANSI_CHARSET,
+ OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,VARIABLE_PITCH | FF_SWISS,L"Tahoma"};
+ LOGFONTA strDefaultLogFontDasmA = {-14,0,0,0,FW_REGULAR,0,0,0,ANSI_CHARSET,
+ OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,FIXED_PITCH | FF_MODERN,"Fixedsys"};
+ LOGFONTA strDefaultLogFontTreeA = {-11,0,0,0,FW_REGULAR,0,0,0,ANSI_CHARSET,
+ OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,VARIABLE_PITCH | FF_SWISS,"Tahoma"};
+#endif
+ g_DisasmBox = new DynamicArray<DisasmBox_t>;
+ g_ClassItemList = new DynamicArray<ClassItem_t>;
+ g_NamespaceList = new DynamicArray<Namespace_t>;
+ WszLoadLibrary(L"riched20.dll");
+
+ InitInfo.dwSize = sizeof(InitInfo);
+ InitInfo.dwICC = ICC_LISTVIEW_CLASSES;
+
+ if (InitCommonControlsEx(&InitInfo) == FALSE)
+ return FALSE;
+
+ g_hInstance = WszGetModuleHandle(NULL);
+ g_hResources = LoadLocalizedResourceDLLForSDK(L"ildasmrc.dll");
+
+ //--------- get logical fonts
+#ifdef DEFAULT_FONTS
+ if(!LoadGUIFonts(&guiInfo))
+ {
+ memcpy(&g_strLogFontDasm,&strDefaultLogFontDasm,sizeof(LOGFONTW));
+ memcpy(&g_strLogFontTree,&strDefaultLogFontTree,sizeof(LOGFONTW));
+ }
+ if(g_fDumpRTF) { g_strLogFontDasm.lfWeight = FW_REGULAR; g_strLogFontDasm.lfItalic = FALSE; }
+ // -------- create font for disassembly window
+ g_hFixedFont = CreateFontIndirectW(&g_strLogFontDasm);
+ // -------- create font for tree view
+ g_hSmallFont = CreateFontIndirectW(&g_strLogFontTree);
+#else
+ if(LoadGUIFonts(&guiInfo))
+ {
+ if(g_fDumpRTF) { g_strLogFontDasm.lfWeight = FW_REGULAR; g_strLogFontDasm.lfItalic = FALSE; }
+ // -------- create font for disassembly window
+ g_hFixedFont = CreateFontIndirect(&g_strLogFontDasm);
+ // -------- create font for tree view
+ g_hSmallFont = CreateFontIndirect(&g_strLogFontTree);
+ }
+ else
+ {
+ g_hFixedFont = (HFONT)GetStockObject(SYSTEM_FIXED_FONT);
+ g_hSmallFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
+ }
+#endif
+ if (g_hFixedFont == NULL) return FALSE;
+ if (g_hSmallFont == NULL) return FALSE;
+
+ memset(&g_strChFontDasm,0,sizeof(CHOOSEFONT));
+ g_strChFontDasm.lStructSize = sizeof(CHOOSEFONT);
+ g_strChFontDasm.lpLogFont = &g_strLogFontDasm;
+ g_strChFontDasm.Flags = CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS |CF_SHOWHELP;
+ if(!g_fDumpRTF) g_strChFontDasm.Flags |= CF_EFFECTS; // no color change option for RTF output!
+ g_strChFontDasm.rgbColors = GetSysColor(COLOR_INFOTEXT);
+
+ memset(&g_strChFontTree,0,sizeof(CHOOSEFONTW));
+ g_strChFontTree.lStructSize = sizeof(CHOOSEFONTW);
+ g_strChFontTree.lpLogFont = &g_strLogFontTree;
+ g_strChFontTree.Flags = CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS |CF_SHOWHELP /*| CF_EFFECTS*/;
+ g_strChFontTree.rgbColors = GetSysColor(COLOR_WINDOWTEXT);
+
+ g_hWhiteBrush = (HBRUSH) GetStockObject(WHITE_BRUSH);
+ if (g_hWhiteBrush == NULL)
+ return FALSE;
+
+ if (LoadImages() == FALSE)
+ return FALSE;
+
+ if (RegisterWindowClasses() == FALSE)
+ return FALSE;
+#undef RegisterWindowMessageW
+ g_uFindReplaceMsg = RegisterWindowMessageW(FINDMSGSTRING);
+
+ CreateMenus();
+
+ return TRUE;
+}
+
+void DestroyGUI()
+{
+ SDELETE(g_DisasmBox);
+ SDELETE(g_ClassItemList);
+ SDELETE(g_NamespaceList);
+}
+//
+// Set the font of a particular window to the global fixed size font
+//
+void SetWindowFontFixed(HWND hwnd)
+{
+ WszSendMessage(
+ hwnd,
+ WM_SETFONT,
+ (LPARAM) g_hFixedFont,
+ FALSE
+ );
+}
+
+
+//
+// Set the char dimensions variables
+//
+void SetCharDimensions(HWND hwnd)
+{
+ if (InterlockedIncrement(&g_SetCharDimensions) == 1)
+ {
+ HDC hdc;
+ TEXTMETRIC tm;
+
+ hdc = GetDC(hwnd);
+
+ GetTextMetrics(hdc, &tm);
+
+ g_MaxCharWidth = tm.tmAveCharWidth;
+ g_Height = tm.tmHeight;
+
+ ReleaseDC(hwnd, hdc);
+ }
+ else
+ {
+ // Already set
+ InterlockedDecrement(&g_SetCharDimensions);
+ }
+}
+
+
+//
+// Given a member handle and a class item, find the TreeItem for that member
+//
+TreeItem_t *FindMemberInClass(ClassItem_t *pClassItem, HTREEITEM hMember)
+{
+ DWORD i;
+
+ for (i = 0; i < pClassItem->SubItems; i++)
+ {
+ if (pClassItem->pMembers[i].hItem == hMember)
+ return &pClassItem->pMembers[i];
+ }
+
+ return NULL;
+}
+
+
+//
+// Register the window classes
+//
+BOOL RegisterWindowClasses()
+{
+ _ASSERTE(g_hResources != NULL);
+ WNDCLASSW wndClass;
+
+ wndClass.style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW;
+ wndClass.lpfnWndProc = DisassemblyWndProc;
+ wndClass.cbClsExtra = 0;
+ wndClass.cbWndExtra = 0;
+ wndClass.hInstance = g_hInstance;
+ wndClass.hIcon = WszLoadIcon(g_hResources,MAKEINTRESOURCE(IDI_ICON2));
+ wndClass.hCursor = NULL;
+ wndClass.hbrBackground = g_hWhiteBrush;
+ wndClass.lpszMenuName = NULL;
+ wndClass.lpszClassName = DISASSEMBLY_CLASS_NAMEW;
+ if (WszRegisterClass((WNDCLASSW*)(&wndClass)) == 0)
+ return FALSE;
+
+ wndClass.style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW;
+ wndClass.lpfnWndProc = MainWndProc;
+ wndClass.cbClsExtra = 0;
+ wndClass.cbWndExtra = 0;
+ wndClass.hInstance = g_hInstance;
+ wndClass.hIcon = WszLoadIcon(g_hResources,MAKEINTRESOURCE(IDI_ICON2));
+ wndClass.hCursor = NULL;
+ wndClass.hbrBackground = g_hWhiteBrush;
+ wndClass.lpszMenuName = NULL;
+
+ wndClass.lpszClassName = MAIN_WINDOW_CLASSW;
+ if (WszRegisterClass((WNDCLASSW*)(&wndClass)) == 0)
+ return FALSE;
+ return TRUE;
+}
+
+//
+// Dump one item to global buffer
+//
+void GUIDumpItemToDisassemblyEditBox(void*pvDLB, mdToken cl, mdToken mbMember)
+{
+ const char * pszClassName;
+ const char * pszNamespace;
+ mdTypeRef crExtends;
+ DWORD dwClassAttrs;
+
+ if ((cl != mdTokenNil)&&TypeFromToken(mbMember))
+ {
+ if (FAILED(g_pImport->GetNameOfTypeDef(cl, &pszClassName, &pszNamespace)))
+ {
+ pszClassName = pszNamespace = "Invalid TypeDef record";
+ }
+ MAKE_NAME_IF_NONE(pszClassName,cl);
+ }
+ else
+ {
+ pszClassName = (TypeFromToken(mbMember) == mdtMethodDef) ? "Global Functions" : "Global Fields";
+ }
+ memset(GlobalBuffer,0,GlobalBufferLen);
+ InGlobalBuffer = 0;
+
+ if (TypeFromToken(mbMember) && cl && (cl != mdTypeDefNil))
+ {
+ if (FAILED(g_pImport->GetTypeDefProps(cl, &dwClassAttrs, &crExtends)))
+ {
+ dwClassAttrs = 0;
+ crExtends = mdTypeDefNil;
+ }
+ }
+ g_Mode |= MODE_GUI;
+ //_ASSERTE(0);
+ mdToken tkVarOwner = g_tkVarOwner;
+ g_tkVarOwner = cl;
+ if(g_fDumpRTF) DumpRTFPrefix(pvDLB,FALSE);
+ switch (TypeFromToken(mbMember))
+ {
+ case 0:
+ switch(cl)
+ {
+ case 0:
+ DumpManifest(pvDLB);
+ DumpTypedefs(pvDLB);
+ break;
+ case IDM_SHOW_HEADER:
+ DumpHeader(g_CORHeader,pvDLB);
+ DumpHeaderDetails(g_CORHeader,pvDLB);
+ break;
+ case IDM_SHOW_METAINFO:
+ DumpMetaInfo(g_wszFullInputFile,NULL,pvDLB);
+ break;
+ case IDM_SHOW_STAT:
+ DumpStatistics(g_CORHeader,pvDLB);
+ break;
+ }
+ break;
+
+ case mdtTypeDef:
+ DumpClass(mbMember,VAL32(g_CORHeader->EntryPointToken), pvDLB, 1); //1 = title+size+pack+custom attributes
+ break;
+ case mdtFieldDef:
+ {
+ ULONG ul1,ul2;
+ GetClassLayout(cl,&ul1,&ul2);
+ DumpField(mbMember,pszClassName, pvDLB, TRUE);
+ }
+ break;
+ case mdtMethodDef:
+ DumpMethod(mbMember,pszClassName,VAL32(g_CORHeader->EntryPointToken), pvDLB, TRUE);
+ break;
+ case mdtEvent:
+ DumpEvent(mbMember,pszClassName, dwClassAttrs, pvDLB, TRUE);
+ break;
+ case mdtProperty:
+ DumpProp(mbMember,pszClassName, dwClassAttrs, pvDLB, TRUE);
+ break;
+ }
+ if(g_fDumpRTF) DumpRTFPostfix(pvDLB);
+ g_tkVarOwner = tkVarOwner;
+ if(g_uCodePage==0xFFFFFFFF)
+ {
+ SendMessageW((HWND)pvDLB,WM_SETTEXT,0, (LPARAM)GlobalBuffer);
+ }
+ else
+ {
+ UINT32 L = (UINT32)strlen(GlobalBuffer);
+ WCHAR* wz = new (nothrow) WCHAR[L+4];
+ if(wz)
+ {
+ memset(wz,0,sizeof(WCHAR)*(L+2));
+ int x = WszMultiByteToWideChar(CP_UTF8,0,GlobalBuffer,-1,wz,L+2);
+ if(g_fDumpRTF)
+ {
+ x = (int)SendMessageA((HWND)pvDLB,WM_SETTEXT,0, (LPARAM)UnicodeToAnsi(wz));
+ }
+ else
+ {
+ SETTEXTEX ste;
+ ste.flags = ST_DEFAULT;
+ ste.codepage = 1200;
+ x = (int)WszSendMessage((HWND)pvDLB,EM_SETTEXTEX,(WPARAM)&ste, (LPARAM)wz);
+ }
+ delete[] wz;
+ }
+ }
+}
+
+//
+// Disassemble the given method in a new window
+//
+
+HWND GUIDisassemble(mdTypeDef cl, mdToken mbMember, __in __nullterminated char *pszNiceMemberName)
+{
+ HWND hwndDisassemblyMain;
+ HWND hwndDisassemblyListBox;
+ const char * pszClassName;
+ const char * pszNamespace;
+ char* szTemp=NULL;
+ RECT rcl;
+ static char szsz[4096];
+ bool fUpdate = false;
+ bool fMetaInfo = (TypeFromToken(mbMember)==0)&&(cl==IDM_SHOW_METAINFO);
+ BOOL fDumpRTF = g_fDumpRTF;
+ if(fMetaInfo) g_fDumpRTF = FALSE;
+
+ //before we even try, check if this member's disasm box is already opened
+ DisasmBox_t* pDisasmBox = FindDisasmBox(cl, mbMember);
+ if(pDisasmBox)
+ {
+ if(fMetaInfo || (0 == strcmp(pszNiceMemberName,"UpdateThisDisassemblyBox")))
+ {
+ fUpdate = true;
+ }
+ else
+ {
+ PostMessageA(pDisasmBox->hwndContainer,WM_ACTIVATE,WA_CLICKACTIVE,0);
+ PostMessageA(pDisasmBox->hwndContainer,WM_SETFOCUS,0,0);
+ return pDisasmBox->hwndContainer;
+ }
+ }
+ if(fUpdate)
+ {
+ SendMessageW(pDisasmBox->hwndContainer,WM_GETTEXT, 0, (LPARAM)szsz);
+ strcpy_s(szsz,4096,UnicodeToUtf((WCHAR*)szsz));
+
+ szTemp = szsz;
+ PostMessageA(pDisasmBox->hwndContainer,WM_CLOSE,1,0);
+ }
+ else
+ {
+ // Prepend class name to nicely formatted member name
+ if (mbMember != 0)
+ {
+ if (cl != mdTokenNil)
+ {
+ if (FAILED(g_pImport->GetNameOfTypeDef(
+ cl,
+ &pszClassName,
+ &pszNamespace)))
+ {
+ pszClassName = pszNamespace = "Invalid TypeDef record";
+ }
+ MAKE_NAME_IF_NONE(pszClassName,cl);
+ if(*pszNamespace != 0)
+ sprintf_s(szsz,4096,"%s.",pszNamespace);
+ else
+ szsz[0] = 0;
+ strcat_s(szsz,4096,pszClassName);
+ pszClassName = (const char*)&szsz[0];
+ }
+ else
+ {
+ pszClassName = (TypeFromToken(mbMember) == mdtMethodDef) ? "Global Functions" : "Global Fields";
+ }
+ szTemp = new (nothrow) char[strlen(pszClassName)+strlen(pszNiceMemberName)+4];
+ if(szTemp) sprintf_s(szTemp, strlen(pszClassName)+strlen(pszNiceMemberName)+4,"%s::%s", pszClassName, pszNiceMemberName);
+ _ASSERTE(TypeFromToken(mbMember) & (mdtMethodDef|mdtEvent|mdtProperty|mdtTypeDef|mdtFieldDef));
+ }
+ if(!szTemp) szTemp = pszNiceMemberName;
+ }
+ _ASSERTE(szTemp);
+
+ HMENU hMenu = CreateMenu();
+ WszAppendMenu(hMenu, MF_STRING, IDM_FIND, RstrW(IDS_FIND));
+ WszAppendMenu(hMenu, MF_STRING, IDM_FINDNEXT, RstrW(IDS_FINDNEXT));
+
+ hwndDisassemblyMain = WszCreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ DISASSEMBLY_CLASS_NAMEW,
+ UtfToUnicode(szTemp),
+ WS_OVERLAPPEDWINDOW | WS_SIZEBOX,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ 640,
+ 400,
+ NULL,
+ hMenu, // menu
+ g_hInstance, // hinst
+ NULL
+ );
+ SendMessageW(hwndDisassemblyMain,WM_SETTEXT, 0, (LPARAM)(UtfToUnicode(szTemp)));
+
+ if((!fUpdate) && szTemp &&(szTemp != pszNiceMemberName)) delete[] szTemp;
+ if (hwndDisassemblyMain == NULL)
+ {
+ g_fDumpRTF = fDumpRTF;
+ return NULL;
+ }
+ GetClientRect(hwndDisassemblyMain, &rcl);
+
+ hwndDisassemblyListBox = WszCreateWindowEx(
+ 0,
+ (!g_fDumpRTF) ? L"RichEdit20W" : L"RichEdit20A",
+ RstrW(IDS_TEXTTOOLARGEFORGUI),
+ WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE
+ | ES_MULTILINE | ES_READONLY | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_NOHIDESEL,
+ rcl.left,
+ rcl.top,
+ rcl.right - rcl.left,
+ rcl.bottom - rcl.top,
+ hwndDisassemblyMain,
+ (HMENU) ID_LISTBOX,
+ g_hInstance, // hinst
+ NULL
+ );
+
+ DWORD e = GetLastError();
+ _ASSERTE(hwndDisassemblyListBox);
+ if (hwndDisassemblyListBox == NULL)
+ {
+ DestroyWindow(hwndDisassemblyMain);
+ return NULL;
+ }
+
+ if(fUpdate)
+ {
+ UpdateDisasmBox(pDisasmBox, hwndDisassemblyMain, hwndDisassemblyListBox, hMenu);
+ }
+ else
+ AddDisasmBox(hwndDisassemblyMain, hwndDisassemblyListBox, hMenu, cl, mbMember);
+
+ SendMessage(hwndDisassemblyListBox,EM_SETTEXTMODE,TM_RICHTEXT|TM_MULTICODEPAGE,0);
+ SendMessage(hwndDisassemblyListBox,EM_SETBKGNDCOLOR,0,GetSysColor(COLOR_INFOBK));
+ SetWindowFontFixed(hwndDisassemblyListBox);
+ SetCharDimensions(hwndDisassemblyListBox);
+
+ GUIDumpItemToDisassemblyEditBox((void *)hwndDisassemblyListBox,cl,mbMember);
+
+ ShowWindow(hwndDisassemblyMain, SW_SHOWNORMAL);
+ UpdateWindow(hwndDisassemblyMain);
+
+ g_fDumpRTF = fDumpRTF;
+ return hwndDisassemblyMain;
+}
+
+//
+// Callback by the disassembler to add another entry to the disassembly window
+//
+void GUIAddOpcode(__inout_opt __nullterminated const char *pszString, __in_opt void *GUICookie)
+{
+ if(pszString)
+ {
+ ULONG L = (g_uCodePage == 0xFFFFFFFF) ? (ULONG)(wcslen((WCHAR*)pszString)*sizeof(WCHAR)) : (ULONG)strlen(pszString);
+ if(InGlobalBuffer+L >= GlobalBufferLen-4)
+ {
+ ULONG LL = ((L >> 12)+1)<<12;
+ char *pch = new (nothrow) char[GlobalBufferLen + LL];
+ if(pch)
+ {
+ memcpy(pch,GlobalBuffer,InGlobalBuffer+1);
+ delete[] GlobalBuffer;
+ GlobalBuffer = pch;
+ GlobalBufferLen += LL;
+ }
+ }
+ if(g_uCodePage == 0xFFFFFFFF)
+ {
+ if(g_fDumpRTF)
+ {
+ swprintf_s((WCHAR*)&GlobalBuffer[InGlobalBuffer], (GlobalBufferLen-InGlobalBuffer)/sizeof(WCHAR), L"%s\\line\r\n",(WCHAR*)pszString);
+ InGlobalBuffer += L+14;
+ }
+ else
+ {
+ swprintf_s((WCHAR*)&GlobalBuffer[InGlobalBuffer], (GlobalBufferLen-InGlobalBuffer)/sizeof(WCHAR), L"%s\r\n",(WCHAR*)pszString);
+ InGlobalBuffer += L+4;
+ }
+ }
+ else
+ {
+ if(g_fDumpRTF)
+ {
+ sprintf_s(&GlobalBuffer[InGlobalBuffer],GlobalBufferLen-InGlobalBuffer,"%s\\line\r\n",pszString);
+ InGlobalBuffer += L+7;
+ }
+ else
+ {
+ sprintf_s(&GlobalBuffer[InGlobalBuffer],GlobalBufferLen-InGlobalBuffer,"%s\r\n",pszString);
+ InGlobalBuffer += L+2;
+ }
+ }
+ }
+ else
+ {
+ delete[] GlobalBuffer;
+ GlobalBufferLen = 0;
+ InGlobalBuffer = 0;
+ }
+}
+
+//
+// Someone has double clicked on an item
+//
+// It could be a method (diassemble it), or a field (ignore it), or an "extends" or "implements"
+// component, in which case we select that component if available.
+//
+HWND DoubleClickSelectedMember(HTREEITEM hItem)
+{
+ HTREEITEM hClass;
+ ClassItem_t *pClassItem;
+
+ static HCURSOR hWaitCursor = NULL;
+
+ if (hWaitCursor == NULL)
+ hWaitCursor = WszLoadCursor(NULL,IDC_WAIT);
+
+ //
+ // It could be any item, but assume it's a member item or class info and find its parent
+ //
+ hClass = TreeView_GetParent(g_hwndTreeView, hItem);
+ if (hClass == NULL)
+ return NULL;
+
+ //
+ // Find the class item given the HTREEITEM
+ // (will return NULL if hClass is not really a class item)
+ //
+ pClassItem = FindClassItem(hClass);
+ if (pClassItem != NULL)
+ {
+ // Which subitem was it?
+ TreeItem_t *pItem = FindMemberInClass(pClassItem, hItem);
+
+ if (pItem == NULL)
+ return NULL;
+
+ if (pItem->Discriminator == TREEITEM_TYPE_MEMBER)
+ {
+ TVITEMA SelItem;
+ char* szText;
+ // Must be a method, event or property
+ switch (TypeFromToken(pItem->mbMember))
+ {
+ case mdtMethodDef:
+ case mdtEvent:
+ case mdtProperty:
+ case mdtFieldDef:
+ break;
+ default:
+ return NULL;
+ }
+
+
+ // Get the name of this item so that we can title the disassembly window
+ szText = new (nothrow) char[8192];
+ if(szText)
+ {
+ memset(&SelItem, 0, sizeof(SelItem));
+ SelItem.mask = TVIF_TEXT;
+ SelItem.pszText = szText;
+ SelItem.hItem = pItem->hItem;
+ SelItem.cchTextMax = 8192;
+
+ WCHAR* wzText = (WCHAR*)szText;
+ SelItem.cchTextMax /= sizeof(WCHAR);
+ SendMessageW(g_hwndTreeView, TVM_GETITEMW, 0, (LPARAM) (LPTVITEMW) &SelItem);
+ unsigned L = ((unsigned)wcslen(wzText)+1)*3;
+ char* szUTFText = new (nothrow) char[L];
+ if(szUTFText)
+ {
+ memset(szUTFText,0,L);
+ WszWideCharToMultiByte(CP_UTF8,0,wzText,-1,szUTFText,L,NULL,NULL);
+ delete[] wzText;
+ szText = szUTFText;
+ }
+ }
+ HCURSOR hWasCursor = SetCursor(hWaitCursor);
+
+ HWND hRet = GUIDisassemble(pClassItem->cl, pItem->mbMember, szText? szText : "");
+ if(szText) delete[] szText;
+
+ SetCursor(hWasCursor);
+
+ return hRet;
+ }
+ else if (pItem->Discriminator == TREEITEM_TYPE_INFO)
+ {
+ if(pItem->mbMember)
+ {
+ if(pItem->mbMember != 0xFFFFFFFF)
+ {
+ // We've clicked on an "extends X" or "implements Y", so select that class
+ SelectClassByToken(pItem->mbMember);
+ }
+ else
+ {
+ HCURSOR hWasCursor = SetCursor(hWaitCursor);
+
+ HWND hRet = GUIDisassemble(0, 0, "MANIFEST");
+
+ SetCursor(hWasCursor);
+ return hRet;
+ }
+ }
+ else
+ {
+ TVITEMA SelItem;
+ char* szText = new (nothrow) char[8192];
+ if(szText)
+ {
+ // Get the name of this item so that we can title the disassembly window
+ memset(&SelItem, 0, sizeof(SelItem));
+ SelItem.mask = TVIF_TEXT;
+ SelItem.pszText = szText;
+ SelItem.hItem = pItem->hItem;
+ SelItem.cchTextMax = 8192;
+
+ WCHAR* wzText = (WCHAR*)szText;
+ SelItem.cchTextMax /= sizeof(WCHAR);
+ SendMessageW(g_hwndTreeView, TVM_GETITEMW, 0, (LPARAM) (LPTVITEMW) &SelItem);
+ unsigned L = ((unsigned)wcslen(wzText)+1)*3;
+ char* szUTFText = new (nothrow) char[L];
+ memset(szUTFText,0,L);
+ WszWideCharToMultiByte(CP_UTF8,0,wzText,-1,szUTFText,L,NULL,NULL);
+ delete[] wzText;
+ szText = szUTFText;
+ }
+ HCURSOR hWasCursor = SetCursor(hWaitCursor);
+
+ HWND hRet = GUIDisassemble(pClassItem->cl, pClassItem->cl, szText ? szText : "");
+ if(szText) delete[] szText;
+
+ SetCursor(hWasCursor);
+
+ return hRet;
+ }
+ }
+ }
+ return NULL;
+}
+
+
+void SelectClassByName(__in __nullterminated char *pszFQName)
+{
+ ClassItem_t *pDestItem;
+
+ // Find namespace
+ char *p = ns::FindSep(pszFQName);
+ if (p == NULL)
+ {
+ pDestItem = FindClassItem(NULL, pszFQName);
+ }
+ else
+ {
+ char szBuffer[MAX_CLASSNAME_LENGTH];
+ strncpy_s(szBuffer, MAX_CLASSNAME_LENGTH,pszFQName, p - pszFQName);
+ szBuffer[ p - pszFQName ] = '\0';
+ pDestItem = FindClassItem(szBuffer, p+1);
+ }
+
+ if (pDestItem != NULL)
+ {
+ SendMessageA(g_hwndTreeView, TVM_SELECTITEM, TVGN_CARET, (LPARAM) (LPTVITEM) pDestItem->hItem);
+ }
+}
+
+void SelectClassByToken(mdToken tk)
+{
+ if(TypeFromToken(tk)==mdtTypeDef)
+ {
+ ClassItem_t *pDestItem;
+ if(pDestItem = FindClassItem(tk))
+ {
+ SendMessageA(g_hwndTreeView, TVM_SELECTITEM, TVGN_CARET, (LPARAM) (LPTVITEM) pDestItem->hItem);
+ }
+ }
+}
+
+//
+// Text search in rich text edit
+//
+void FindTextInListbox(HWND hwnd, FINDREPLACEW* lpfr)
+{
+ HWND hwndLB = FindAssociatedDisassemblyListBox(hwnd);
+ if(hwndLB)
+ {
+ FINDTEXTW strFind;
+ DWORD bgn,end;
+ SendMessage(hwndLB,EM_GETSEL,(WPARAM)&bgn,(LPARAM)&end);
+ if(lpfr->Flags & FR_DOWN)
+ {
+ strFind.chrg.cpMin=end;
+ strFind.chrg.cpMax=-1;
+ }
+ else
+ {
+ strFind.chrg.cpMin=bgn;
+ strFind.chrg.cpMax=0;
+ }
+ strFind.lpstrText=lpfr->lpstrFindWhat;
+ int pos = (int)SendMessage(hwndLB,EM_FINDTEXTW,(WPARAM)(lpfr->Flags),(LPARAM)&strFind);
+ if(pos >= 0)
+ {
+ //char sz[32];
+ //sprintf(sz,"%d:%d",strFind.chrg.cpMin,strFind.chrg.cpMax);
+ //MessageBox(hwnd,sz,"Find",MB_OK);
+ SendMessage(hwndLB,EM_SETSEL,(WPARAM)pos,(LPARAM)(pos+wcslen(lpfr->lpstrFindWhat)));
+ }
+ }
+}
+
+//
+// Disassembly window(s) WndProc
+//
+LRESULT CALLBACK DisassemblyWndProc(
+ HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam
+)
+{
+ static HBRUSH hBrush=NULL;
+ COLORREF crBackGr;
+
+ static COLORREF crBackGrOld=NULL;
+
+ if (crBackGrOld == NULL)
+ crBackGrOld = GetSysColor(COLOR_INFOBK);
+
+ if(uMsg== g_uFindReplaceMsg)
+ {
+ FINDREPLACEW* lpfr = (FINDREPLACEW*)lParam;
+ if(!(lpfr->Flags & FR_DIALOGTERM))
+ {
+ FindTextInListbox(hwnd,lpfr);
+ }
+ }
+ else
+ switch (uMsg)
+ {
+ case WM_CREATE:
+ hBrush = CreateSolidBrush(RGB(255,255,255));
+ break;
+
+ //===== Sent by Static (label) and Read-Only Edit field =====
+ case WM_CTLCOLORSTATIC:
+ case WM_CTLCOLOREDIT:
+ if(hBrush) DeleteObject(hBrush);
+ crBackGr = GetSysColor(COLOR_INFOBK);
+ hBrush = CreateSolidBrush(crBackGr);
+ SetBkColor((HDC) wParam, crBackGr);
+ if(crBackGr != crBackGrOld)
+ {
+ g_strChFontDasm.rgbColors = GetSysColor(COLOR_INFOTEXT);
+ crBackGrOld = crBackGr;
+ }
+ SetTextColor((HDC) wParam, g_strChFontDasm.rgbColors);
+ return (LRESULT) hBrush;
+
+ //====== Sent by active Edit field ============
+ //case WM_CTLCOLOREDIT:
+ // if(hBrush) DeleteObject(hBrush);
+ // hBrush = CreateSolidBrush(RGB(255,255,255));
+ // SetBkColor((HDC) wParam, RGB(255,255,255));
+ // return (LRESULT) hBrush;
+
+ // Ownerdraw stuff
+ case WM_MEASUREITEM:
+ {
+ ((MEASUREITEMSTRUCT *) (lParam))->itemHeight = g_Height;
+ break;
+ }
+
+ // Ownerdraw stuff
+ case WM_DRAWITEM:
+ {
+ DRAWITEMSTRUCT *pDIS;
+ WCHAR wzBuf[1024];
+ int ItemID;
+
+ pDIS = (DRAWITEMSTRUCT *) lParam;
+ ItemID = (int) pDIS->itemID;
+
+ if (ItemID < 0)
+ {
+ switch (pDIS->CtlType)
+ {
+ case ODT_LISTBOX:
+ {
+ if ((pDIS->itemAction) & (ODA_FOCUS))
+ DrawFocusRect (PHDC, &PRC);
+ break;
+ }
+
+ case ODT_COMBOBOX:
+ {
+ if ((pDIS->itemAction) & ODS_FOCUS)
+ DrawFocusRect(PHDC, &PRC);
+ break;
+ }
+ }
+
+ return TRUE;
+ }
+
+ switch (pDIS->CtlType)
+ {
+ case ODT_LISTBOX:
+ WszSendMessage(pDIS->hwndItem, LB_GETTEXT, pDIS->itemID, (LPARAM)wzBuf);
+ break;
+
+ case ODT_COMBOBOX:
+ WszSendMessage(pDIS->hwndItem, CB_GETLBTEXT, pDIS->itemID, (LPARAM)wzBuf);
+ break;
+ }
+
+ int crBack,crText;
+ HBRUSH hbrBack;
+
+ if ((pDIS->itemState) & (ODS_SELECTED))
+ {
+ crBack = GetSysColor(COLOR_HIGHLIGHT);
+ crText = GetSysColor(COLOR_HIGHLIGHTTEXT);
+ }
+ else
+ {
+ crBack = GetSysColor(COLOR_WINDOW);
+ crText = GetSysColor(COLOR_WINDOWTEXT);
+ }
+
+ hbrBack = CreateSolidBrush(crBack);
+ FillRect(PHDC, &PRC, hbrBack);
+ DeleteObject(hbrBack);
+
+ // 0x00bbggrr
+ SetBkColor(PHDC, crBack);
+
+ // Instruction counter
+ if (wcslen(wzBuf) >= PADDING && isdigit(*wzBuf))
+ {
+ SetTextColor(PHDC, 0x00FF0000);
+ TextOutW(PHDC, PRC.left, PRC.top, wzBuf, 5);
+
+ SetTextColor(PHDC, 0x00005500);
+ TextOutW(PHDC, PRC.left + (5*g_MaxCharWidth), PRC.top, &wzBuf[5], PADDING-5);
+
+ SetTextColor(PHDC, crText);
+ TextOutW(PHDC, PRC.left + (PADDING*g_MaxCharWidth), PRC.top, &wzBuf[PADDING], (UINT32)wcslen(&wzBuf[PADDING]));
+ }
+ else
+ TextOutW(PHDC, PRC.left, PRC.top, wzBuf, (UINT32)wcslen(wzBuf));
+
+ if ((pDIS->itemState) & (ODS_FOCUS))
+ DrawFocusRect(PHDC, &PRC);
+
+ break;
+ }
+
+
+ case WM_COMMAND:
+ {
+ if(HIWORD(wParam) > 1) break; // we are interested in commands from menu only
+ switch (LOWORD(wParam))
+ {
+ case IDM_FIND:
+ {
+ HWND hwndLB = FindAssociatedDisassemblyListBox(hwnd);
+ if(hwndLB)
+ {
+ FINDREPLACEW *pFR = &(FindDisasmBoxByHwnd(hwnd)->strFR);
+ if(pFR && (pFR->Flags&FR_DIALOGTERM)) // i.e., if the box isn't up
+ {
+ DWORD bgn,end;
+ WszSendMessage(hwndLB,EM_GETSEL,(WPARAM)&bgn,(LPARAM)&end);
+ if(end > bgn)
+ {
+ if(end - bgn > 119)
+ SendMessage(hwndLB,EM_SETSEL,(WPARAM)bgn,(LPARAM)(bgn+119));
+ SendMessage(hwndLB,EM_GETSELTEXT,0,(LPARAM)(pFR->lpstrFindWhat));
+ }
+ pFR->Flags &= ~FR_DIALOGTERM;
+ g_hFindText = FindTextW(pFR);
+ }
+ }
+ }
+ break;
+ case IDM_FINDNEXT:
+ {
+ FindTextInListbox(hwnd,&(FindDisasmBoxByHwnd(hwnd)->strFR));
+ }
+ break;
+ }
+ break;
+ }
+
+ case WM_SETFOCUS:
+ SetFocus(FindAssociatedDisassemblyListBox(hwnd));
+ break;
+
+ case WM_SIZE:
+ {
+ DWORD cxClient = LOWORD(lParam);
+ DWORD cyClient = HIWORD(lParam);
+ HWND hListView;
+
+ // We have to size the listview also
+
+ // Will be NULL if we are ourselves a listview
+ hListView = FindAssociatedDisassemblyListBox(hwnd);
+
+ if (hListView != NULL)
+ {
+ // Resize listview window
+ MoveWindow(
+ hListView,
+ 0,
+ 0,
+ cxClient,
+ cyClient,
+ TRUE // repaint
+ );
+ }
+
+ break;
+ }
+
+ case WM_CLOSE:
+ if(hBrush) DeleteObject(hBrush);
+ if(LOWORD(wParam)==0) RemoveDisasmBox(hwnd);
+ DestroyWindow(hwnd); // Generates the WM_DESTROY message
+
+ // Shutdown everything if we're just viewing GUI IL and close all our boxes
+ if (IsGuiILOnly() && (g_NumDisasmBoxes == 0)) {
+ PostQuitMessage(0);
+ }
+
+ break;
+
+ default :
+ return WszDefWindowProc(hwnd, uMsg, wParam, lParam);
+ }
+
+ return 0;
+}
+
+BOOL CALLBACK AboutBoxProc(HWND hwndDlg, // handle to dialog box
+ UINT uMsg, // message
+ WPARAM wParam, // first message parameter
+ LPARAM lParam) // second message parameter
+{
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ WCHAR str[1024];
+ WszSendDlgItemMessage(hwndDlg,IDC_ABOUT_LINE1,WM_SETTEXT,0,
+ (LPARAM)RstrW(IDS_ILDASM_TITLE));
+ swprintf_s(str,1024,RstrW(IDS_VERSION), VER_FILEVERSION_STR_L); str[1023]=0;
+ WszSendDlgItemMessage(hwndDlg,IDC_ABOUT_LINE2,WM_SETTEXT,0,(LPARAM)str);
+ WszSendDlgItemMessage(hwndDlg,IDC_ABOUT_LINE3,WM_SETTEXT,0,
+ (LPARAM)RstrW(IDS_LEGALCOPYRIGHT));
+ }
+ return TRUE;
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case ID_ABOUT_OK:
+ EndDialog(hwndDlg,0);
+ return TRUE;
+ }
+ break;
+
+ }
+ return FALSE;
+}
+
+BOOL CALLBACK DumpOptionsProc(HWND hwndDlg, // handle to dialog box
+ UINT uMsg, // message
+ WPARAM wParam, // first message parameter
+ LPARAM lParam) // second message parameter
+{
+ static BOOL fAsmChecked;
+ static BOOL fMetaChecked;
+ static ULONG uCodePage = 0;
+
+ if (uCodePage == 0)
+ uCodePage = g_uCodePage;
+
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ WszSendDlgItemMessage(hwndDlg,IDC_RADIO1,BM_SETCHECK,(uCodePage==g_uConsoleCP ? BST_CHECKED : BST_UNCHECKED),0);
+ WszSendDlgItemMessage(hwndDlg,IDC_RADIO2,BM_SETCHECK,(uCodePage==CP_UTF8 ? BST_CHECKED : BST_UNCHECKED),0);
+ WszSendDlgItemMessage(hwndDlg,IDC_RADIO3,BM_SETCHECK,(uCodePage==0xFFFFFFFF ? BST_CHECKED : BST_UNCHECKED),0);
+
+
+ WszSendDlgItemMessage(hwndDlg,IDC_CHECK18,BM_SETCHECK,(g_fShowProgressBar ? BST_CHECKED : BST_UNCHECKED),0);
+ WszSendDlgItemMessage(hwndDlg,IDC_CHECK1, BM_SETCHECK,(g_fDumpHeader ? BST_CHECKED : BST_UNCHECKED),0);
+ if(g_fTDC)
+ {
+ WszSendDlgItemMessage(hwndDlg,IDC_CHECK2, BM_SETCHECK,(g_fDumpStats ? BST_CHECKED : BST_UNCHECKED),0);
+ WszSendDlgItemMessage(hwndDlg,IDC_CHECK19, BM_SETCHECK,(g_fDumpClassList ? BST_CHECKED : BST_UNCHECKED),0);
+ }
+ else
+ {
+ ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK2), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK19), SW_HIDE);
+ }
+ WszSendDlgItemMessage(hwndDlg,IDC_CHECK3, BM_SETCHECK,(g_fDumpAsmCode ? BST_CHECKED : BST_UNCHECKED),0);
+ WszSendDlgItemMessage(hwndDlg,IDC_CHECK4, BM_SETCHECK,(g_fDumpTokens ? BST_CHECKED : BST_UNCHECKED),0);
+ WszSendDlgItemMessage(hwndDlg,IDC_CHECK5, BM_SETCHECK,(g_fShowBytes ? BST_CHECKED : BST_UNCHECKED),0);
+ WszSendDlgItemMessage(hwndDlg,IDC_CHECK6, BM_SETCHECK,(g_fShowSource ? BST_CHECKED : BST_UNCHECKED),0);
+ WszSendDlgItemMessage(hwndDlg,IDC_CHECK20, BM_SETCHECK,(g_fInsertSourceLines ? BST_CHECKED : BST_UNCHECKED),0);
+ WszSendDlgItemMessage(hwndDlg,IDC_CHECK7, BM_SETCHECK,(g_fTryInCode ? BST_CHECKED : BST_UNCHECKED),0);
+ if(!(fAsmChecked = g_fDumpAsmCode))
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK4), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK5), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK6), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK7), FALSE);
+ }
+ if(g_fTDC)
+ {
+ WszSendDlgItemMessage(hwndDlg,IDC_CHECK8, BM_SETCHECK,(g_fDumpMetaInfo ? BST_CHECKED : BST_UNCHECKED),0);
+ WszSendDlgItemMessage(hwndDlg,IDC_CHECK10,BM_SETCHECK,(g_ulMetaInfoFilter & MDInfo::dumpHeader ? BST_CHECKED : BST_UNCHECKED),0);
+ WszSendDlgItemMessage(hwndDlg,IDC_CHECK11,BM_SETCHECK,(g_ulMetaInfoFilter & MDInfo::dumpMoreHex ? BST_CHECKED : BST_UNCHECKED),0);
+ WszSendDlgItemMessage(hwndDlg,IDC_CHECK12,BM_SETCHECK,(g_ulMetaInfoFilter & MDInfo::dumpCSV ? BST_CHECKED : BST_UNCHECKED),0);
+ WszSendDlgItemMessage(hwndDlg,IDC_CHECK13,BM_SETCHECK,(g_ulMetaInfoFilter & MDInfo::dumpUnsat ? BST_CHECKED : BST_UNCHECKED),0);
+ WszSendDlgItemMessage(hwndDlg,IDC_CHECK16,BM_SETCHECK,(g_ulMetaInfoFilter & MDInfo::dumpValidate ? BST_CHECKED : BST_UNCHECKED),0);
+ WszSendDlgItemMessage(hwndDlg,IDC_CHECK14,BM_SETCHECK,(g_ulMetaInfoFilter & MDInfo::dumpSchema ? BST_CHECKED : BST_UNCHECKED),0);
+ WszSendDlgItemMessage(hwndDlg,IDC_CHECK15,BM_SETCHECK,(g_ulMetaInfoFilter & MDInfo::dumpRaw ? BST_CHECKED : BST_UNCHECKED),0);
+ WszSendDlgItemMessage(hwndDlg,IDC_CHECK17,BM_SETCHECK,(g_ulMetaInfoFilter & MDInfo::dumpRawHeaps ? BST_CHECKED : BST_UNCHECKED),0);
+ if(!(fMetaChecked = g_fDumpMetaInfo))
+ {
+ //EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK9), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK10), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK11), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK12), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK13), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK14), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK15), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK16), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK17), FALSE);
+ }
+ }
+ else
+ {
+ ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK8), SW_HIDE);
+ //ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK9), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK10), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK11), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK12), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK13), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK14), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK15), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK16), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK17), SW_HIDE);
+ }
+ ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK9), SW_HIDE);
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDC_CHECK3:
+ fAsmChecked = !fAsmChecked;
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK4), fAsmChecked);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK5), fAsmChecked);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK6), fAsmChecked);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK7), fAsmChecked);
+ return TRUE;
+
+ case IDC_CHECK8:
+ fMetaChecked = !fMetaChecked;
+ //EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK9), fMetaChecked);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK10), fMetaChecked);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK11), fMetaChecked);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK12), fMetaChecked);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK13), fMetaChecked);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK14), fMetaChecked);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK15), fMetaChecked);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK16), fMetaChecked);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK17), fMetaChecked);
+ return TRUE;
+
+ case IDOK:
+ if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_RADIO1, BM_GETCHECK,0,0)) g_uCodePage = g_uConsoleCP;
+ else if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_RADIO2, BM_GETCHECK,0,0)) g_uCodePage = CP_UTF8;
+ else if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_RADIO3, BM_GETCHECK,0,0)) g_uCodePage = 0xFFFFFFFF;
+ uCodePage = g_uCodePage;
+
+ g_fShowProgressBar = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK18, BM_GETCHECK,0,0));
+ g_fDumpHeader = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK1, BM_GETCHECK,0,0));
+ if(g_fTDC)
+ {
+ g_fDumpStats = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK2, BM_GETCHECK,0,0));
+ g_fDumpClassList = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK19, BM_GETCHECK,0,0));
+ }
+ g_fDumpAsmCode = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK3, BM_GETCHECK,0,0));
+ g_fDumpTokens = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK4, BM_GETCHECK,0,0));
+ g_fShowBytes = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK5, BM_GETCHECK,0,0));
+ g_fShowSource = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK6, BM_GETCHECK,0,0));
+ g_fInsertSourceLines = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK20, BM_GETCHECK,0,0));
+ g_fTryInCode = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK7, BM_GETCHECK,0,0));
+ if(g_fTDC)
+ {
+ g_fDumpMetaInfo = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK8, BM_GETCHECK,0,0));
+ g_ulMetaInfoFilter = 0;
+ if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK10, BM_GETCHECK,0,0)) g_ulMetaInfoFilter |= MDInfo::dumpHeader;
+ if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK11, BM_GETCHECK,0,0)) g_ulMetaInfoFilter |= MDInfo::dumpMoreHex;
+ if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK12, BM_GETCHECK,0,0)) g_ulMetaInfoFilter |= MDInfo::dumpCSV;
+ if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK13, BM_GETCHECK,0,0)) g_ulMetaInfoFilter |= MDInfo::dumpUnsat;
+ if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK16, BM_GETCHECK,0,0)) g_ulMetaInfoFilter |= MDInfo::dumpValidate;
+ if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK14, BM_GETCHECK,0,0)) g_ulMetaInfoFilter |= MDInfo::dumpSchema;
+ if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK15, BM_GETCHECK,0,0)) g_ulMetaInfoFilter |= MDInfo::dumpRaw;
+ if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK17, BM_GETCHECK,0,0)) g_ulMetaInfoFilter |= MDInfo::dumpRawHeaps;
+ }
+ EndDialog(hwndDlg,1);
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog(hwndDlg,0);
+ return TRUE;
+ }
+ break;
+
+ }
+ return FALSE;
+}
+
+static HWND help_hw;
+void * __cdecl HelpFileLoader(_In_z_ LPCWSTR lpHelpFileName)
+{
+ return HtmlHelpW(help_hw, lpHelpFileName, HH_DISPLAY_TOPIC, NULL);
+}
+
+//
+// Main window WndProc
+//
+#define CHECK_UNCHECK(x) { x=!x; CheckMenuItem(g_hMenu, LOWORD(wParam), (x ? MF_CHECKED : MF_UNCHECKED)); }
+
+#ifdef _PREFAST_
+#pragma warning(push)
+#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
+#endif
+LRESULT CALLBACK MainWndProc(
+ HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam
+)
+{
+ HWND hwndDasm;
+ static HCURSOR hWaitCursor = NULL;
+
+ if (hWaitCursor == NULL)
+ hWaitCursor = WszLoadCursor(NULL,IDC_WAIT);
+
+ switch (uMsg)
+ {
+ case WM_DROPFILES:
+ {
+ WCHAR wzFileName[MAX_FILENAME_LENGTH];
+ DragQueryFileW((HDROP)wParam,0,wzFileName,MAX_FILENAME_LENGTH-1);
+ memset(g_szInputFile,0,MAX_FILENAME_LENGTH);
+ WszWideCharToMultiByte(CP_UTF8,0,wzFileName,-1,g_szInputFile,MAX_FILENAME_LENGTH-1,NULL,NULL);
+ GetInputFileFullPath();
+ {
+ HCURSOR hWasCursor = SetCursor(hWaitCursor);
+ GUICleanupClassItems();
+ TreeView_DeleteAllItems(g_hwndTreeView);
+ Cleanup();
+ GUISetModule(g_szInputFile);
+ DumpFile();
+ SetCursor(hWasCursor);
+ }
+ DragFinish((HDROP)wParam);
+ }
+ break;
+
+ case WM_COMMAND:
+ {
+ if(HIWORD(wParam) > 1) break; // we are interested in commands from menu only
+ switch (LOWORD(wParam))
+ {
+ case IDM_OPEN:
+ {
+ WCHAR wzInputFile[MAX_FILENAME_LENGTH];
+ memset(wzInputFile,0,sizeof(wzInputFile));
+ if(strlen(g_szInputFile))
+ {
+ WszMultiByteToWideChar(CP_UTF8,0,g_szInputFile,-1,wzInputFile,MAX_FILENAME_LENGTH-1);
+ }
+ {
+ OPENFILENAMEW ofn;
+ WCHAR* wzFilter = RstrW(IDS_FILTER_IN); //L"PE file (*.exe,*.dll,*.mod,*.mdl,*.winmd)\0*.exe;*.dll;*.mod;*.mdl;*.winmd\0Any type (*.*)\0*.*\0\0";
+ const WCHAR* wzDefltExt = L"exe";
+ for(WCHAR* pwc = wzFilter; pwc = wcschr(pwc,'\t'); pwc++) *pwc = 0;
+ memset(&ofn,0,sizeof(OPENFILENAMEW));
+ ofn.lStructSize = sizeof(OPENFILENAMEW);
+ ofn.hwndOwner = hwnd;
+ ofn.lpstrFilter = wzFilter;
+ ofn.nFilterIndex = 0;
+ ofn.lpstrFile = wzInputFile;
+ ofn.nMaxFile = MAX_FILENAME_LENGTH-1;
+ ofn.Flags = OFN_FILEMUSTEXIST;
+ ofn.lpstrDefExt = wzDefltExt;
+ if(GetOpenFileName(&ofn))
+ {
+ HCURSOR hWasCursor = SetCursor(hWaitCursor);
+ GUICleanupClassItems();
+ TreeView_DeleteAllItems(g_hwndTreeView);
+ Cleanup();
+ memset(g_szInputFile,0,MAX_FILENAME_LENGTH);
+ WszWideCharToMultiByte(CP_UTF8,0,wzInputFile,-1,g_szInputFile,MAX_FILENAME_LENGTH-1,NULL,NULL);
+ GetInputFileFullPath();
+ GUISetModule(g_szInputFile);
+ DumpFile();
+ SetCursor(hWasCursor);
+ }
+ }
+ break;
+ }
+ case IDM_ABOUT:
+ {
+ _ASSERTE(g_hResources != NULL);
+ WszDialogBoxParam(g_hResources,MAKEINTRESOURCE(IDD_ABOUT),hwnd,(DLGPROC)AboutBoxProc,0L);
+ break;
+ }
+ case IDM_DUMP:
+ //case IDM_DUMP_TREE:
+ if(g_pImport)
+ {
+ unsigned uWasCodePage = g_uCodePage;
+ WCHAR wzOutputFile[MAX_FILENAME_LENGTH];
+ memset(wzOutputFile,0,sizeof(wzOutputFile));
+ if(strlen(g_szOutputFile))
+ {
+ WszMultiByteToWideChar(CP_UTF8,0,g_szOutputFile,-1,wzOutputFile,MAX_FILENAME_LENGTH-1);
+ }
+ {
+ OPENFILENAMEW ofn;
+ WCHAR* wzFilter = RstrW(IDS_FILTER_OUT);//L"IL file (*.il)\0*.il\0Text file (*.txt) \0*.txt\0Any type (*.*)\0*.*\0\0";
+ const WCHAR* wzDefltExt = L"il";
+ for(WCHAR* pwc = wzFilter; pwc = wcschr(pwc,'\t'); pwc++) *pwc = 0;
+ memset(&ofn,0,sizeof(OPENFILENAMEW));
+ ofn.lStructSize = sizeof(OPENFILENAMEW);
+ ofn.hwndOwner = hwnd;
+ ofn.lpstrFilter = wzFilter;
+ ofn.nFilterIndex = 0;
+ ofn.lpstrFile = wzOutputFile;
+ ofn.nMaxFile = MAX_FILENAME_LENGTH-1;
+ ofn.Flags = OFN_OVERWRITEPROMPT;
+ ofn.lpstrDefExt = wzDefltExt;
+ _ASSERTE(g_hResources != NULL);
+ if(WszDialogBoxParam(g_hResources,MAKEINTRESOURCE(IDD_DIALOG1),hwnd,(DLGPROC)DumpOptionsProc,0L) &&
+ GetSaveFileName(&ofn))
+ {
+ HCURSOR hWasCursor = SetCursor(hWaitCursor);
+ g_Mode &= ~MODE_GUI;
+ memset(g_szOutputFile,0,MAX_FILENAME_LENGTH);
+ WszWideCharToMultiByte(CP_UTF8,0,wzOutputFile,-1,g_szOutputFile,MAX_FILENAME_LENGTH-1,NULL,NULL);
+ g_pFile = OpenOutput(wzOutputFile);
+ if(g_pFile)
+ {
+ DumpFile(); // closes g_pFile upon completion
+ SetCursor(hWasCursor);
+ }
+ else
+ {
+ SetCursor(hWasCursor);
+ WszMessageBox(hwnd,wzOutputFile,RstrW(IDS_CANNOTOPENFILE),MB_OK|MB_ICONERROR | GetDasmMBRTLStyle());
+ }
+ g_szOutputFile[0] = 0;
+ g_Mode |= MODE_GUI;
+ //g_fShowSource = FALSE; // flag could have been changed for dump
+ }
+ }
+ g_uCodePage = uWasCodePage; // g_uCodePage is changed in DumpOptionsProc
+ }
+ break;
+
+ case IDM_DUMP_TREE:
+ if(g_pImport)
+ {
+ // Dump the tree view(fully expanded, with current sorting) to a text file
+ OPENFILENAMEW ofn;
+ WCHAR* wzFilter = RstrW(IDS_FILTER_OUT2); //L"Text file (*.txt) \0*.txt\0Any type (*.*)\0*.*\0\0";
+ const WCHAR* wzDefltExt = L"txt";
+ WCHAR szIndent[MAX_FILENAME_LENGTH];
+ FILE* pFile;
+ WCHAR wzOutputFile[MAX_FILENAME_LENGTH];
+ for(WCHAR* pwc = wzFilter; pwc = wcschr(pwc,'\t'); pwc++) *pwc = 0;
+ memset(wzOutputFile,0,sizeof(wzOutputFile));
+ memset(&ofn,0,sizeof(OPENFILENAMEW));
+ ofn.lStructSize = sizeof(OPENFILENAMEW);
+ ofn.hwndOwner = hwnd;
+ ofn.lpstrFilter = wzFilter;
+ ofn.nFilterIndex = 0;
+ ofn.lpstrFile = wzOutputFile;
+ ofn.nMaxFile = MAX_FILENAME_LENGTH-1;
+ ofn.Flags = OFN_OVERWRITEPROMPT;
+ ofn.lpstrDefExt = wzDefltExt;
+ if(GetSaveFileName(&ofn))
+ {
+ HCURSOR hWasCursor = SetCursor(hWaitCursor);
+ pFile = g_pFile;
+ g_pFile = OpenOutput(wzOutputFile);
+ szIndent[0] = 0;
+ if(g_pFile)
+ {
+ g_Mode &= ~MODE_GUI;
+ DumpTreeItem(g_hRoot,g_pFile,szIndent);
+ g_Mode |= MODE_GUI;
+ fclose(g_pFile);
+ SetCursor(hWasCursor);
+ }
+ else
+ {
+ SetCursor(hWasCursor);
+ WszMessageBox(hwnd,wzOutputFile,RstrW(IDS_CANNOTOPENFILE),MB_OK|MB_ICONERROR | GetDasmMBRTLStyle());
+ }
+ g_pFile = pFile;
+ }
+ }
+ break;
+
+ case IDM_EXIT:
+ {
+ WszSendMessage(GetActiveWindow(),WM_CLOSE,0,0);
+ }
+ break;
+
+ case IDM_FONT_TREE:
+ {
+ g_strChFontTree.hwndOwner = g_hwndMain;
+ if(ChooseFont(&g_strChFontTree))
+ {
+ DeleteObject((HGDIOBJ)g_hSmallFont);
+ g_hSmallFont = CreateFontIndirect(&g_strLogFontTree);
+ WszSendMessage(g_hwndTreeView,WM_SETFONT,(LPARAM) g_hSmallFont,TRUE);
+ if(g_hwndAsmInfo)
+ WszSendMessage(g_hwndAsmInfo,WM_SETFONT,(LPARAM) g_hSmallFont,TRUE);
+ SaveGUIFonts(&guiInfo);
+ }
+ break;
+ }
+
+ case IDM_FONT_DASM:
+ {
+ g_strChFontDasm.hwndOwner = g_hwndMain;
+ if(ChooseFont(&g_strChFontDasm))
+ {
+ if(g_fDumpRTF) { g_strLogFontDasm.lfWeight = FW_REGULAR; g_strLogFontDasm.lfItalic = FALSE; }
+ DeleteObject((HGDIOBJ)g_hFixedFont);
+ g_hFixedFont = CreateFontIndirect(&g_strLogFontDasm);
+
+ for (DWORD i = 0; i < g_NumDisasmBoxes; i++)
+ {
+ WszSendMessage((*g_DisasmBox)[i].hwndChild,WM_SETFONT,(LPARAM)g_hFixedFont,TRUE);
+ if(g_fDumpRTF)
+ GUIDumpItemToDisassemblyEditBox((void*)(*g_DisasmBox)[i].hwndChild,
+ (*g_DisasmBox)[i].tkClass,(*g_DisasmBox)[i].tkMember);
+ }
+ SaveGUIFonts(&guiInfo);
+ }
+ break;
+ }
+
+ case IDM_CAVERBAL:
+ {
+ CHECK_UNCHECK(g_fCAVerbal);
+ for (DWORD i = 0; i < g_NumDisasmBoxes; i++)
+ {
+ GUIDumpItemToDisassemblyEditBox((void*)(*g_DisasmBox)[i].hwndChild,
+ (*g_DisasmBox)[i].tkClass,
+ (*g_DisasmBox)[i].tkMember);
+ }
+ break;
+ }
+
+ case IDM_DUMPRTF:
+ {
+ CHECK_UNCHECK(g_fDumpRTF);
+ //GUIDumpAssemblyInfo();
+ for (DWORD i = 0; i < g_NumDisasmBoxes; i++)
+ {
+ mdToken tkClass = (*g_DisasmBox)[i].tkClass;
+ mdToken tkMember = (*g_DisasmBox)[i].tkMember;
+ if((TypeFromToken(tkMember)==0)&&(tkClass==IDM_SHOW_METAINFO))
+ continue;
+ GUIDisassemble(tkClass,tkMember,"UpdateThisDisassemblyBox");
+ }
+ break;
+ }
+
+ case IDM_SORT_BY_NAME:
+ {
+ CHECK_UNCHECK(g_fSortByName);
+ if(g_pImport)
+ {
+ if(!RefreshList()) goto CloseAndDestroy;
+ }
+ break;
+ }
+
+ case IDM_TREEVIEWFCN:
+ {
+ CHECK_UNCHECK(g_fTreeViewFCN);
+ if(g_pImport)
+ {
+ if(!RefreshList()) goto CloseAndDestroy;
+ }
+ break;
+ }
+
+ case IDM_SHOW_PUB:
+ {
+ CHECK_UNCHECK(g_fHidePub);
+UpdateVisibilityOptions:
+ g_fLimitedVisibility = g_fHidePub ||
+ g_fHidePriv ||
+ g_fHideFam ||
+ g_fHideFAA ||
+ g_fHideFOA ||
+ g_fHidePrivScope ||
+ g_fHideAsm;
+ if(g_pImport)
+ {
+ if(!RefreshList()) DestroyWindow(hwnd);
+ }
+ break;
+ }
+ case IDM_SHOW_PRIV:
+ {
+ CHECK_UNCHECK(g_fHidePriv);
+ goto UpdateVisibilityOptions;
+ }
+ case IDM_SHOW_FAM:
+ {
+ CHECK_UNCHECK(g_fHideFam);
+ goto UpdateVisibilityOptions;
+ }
+ case IDM_SHOW_ASM:
+ {
+ CHECK_UNCHECK(g_fHideAsm);
+ goto UpdateVisibilityOptions;
+ }
+ case IDM_SHOW_FAA:
+ {
+ CHECK_UNCHECK(g_fHideFAA);
+ goto UpdateVisibilityOptions;
+ }
+ case IDM_SHOW_FOA:
+ {
+ CHECK_UNCHECK(g_fHideFOA);
+ goto UpdateVisibilityOptions;
+ }
+ case IDM_SHOW_PSCOPE:
+ {
+ CHECK_UNCHECK(g_fHidePrivScope);
+ goto UpdateVisibilityOptions;
+ }
+ case IDM_FULL_INFO:
+ {
+ CHECK_UNCHECK(g_fFullMemberInfo);
+ if(g_pImport)
+ {
+ if(!RefreshList()) DestroyWindow(hwnd);
+ }
+ break;
+ }
+ case IDM_BYTES:
+ {
+ CHECK_UNCHECK(g_fShowBytes);
+ break;
+ }
+ case IDM_TOKENS:
+ {
+ CHECK_UNCHECK(g_fDumpTokens);
+ break;
+ }
+ case IDM_SOURCELINES:
+ {
+ CHECK_UNCHECK(g_fShowSource);
+ break;
+ }
+ case IDM_EXPANDTRY:
+ {
+ CHECK_UNCHECK(g_fTryInCode);
+ break;
+ }
+ case IDM_QUOTEALLNAMES:
+ {
+ CHECK_UNCHECK(g_fQuoteAllNames);
+ break;
+ }
+ case IDM_SHOW_HEADER:
+ {
+ GUIDisassemble(IDM_SHOW_HEADER,0,"Headers");
+ break;
+ }
+ case IDM_SHOW_STAT:
+ {
+ GUIDisassemble(IDM_SHOW_STAT,0,"Statistics");
+ break;
+ }
+ case IDM_HELP:
+ {
+ help_hw = hwnd;
+ FindLocalizedFile(L"ildasm.chm", &HelpFileLoader);
+ break;
+ }
+ case IDM_SHOW_METAINFO:
+ {
+ if(g_pImport)
+ GUIDisassemble(IDM_SHOW_METAINFO,0,"MetaInfo");
+ break;
+ }
+ case IDM_MI_HEADER:
+ {
+ WORD iSelection = LOWORD(wParam);
+ if(g_ulMetaInfoFilter & MDInfo::dumpHeader) g_ulMetaInfoFilter &= ~MDInfo::dumpHeader;
+ else g_ulMetaInfoFilter |= MDInfo::dumpHeader;
+ CheckMenuItem(g_hMetaInfoMenu, iSelection, (g_ulMetaInfoFilter & MDInfo::dumpHeader ? MF_CHECKED : MF_UNCHECKED));
+ if(g_ulMetaInfoFilter & MDInfo::dumpHeader)
+ {
+ // HeaderOnly specified,
+ // Suppress Counts,Sizes, Header,Schema and Header,Schema,Rows
+ g_ulMetaInfoFilter &= ~MDInfo::dumpCSV;
+ CheckMenuItem(g_hMetaInfoMenu, IDM_MI_CSV, MF_UNCHECKED);
+ g_ulMetaInfoFilter &= ~MDInfo::dumpSchema;
+ CheckMenuItem(g_hMetaInfoMenu, IDM_MI_SCHEMA, MF_UNCHECKED);
+ g_ulMetaInfoFilter &= ~MDInfo::dumpRaw;
+ CheckMenuItem(g_hMetaInfoMenu, IDM_MI_RAW, MF_UNCHECKED);
+ }
+ return 1; //break;
+ }
+ case IDM_MI_HEX:
+ {
+ WORD iSelection = LOWORD(wParam);
+ if(g_ulMetaInfoFilter & MDInfo::dumpMoreHex) g_ulMetaInfoFilter &= ~MDInfo::dumpMoreHex;
+ else g_ulMetaInfoFilter |= MDInfo::dumpMoreHex;
+ CheckMenuItem(g_hMetaInfoMenu, iSelection, (g_ulMetaInfoFilter & MDInfo::dumpMoreHex ? MF_CHECKED : MF_UNCHECKED));
+ return 1; //break;
+ }
+ case IDM_MI_CSV:
+ {
+ WORD iSelection = LOWORD(wParam);
+ if(g_ulMetaInfoFilter & MDInfo::dumpCSV) g_ulMetaInfoFilter &= ~MDInfo::dumpCSV;
+ else g_ulMetaInfoFilter |= MDInfo::dumpCSV;
+ CheckMenuItem(g_hMetaInfoMenu, iSelection, (g_ulMetaInfoFilter & MDInfo::dumpCSV ? MF_CHECKED : MF_UNCHECKED));
+ if(g_ulMetaInfoFilter & MDInfo::dumpCSV)
+ {
+ // Counts,Sizes specified,
+ // Suppress HeaderOnly, Header,Schema and Header,Schema,Rows
+ g_ulMetaInfoFilter &= ~MDInfo::dumpHeader;
+ CheckMenuItem(g_hMetaInfoMenu, IDM_MI_HEADER, MF_UNCHECKED);
+ g_ulMetaInfoFilter &= ~MDInfo::dumpSchema;
+ CheckMenuItem(g_hMetaInfoMenu, IDM_MI_SCHEMA, MF_UNCHECKED);
+ g_ulMetaInfoFilter &= ~MDInfo::dumpRaw;
+ CheckMenuItem(g_hMetaInfoMenu, IDM_MI_RAW, MF_UNCHECKED);
+ }
+ return 1; //break;
+ }
+ case IDM_MI_UNREX:
+ {
+ WORD iSelection = LOWORD(wParam);
+ if(g_ulMetaInfoFilter & MDInfo::dumpUnsat) g_ulMetaInfoFilter &= ~MDInfo::dumpUnsat;
+ else g_ulMetaInfoFilter |= MDInfo::dumpUnsat;
+ CheckMenuItem(g_hMetaInfoMenu, iSelection, (g_ulMetaInfoFilter & MDInfo::dumpUnsat ? MF_CHECKED : MF_UNCHECKED));
+ return 1; //break;
+ }
+ case IDM_MI_SCHEMA:
+ {
+ WORD iSelection = LOWORD(wParam);
+ if(g_ulMetaInfoFilter & MDInfo::dumpSchema) g_ulMetaInfoFilter &= ~MDInfo::dumpSchema;
+ else g_ulMetaInfoFilter |= MDInfo::dumpSchema;
+ CheckMenuItem(g_hMetaInfoMenu, iSelection, (g_ulMetaInfoFilter & MDInfo::dumpSchema ? MF_CHECKED : MF_UNCHECKED));
+ if(g_ulMetaInfoFilter & MDInfo::dumpSchema)
+ {
+ // Header,Schema specified,
+ // suppress Counts,Sizes, HeaderOnly and Header,Schema,Rows
+ g_ulMetaInfoFilter &= ~MDInfo::dumpCSV;
+ CheckMenuItem(g_hMetaInfoMenu, IDM_MI_CSV, MF_UNCHECKED);
+ g_ulMetaInfoFilter &= ~MDInfo::dumpHeader;
+ CheckMenuItem(g_hMetaInfoMenu, IDM_MI_HEADER, MF_UNCHECKED);
+ g_ulMetaInfoFilter &= ~MDInfo::dumpRaw;
+ CheckMenuItem(g_hMetaInfoMenu, IDM_MI_RAW, MF_UNCHECKED);
+ }
+ return 1; //break;
+ }
+ case IDM_MI_RAW:
+ {
+ WORD iSelection = LOWORD(wParam);
+ if(g_ulMetaInfoFilter & MDInfo::dumpRaw) g_ulMetaInfoFilter &= ~MDInfo::dumpRaw;
+ else g_ulMetaInfoFilter |= MDInfo::dumpRaw;
+ CheckMenuItem(g_hMetaInfoMenu, iSelection, (g_ulMetaInfoFilter & MDInfo::dumpRaw ? MF_CHECKED : MF_UNCHECKED));
+ if(g_ulMetaInfoFilter & MDInfo::dumpRaw)
+ {
+ // Header,Schema,Rows specified,
+ // suppress Counts,Sizes, HeaderOnly and Header,Schema
+ g_ulMetaInfoFilter &= ~MDInfo::dumpCSV;
+ CheckMenuItem(g_hMetaInfoMenu, IDM_MI_CSV, MF_UNCHECKED);
+ g_ulMetaInfoFilter &= ~MDInfo::dumpHeader;
+ CheckMenuItem(g_hMetaInfoMenu, IDM_MI_HEADER, MF_UNCHECKED);
+ g_ulMetaInfoFilter &= ~MDInfo::dumpSchema;
+ CheckMenuItem(g_hMetaInfoMenu, IDM_MI_SCHEMA, MF_UNCHECKED);
+ }
+ return 1; //break;
+ }
+ case IDM_MI_HEAPS:
+ {
+ WORD iSelection = LOWORD(wParam);
+ if(g_ulMetaInfoFilter & MDInfo::dumpRawHeaps) g_ulMetaInfoFilter &= ~MDInfo::dumpRawHeaps;
+ else g_ulMetaInfoFilter |= MDInfo::dumpRawHeaps;
+ CheckMenuItem(g_hMetaInfoMenu, iSelection, (g_ulMetaInfoFilter & MDInfo::dumpRawHeaps ? MF_CHECKED : MF_UNCHECKED));
+ return 1; //break;
+ }
+ case IDM_MI_VALIDATE:
+ {
+ WORD iSelection = LOWORD(wParam);
+ if(g_ulMetaInfoFilter & MDInfo::dumpValidate) g_ulMetaInfoFilter &= ~MDInfo::dumpValidate;
+ else g_ulMetaInfoFilter |= MDInfo::dumpValidate;
+ CheckMenuItem(g_hMetaInfoMenu, iSelection, (g_ulMetaInfoFilter & MDInfo::dumpValidate ? MF_CHECKED : MF_UNCHECKED));
+ return 1; //break;
+ }
+
+ }
+
+ break;
+ }
+
+ case WM_SETFOCUS:
+ SetFocus(g_hwndTreeView);
+ break;
+
+ case WM_SIZE:
+ {
+ DWORD cxClient = LOWORD(lParam);
+ DWORD cyClient = HIWORD(lParam);
+ DWORD dy;
+
+ dy = cyClient >> 3;
+ if(dy < 50) dy = 50;
+ if(cyClient < dy+4) cyClient = dy+4;
+
+ // Resize listview window
+ MoveWindow(
+ g_hwndTreeView,
+ 0,
+ 0,
+ cxClient,
+ cyClient-dy-2,
+ TRUE // repaint
+ );
+ // Resize AsmInfo window
+ MoveWindow(
+ g_hwndAsmInfo,
+ 0,
+ cyClient-dy-1,
+ cxClient,
+ dy,
+ TRUE // repaint
+ );
+
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ if (wParam == ID_TREEVIEW)
+ {
+ NMHDR * pNMHDR = (NMHDR*) lParam;
+ switch (pNMHDR->code)
+ {
+ case TVN_KEYDOWN:
+ {
+ NMTVKEYDOWN *pKeyDown = (NMTVKEYDOWN *) pNMHDR;
+
+ if (pKeyDown->wVKey == '\r')
+ {
+ if(DoubleClickSelectedMember(g_CurSelItem) == NULL)
+ TreeView_Expand(g_hwndTreeView,g_CurSelItem,TVE_TOGGLE);
+ }
+ break;
+ }
+
+ case NM_DBLCLK:
+ {
+ hwndDasm = DoubleClickSelectedMember(g_CurSelItem);
+ if(hwndDasm)
+ {
+ PostMessageA(hwndDasm,WM_ACTIVATE,WA_CLICKACTIVE,0);
+ PostMessageA(hwndDasm,WM_SETFOCUS,0,0);
+ }
+ break;
+ }
+
+ case TVN_SELCHANGEDW:
+ case TVN_SELCHANGEDA:
+ {
+ NMTREEVIEW *pTV = (NMTREEVIEW *) pNMHDR;
+ /*
+ TVITEM SelItem;
+ char szText[256];
+
+ memset(&SelItem, 0, sizeof(SelItem));
+ SelItem.mask = TVIF_TEXT;
+ SelItem.pszText = szText;
+ SelItem.cchTextMax = sizeof(szText)-1;
+ SelItem.hItem = pTV->itemNew.hItem;
+
+ g_CurSelItem = SelItem.hItem;
+ SendMessageA(g_hwndTreeView, TVM_GETITEM, 0, (LPARAM)&SelItem);
+ */
+ g_CurSelItem = pTV->itemNew.hItem;
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+
+ case WM_CLOSE:
+ CloseAndDestroy:
+ // HTML help window is closed automatically
+ {
+ RECT r;
+ ShowWindow(hwnd,SW_RESTORE);
+ GetWindowRect(hwnd,(LPRECT)&r);
+ guiInfo.x = r.left;
+ guiInfo.y = r.top;
+ guiInfo.w = r.right - r.left;
+ guiInfo.h = r.bottom - r.top;
+ SaveGUIFonts(&guiInfo);
+ }
+ DestroyWindow(hwnd); // Generates the WM_DESTROY message
+ break;
+
+ case WM_DESTROY :
+ PostQuitMessage(0); // Puts a WM_QUIT in the queue
+ break;
+
+ default :
+ return DefWindowProcW(hwnd, uMsg, wParam, lParam);
+ }
+
+ return 0;
+}
+#ifdef _PREFAST_
+#pragma warning(pop)
+#endif
+
+
+//
+// Create the treeview in the main window
+//
+HWND CreateTreeView(HWND hwndParent)
+{
+ HWND hwndTree;
+ RECT rcl;
+ DWORD tvs =
+ TVS_HASLINES
+ |TVS_HASBUTTONS
+ |TVS_LINESATROOT
+ |TVS_SHOWSELALWAYS
+ // |TVS_TRACKSELECT
+ // |TVS_SINGLEEXPAND
+ |TVS_DISABLEDRAGDROP
+ ;
+ unsigned cy,dy;
+
+ GetClientRect(hwndParent, &rcl);
+ cy = rcl.bottom - rcl.top;
+ dy = cy >> 3;
+ hwndTree = WszCreateWindowEx(
+ 0,
+ WC_TREEVIEWW,
+ NULL,
+ WS_VISIBLE|WS_CHILD|WS_BORDER|tvs,
+ 0,
+ 0,
+ rcl.right - rcl.left,
+ cy-dy-2, //rcl.bottom - rcl.top,
+ hwndParent,
+ (HMENU) ID_TREEVIEW,
+ g_hInstance,
+ NULL
+ );
+ g_hwndAsmInfo = NULL;
+ if (hwndTree == NULL)
+ return NULL;
+
+ WszSendMessage(hwndTree,WM_SETFONT,(LPARAM) g_hSmallFont,FALSE);
+
+ TreeView_SetBkColor(hwndTree,-1);
+ TreeView_SetImageList(hwndTree, g_hImageList, TVSIL_NORMAL);
+
+ g_hwndAsmInfo = WszCreateWindowEx(
+ 0, //WS_EX_TOOLWINDOW,
+ g_fDumpRTF ? L"RichEdit20A" : L"EDIT",
+ NULL,
+ WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE | WS_BORDER //| WS_CAPTION | WS_OVERLAPPEDWINDOW
+ | ES_MULTILINE | ES_READONLY | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_NOHIDESEL,
+ 0,
+ cy-dy-1,
+ rcl.right - rcl.left,
+ dy,
+ hwndParent,
+ (HMENU) ID_LISTBOX,
+ g_hInstance, // hinst
+ NULL
+ );
+ if(g_hwndAsmInfo)
+ {
+ WszSendMessage(g_hwndAsmInfo,WM_SETFONT,(LPARAM) g_hSmallFont,FALSE);
+ }
+
+ return hwndTree;
+}
+
+
+//
+// Add one item to a treeview
+//
+HTREEITEM AddOneItem(HTREEITEM hParent, const char *pszText, HTREEITEM hInsAfter, int iImage, HWND hwndTree, BOOL fExpanded)
+{
+ HTREEITEM hItem;
+ WCHAR* wz = UtfToUnicode(pszText);
+ ULONG lLen = (ULONG)wcslen(wz);
+ TVINSERTSTRUCTW tvIns;
+ memset(&tvIns, 0, sizeof(tvIns));
+
+ tvIns.item.mask = TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM;
+ tvIns.item.pszText = wz;
+ tvIns.item.cchTextMax = lLen;
+ tvIns.item.iImage = iImage;
+ tvIns.item.iSelectedImage = iImage;
+
+ tvIns.hInsertAfter = hInsAfter;
+ tvIns.hParent = hParent;
+
+ hItem = (HTREEITEM)WszSendMessage(hwndTree, TVM_INSERTITEMW, 0, (LPARAM)(&tvIns));
+
+ return hItem;
+}
+
+#ifdef _PREFAST_
+#pragma warning(push)
+#pragma warning(disable:22018) // Suppress PREFast warning about Integer overflow/underflow
+#endif
+//ulen cannot be greater than GlobalBufferLen by the definition of ulen. Therefore it's safe to disable this warning here.
+void AddMethodToGUI(
+ mdTypeDef cl,
+ ClassItem_t * pClassItem,
+ const char *pszNamespace,
+ const char *pszClassName,
+ const char *pszMethodName,
+ PCCOR_SIGNATURE pComSig,
+ unsigned cComSig,
+ mdMethodDef mbMethod,
+ DWORD dwAttrs
+)
+{
+ HTREEITEM hParent;
+ char* szName;
+ ULONG ulLen,ulImageIndex;
+ BOOL wasDumpRTF;
+
+ memset(GlobalBuffer,0,GlobalBufferLen);
+ sprintf_s(GlobalBuffer, GlobalBufferLen,g_fFullMemberInfo ? "method %s : ": "%s : ",pszMethodName);
+ InGlobalBuffer = (UINT32)strlen(GlobalBuffer);
+ ulLen = InGlobalBuffer;
+ wasDumpRTF = g_fDumpRTF;
+ g_fDumpRTF = FALSE;
+ mdToken tkVarOwner = g_tkVarOwner;
+ g_tkVarOwner = cl;
+ DumpMethod(mbMethod, pszClassName,VAL32(g_CORHeader->EntryPointToken),(void *)g_hwndTreeView,FALSE);
+ g_tkVarOwner = tkVarOwner;
+ g_fDumpRTF = wasDumpRTF;
+ GlobalBuffer[InGlobalBuffer-2] = 0; // get rid of \r\n
+
+ szName = &GlobalBuffer[ulLen];
+
+ if(strstr(szName,"instance ") == szName) strcpy_s(szName,GlobalBufferLen-ulLen,szName+9);
+
+ szName = GlobalBuffer;
+
+ hParent = pClassItem->hItem;
+
+ _ASSERTE(pClassItem->CurMember < pClassItem->SubItems);
+
+ if((strchr(szName, '<'))&&(strchr(szName, '>')))
+ {
+ ulImageIndex = IsMdStatic(dwAttrs) ? STATIC_METHOD_GEN_IMAGE_INDEX : METHOD_GEN_IMAGE_INDEX;
+ }
+ else
+ {
+ ulImageIndex = IsMdStatic(dwAttrs) ? STATIC_METHOD_IMAGE_INDEX : METHOD_IMAGE_INDEX;
+ }
+
+ pClassItem->pMembers[pClassItem->CurMember].hItem = AddOneItem(
+ hParent, szName, TVI_LAST, ulImageIndex, g_hwndTreeView, FALSE
+ );
+ pClassItem->pMembers[pClassItem->CurMember].Discriminator = TREEITEM_TYPE_MEMBER;
+ pClassItem->pMembers[pClassItem->CurMember].mbMember = mbMethod;
+ pClassItem->CurMember++;
+}
+
+#ifdef _PREFAST_
+#pragma warning(pop)
+#endif
+BOOL NamespaceMatch(const char *pszNamespace, __in __nullterminated char *pszString)
+{
+ if (strncmp(pszNamespace, pszString, strlen(pszNamespace)) == 0)
+ {
+ if (pszString[ strlen(pszNamespace) ] == NAMESPACE_SEPARATOR_CHAR)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void AddFieldToGUI(
+ mdTypeDef cl,
+ ClassItem_t *pClassItem,
+ const char *pszNamespace,
+ const char *pszClassName,
+ const char *pszFieldName,
+ const char *pszSignature,
+ mdFieldDef mbField,
+ DWORD dwAttrs
+)
+{
+ DWORD Dimensions;
+ ULONG ul1,ul2;
+ BOOL wasDumpRTF;
+ HTREEITEM hParent = pClassItem->hItem;
+
+ Dimensions = 0;
+
+ memset(GlobalBuffer,0,GlobalBufferLen);
+ sprintf_s(GlobalBuffer,GlobalBufferLen,g_fFullMemberInfo ? "field %s : " : "%s : ",pszFieldName);
+ InGlobalBuffer = (UINT32)strlen(GlobalBuffer);
+ GetClassLayout(cl,&ul1,&ul2);
+ wasDumpRTF = g_fDumpRTF;
+ g_fDumpRTF = FALSE;
+ DumpField(mbField, pszClassName,(void *)g_hwndTreeView,FALSE);
+ g_fDumpRTF = wasDumpRTF;
+ GlobalBuffer[InGlobalBuffer-2] = 0; // get rid of \r\n
+ char* pch = strchr(GlobalBuffer,'\r');
+ if(pch) strcpy_s(pch,5," ...");
+ _ASSERTE(pClassItem->CurMember < pClassItem->SubItems);
+
+ pClassItem->pMembers[pClassItem->CurMember].mbMember = mbField;
+ pClassItem->pMembers[pClassItem->CurMember].Discriminator = TREEITEM_TYPE_MEMBER;
+ pClassItem->pMembers[pClassItem->CurMember++].hItem = AddOneItem(
+ hParent,
+ GlobalBuffer, //szType,
+ TVI_LAST,
+ (dwAttrs & mdStatic) ? STATIC_FIELD_IMAGE_INDEX : FIELD_IMAGE_INDEX,
+ g_hwndTreeView,
+ FALSE
+ );
+}
+
+void AddEventToGUI(
+ mdTypeDef cl,
+ ClassItem_t *pClassItem,
+ const char *pszNamespace,
+ const char *pszClassName,
+ DWORD dwClassAttrs,
+ mdEvent mbEvent
+)
+{
+ DWORD Dimensions;
+ BOOL wasDumpRTF;
+ HTREEITEM hParent = pClassItem->hItem;
+
+ Dimensions = 0;
+
+ memset(GlobalBuffer,0,GlobalBufferLen);
+ if(g_fFullMemberInfo) strcpy_s(GlobalBuffer,GlobalBufferLen,"event ");
+ InGlobalBuffer = (UINT32)strlen(GlobalBuffer);
+ wasDumpRTF = g_fDumpRTF;
+ g_fDumpRTF = FALSE;
+ DumpEvent(mbEvent, pszClassName, dwClassAttrs, (void *)g_hwndTreeView, FALSE); //FALSE=don't dump the body
+ g_fDumpRTF = wasDumpRTF;
+ GlobalBuffer[InGlobalBuffer-2] = 0; // get rid of \r\n
+
+ _ASSERTE(pClassItem->CurMember < pClassItem->SubItems);
+
+ pClassItem->pMembers[pClassItem->CurMember].mbMember = mbEvent;
+ pClassItem->pMembers[pClassItem->CurMember].Discriminator = TREEITEM_TYPE_MEMBER;
+ pClassItem->pMembers[pClassItem->CurMember++].hItem = AddOneItem(
+ hParent,
+ GlobalBuffer, //szType,
+ TVI_LAST,
+ EVENT_IMAGE_INDEX,
+ g_hwndTreeView,
+ FALSE
+ );
+}
+
+void AddPropToGUI(
+ mdTypeDef cl,
+ ClassItem_t *pClassItem,
+ const char *pszNamespace,
+ const char *pszClassName,
+ DWORD dwClassAttrs,
+ mdProperty mbProp
+)
+{
+ DWORD Dimensions;
+ BOOL wasDumpRTF;
+ HTREEITEM hParent = pClassItem->hItem;
+
+ Dimensions = 0;
+
+ memset(GlobalBuffer,0,GlobalBufferLen);
+ if(g_fFullMemberInfo) strcpy_s(GlobalBuffer,GlobalBufferLen,"prop ");
+ InGlobalBuffer = (UINT32)strlen(GlobalBuffer);
+ wasDumpRTF = g_fDumpRTF;
+ g_fDumpRTF = FALSE;
+ DumpProp(mbProp, pszClassName, dwClassAttrs, (void *)g_hwndTreeView, FALSE); //FALSE=don't dump the body
+ g_fDumpRTF = wasDumpRTF;
+ GlobalBuffer[InGlobalBuffer-2] = 0; // get rid of \r\n
+
+ _ASSERTE(pClassItem->CurMember < pClassItem->SubItems);
+
+ pClassItem->pMembers[pClassItem->CurMember].mbMember = mbProp;
+ pClassItem->pMembers[pClassItem->CurMember].Discriminator = TREEITEM_TYPE_MEMBER;
+ pClassItem->pMembers[pClassItem->CurMember++].hItem = AddOneItem(
+ hParent,
+ GlobalBuffer, //szType,
+ TVI_LAST,
+ PROP_IMAGE_INDEX,
+ g_hwndTreeView,
+ FALSE
+ );
+}
+
+
+
+HTREEITEM FindCreateNamespaceRoot(const char *pszNamespace)
+{
+ DWORD i;
+ HTREEITEM hRoot;
+ DWORD l = 0,ll;
+
+ if (!pszNamespace || !*pszNamespace)
+ return g_hRoot; // not in a namespace, use tree root
+
+ hRoot = g_hRoot;
+ for (i = 0; i < g_NumNamespaces; i++)
+ {
+ if (!strcmp(pszNamespace, (*g_NamespaceList)[i].pszNamespace))
+ return (*g_NamespaceList)[i].hRoot;
+ }
+ for (i = 0; i < g_NumNamespaces; i++)
+ {
+ if(strstr(pszNamespace,(*g_NamespaceList)[i].pszNamespace) == pszNamespace)
+ {
+ ll = (DWORD)strlen((*g_NamespaceList)[i].pszNamespace);
+ if((ll > l)&&(pszNamespace[ll] == '.'))
+ {
+ hRoot = (*g_NamespaceList)[i].hRoot;
+ l = ll;
+ }
+ }
+ }
+
+ hRoot = AddOneItem(hRoot, pszNamespace, TVI_LAST, NAMESPACE_IMAGE_INDEX, g_hwndTreeView, TRUE);
+ (*g_NamespaceList)[g_NumNamespaces].pszNamespace = pszNamespace;
+ (*g_NamespaceList)[g_NumNamespaces].hRoot = hRoot;
+ g_NumNamespaces++;
+
+ return hRoot;
+}
+
+
+Namespace_t *FindNamespace(const char *pszNamespace)
+{
+ DWORD i;
+
+ for (i = 0; i < g_NumNamespaces; i++)
+ {
+ if (!strcmp(pszNamespace, (*g_NamespaceList)[i].pszNamespace))
+ return &(*g_NamespaceList)[i];
+ }
+
+ return NULL;
+}
+
+
+void GUICleanupClassItems()
+{
+ DWORD i;
+ WCHAR* sz=L"\0\0";
+
+ for (i = 0; i < g_NumClassItems; i++)
+ {
+ if((*g_ClassItemList)[i].pMembers)
+ {
+ delete[] (*g_ClassItemList)[i].pMembers;
+ (*g_ClassItemList)[i].pMembers = NULL;
+ }
+ }
+ for (i = 0; i < g_NumDisasmBoxes; i++)
+ {
+ PostMessageA((*g_DisasmBox)[i].hwndContainer,WM_CLOSE,0,0);
+ }
+ WszSendMessage(g_hwndAsmInfo,WM_SETTEXT,0,(LPARAM)sz);
+ EnableMenuItem(g_hMenu,(UINT)(UINT_PTR)g_hViewMenu, MF_GRAYED);
+ EnableMenuItem(g_hFileMenu,IDM_DUMP,MF_GRAYED);
+ EnableMenuItem(g_hFileMenu,IDM_DUMP_TREE,MF_GRAYED);
+}
+
+//
+// Add a new class tree node
+//
+ClassItem_t *AddClassToGUI(
+ mdTypeDef cl,
+ UINT uImageIndex,
+ const char *pszNamespace,
+ const char *pszClassName,
+ DWORD cSubItems,
+ HTREEITEM *phRoot // Returns the namespace root (NOT the class root)
+)
+{
+ HTREEITEM hRoot;
+
+ if(*phRoot)
+ hRoot = *phRoot;
+ else
+ {
+ hRoot = FindCreateNamespaceRoot(pszNamespace);
+ _ASSERTE(hRoot != NULL);
+
+ *phRoot = hRoot;
+ }
+
+ (*g_ClassItemList)[g_NumClassItems].hItem = AddOneItem(hRoot, pszClassName, TVI_LAST, uImageIndex, g_hwndTreeView, FALSE);
+ (*g_ClassItemList)[g_NumClassItems].cl = cl;
+ (*g_ClassItemList)[g_NumClassItems].SubItems = cSubItems;
+ (*g_ClassItemList)[g_NumClassItems].CurMember = 0;
+
+ (*g_ClassItemList)[g_NumClassItems].pMembers = new (nothrow) TreeItem_t[cSubItems];
+
+ g_NumClassItems++;
+
+ return &(*g_ClassItemList)[g_NumClassItems-1];
+}
+
+
+void AddGlobalFunctions()
+{
+ HRESULT hr = S_OK;
+ HENUMInternal hEnumMethod;
+ mdToken FuncToken;
+ DWORD i;
+ HTREEITEM hNamespaceRoot = NULL;
+ DWORD NumGlobals;
+
+ ClassItem_t* pClassItem = &(*g_ClassItemList)[0];
+
+ if (SUCCEEDED(g_pImport->EnumGlobalFieldsInit(&hEnumMethod)))
+ {
+ NumGlobals = g_pImport->EnumGetCount(&hEnumMethod);
+ MemberInfo* fields = new (nothrow) MemberInfo[NumGlobals];
+ MemberInfo* curField = fields;
+
+ for (i = 0; g_pImport->EnumNext(&hEnumMethod, &FuncToken); i++)
+ {
+ curField->token = FuncToken;
+ if (FAILED(g_pImport->GetFieldDefProps(FuncToken, &curField->dwAttrs)) ||
+ FAILED(g_pImport->GetNameOfFieldDef(FuncToken, &curField->pszMemberName)))
+ {
+ curField->pszMemberName = "Invalid FieldDef record";
+ }
+ MAKE_NAME_IF_NONE(curField->pszMemberName,FuncToken);
+ //curField->pComSig = g_pImport->GetSigOfFieldDef(FuncToken, &curMethod->cComSig);
+ curField++;
+ }
+ g_pImport->EnumClose(&hEnumMethod);
+
+ _ASSERTE(curField - fields == (int) NumGlobals);
+
+ if(g_fSortByName) qsort(fields, NumGlobals, sizeof MemberInfo, memberCmp);
+
+ for(curField = fields; curField < &fields[NumGlobals];curField++)
+ {
+ if(g_fLimitedVisibility)
+ {
+ if(g_fHidePub && IsFdPublic(curField->dwAttrs)) continue;
+ if(g_fHidePriv && IsFdPrivate(curField->dwAttrs)) continue;
+ if(g_fHideFam && IsFdFamily(curField->dwAttrs)) continue;
+ if(g_fHideAsm && IsFdAssembly(curField->dwAttrs)) continue;
+ if(g_fHideFOA && IsFdFamORAssem(curField->dwAttrs)) continue;
+ if(g_fHideFAA && IsFdFamANDAssem(curField->dwAttrs)) continue;
+ if(g_fHidePrivScope && IsFdPrivateScope(curField->dwAttrs)) continue;
+ }
+ AddFieldToGUI(NULL, pClassItem, NULL, "Global Fields", curField->pszMemberName, NULL, curField->token, curField->dwAttrs);
+ }
+ delete[] fields;
+ }
+ if (FAILED(g_pImport->EnumGlobalFunctionsInit(&hEnumMethod)))
+ return;
+
+ NumGlobals = g_pImport->EnumGetCount(&hEnumMethod);
+ MemberInfo* methods = new (nothrow) MemberInfo[NumGlobals];
+ MemberInfo* curMethod = methods;
+
+ for (i = 0; g_pImport->EnumNext(&hEnumMethod, &FuncToken); i++)
+ {
+ curMethod->token = FuncToken;
+ if (FAILED(g_pImport->GetMethodDefProps(FuncToken, &curMethod->dwAttrs)) ||
+ FAILED(g_pImport->GetNameOfMethodDef(FuncToken, &curMethod->pszMemberName)))
+ {
+ curMethod->pszMemberName = "Invalid MethodDef record";
+ }
+ MAKE_NAME_IF_NONE(curMethod->pszMemberName,FuncToken);
+ if (FAILED(g_pImport->GetSigOfMethodDef(FuncToken, &curMethod->cComSig, &curMethod->pComSig)))
+ {
+ curMethod->pszMemberName = "Invalid MethodDef record";
+ curMethod->cComSig = 0;
+ curMethod->pComSig = NULL;
+ }
+ curMethod++;
+ }
+ g_pImport->EnumClose(&hEnumMethod);
+
+ _ASSERTE(curMethod - methods == (int) NumGlobals);
+
+ if(g_fSortByName) qsort(methods, NumGlobals, sizeof MemberInfo, memberCmp);
+
+ for(curMethod = methods; curMethod < &methods[NumGlobals];curMethod++)
+ {
+ if(g_fLimitedVisibility)
+ {
+ if(g_fHidePub && IsMdPublic(curMethod->dwAttrs)) continue;
+ if(g_fHidePriv && IsMdPrivate(curMethod->dwAttrs)) continue;
+ if(g_fHideFam && IsMdFamily(curMethod->dwAttrs)) continue;
+ if(g_fHideAsm && IsMdAssem(curMethod->dwAttrs)) continue;
+ if(g_fHideFOA && IsMdFamORAssem(curMethod->dwAttrs)) continue;
+ if(g_fHideFAA && IsMdFamANDAssem(curMethod->dwAttrs)) continue;
+ if(g_fHidePrivScope && IsMdPrivateScope(curMethod->dwAttrs)) continue;
+ }
+ AddMethodToGUI(NULL, pClassItem, NULL, "Global Functions", curMethod->pszMemberName, curMethod->pComSig, curMethod->cComSig, curMethod->token, curMethod->dwAttrs);
+ }
+ delete[] methods;
+ return;
+}
+
+
+BOOL CreateMainWindow()
+{
+ DWORD dwStyle, dwStyleEx;
+
+// If only showing GUI's IL window, than we don't want to see the main window
+// However, main window still manages our data, so we have to still create it. :(
+// But we can "pretend" it's not there by hiding it (no WS_VISIBLE, and add WS_EX_TOOLWINDOW)
+ if (IsGuiILOnly()) {
+ dwStyle = WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_POPUP | WS_SIZEBOX;
+ dwStyleEx = WS_EX_TOOLWINDOW;
+ } else {
+ dwStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CAPTION | WS_POPUP | WS_SIZEBOX;
+ dwStyleEx = WS_EX_CLIENTEDGE;
+ }
+ g_hwndMain = WszCreateWindowEx(dwStyleEx,
+ MAIN_WINDOW_CLASSW,
+ L"IL DASM ", //MAIN_WINDOW_CAPTIONW,
+ dwStyle,
+ guiInfo.x,
+ guiInfo.y,
+ guiInfo.w,
+ guiInfo.h,
+ NULL,
+ g_hMenu, // menu
+ g_hInstance, // hinst
+ NULL
+ );
+ if (g_hwndMain == NULL)
+ return FALSE;
+ DragAcceptFiles(g_hwndMain,TRUE);
+ SendMessageA(g_hwndMain,WM_SETTEXT, 0, (LPARAM)"IL DASM ");
+ return TRUE;
+}
+
+
+//
+// Given a CL token, find the classitem for it
+//
+ClassItem_t *FindClassItem(mdTypeDef cl)
+{
+ DWORD i;
+
+ for (i = 0; i < g_NumClassItems; i++)
+ {
+ if ((*g_ClassItemList)[i].cl == cl)
+ return &(*g_ClassItemList)[i];
+ }
+
+ return NULL;
+}
+
+
+//
+// Given a class name, find the classitem for it (may fail)
+//
+ClassItem_t *FindClassItem(__in_opt __nullterminated char *pszFindNamespace, __in __nullterminated char *pszFindName)
+{
+ DWORD i;
+
+ for (i = 0; i < g_NumClassItems; i++)
+ {
+ const char *pszClassName;
+ const char *pszNamespace;
+
+ if((*g_ClassItemList)[i].cl)
+ {
+
+ if (FAILED(g_pImport->GetNameOfTypeDef(
+ (*g_ClassItemList)[i].cl,
+ &pszClassName,
+ &pszNamespace)))
+ {
+ pszClassName = pszNamespace = "Invalid TypeDef record";
+ }
+ MAKE_NAME_IF_NONE(pszClassName,(*g_ClassItemList)[i].cl);
+
+ if (!strcmp(pszFindName, pszClassName))
+ {
+ if ((((pszFindNamespace == NULL)||(*pszFindNamespace == 0))
+ &&((pszNamespace == NULL)||(*pszNamespace == 0)))
+ ||(!strcmp(pszFindNamespace, pszNamespace)))
+ return &(*g_ClassItemList)[i];
+ }
+ }
+ }
+ //MessageBox(NULL,pszFindName,"Class Not Found",MB_OK);
+ return NULL;
+}
+
+
+ClassItem_t *FindClassItem(HTREEITEM hItem)
+{
+ DWORD i;
+
+ for (i = 0; i < g_NumClassItems; i++)
+ {
+ if ((*g_ClassItemList)[i].hItem == hItem)
+ return &(*g_ClassItemList)[i];
+ }
+
+ return NULL;
+}
+
+
+//
+// Init GUI components
+//
+BOOL CreateGUI()
+{
+
+ if (InitGUI() == FALSE)
+ return FALSE;
+
+ // Register the window class for the main window.
+ if (CreateMainWindow() == FALSE)
+ return FALSE;
+
+ g_hwndTreeView = CreateTreeView(g_hwndMain);
+ if (g_hwndTreeView == NULL)
+ return FALSE;
+
+ return 0;
+}
+
+
+//
+// This is the main loop which the disassembler sits in when in GUI mode
+//
+void GUIMainLoop()
+{
+ MSG msg;
+ HACCEL hAccel = NULL;
+
+ _ASSERTE(g_hResources != NULL);
+ hAccel = WszLoadAccelerators(g_hResources,L"FileAccel");
+ // Accelerator tables are released when the app exits
+ while (WszGetMessage(&msg, (HWND) NULL, 0, 0))
+ {
+ // Dispatch message to appropriate window
+ if((g_hFindText == NULL)|| !WszIsDialogMessage(g_hFindText,&msg))
+ {
+ if(hAccel && WszTranslateAccelerator(g_hwndMain,hAccel,&msg));
+ else
+ {
+ TranslateMessage(&msg);
+ WszDispatchMessage(&msg);
+ }
+ }
+ }
+ GUICleanupClassItems();
+}
+// Dump one tree item to a text file (calls itself recursively)
+void DumpTreeItem(HTREEITEM hSelf, FILE* pFile, __inout __nullterminated WCHAR* szIndent)
+{
+ HTREEITEM hNext;
+ TVITEMEXW tvi;
+ static WCHAR szText[2048];
+ WCHAR* wzString = (WCHAR*)GlobalBuffer;
+ tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_TEXT;
+ tvi.hItem = hSelf;
+ tvi.pszText = szText;
+ tvi.cchTextMax = 2047;
+ if(WszSendMessage(g_hwndTreeView,TVM_GETITEMW,0,(LPARAM)(&tvi)))
+ {
+ WCHAR* szType = NULL;
+ if(hSelf == g_hRoot) szType = L"MOD";
+ else
+ {
+ switch(tvi.iImage)
+ {
+ case CLASS_IMAGE_INDEX: szType = L"CLS"; break;
+ case EVENT_IMAGE_INDEX: szType = L"EVT"; break;
+ case FIELD_IMAGE_INDEX: szType = L"FLD"; break;
+ case NAMESPACE_IMAGE_INDEX: szType = L"NSP"; break;
+ case METHOD_IMAGE_INDEX: szType = L"MET"; break;
+ case PROP_IMAGE_INDEX: szType = L"PTY"; break;
+ case STATIC_FIELD_IMAGE_INDEX: szType = L"STF"; break;
+ case STATIC_METHOD_IMAGE_INDEX: szType = L"STM"; break;
+ case CLASSENUM_IMAGE_INDEX: szType = L"ENU"; break;
+ case CLASSINT_IMAGE_INDEX: szType = L"INT"; break;
+ case CLASSVAL_IMAGE_INDEX: szType = L"VCL"; break;
+ }
+ }
+ if(szType) swprintf_s(wzString,4096,L"%s___[%s] %s",szIndent,szType,szText);
+ else swprintf_s(wzString,4096,L"%s %s",szIndent,szText);
+ }
+ else swprintf_s(wzString,4096,L"%sGetItemW failed",szIndent);
+ printLineW(pFile,wzString);
+ *wzString = 0;
+ if(hNext = TreeView_GetChild(g_hwndTreeView,hSelf))
+ {
+ wcscat_s(szIndent,MAX_FILENAME_LENGTH,L" |");
+
+ do {
+ DumpTreeItem(hNext,pFile,szIndent);
+ } while(hNext = TreeView_GetNextSibling(g_hwndTreeView,hNext));
+
+ szIndent[wcslen(szIndent)-4] = 0;
+ printLineW(pFile,szIndent);
+ }
+}
+
diff --git a/src/ildasm/gui.h b/src/ildasm/gui.h
new file mode 100644
index 0000000000..07233b5aee
--- /dev/null
+++ b/src/ildasm/gui.h
@@ -0,0 +1,156 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include "dynamicarray.h"
+
+#define BITMAP_WIDTH 15
+#define BITMAP_HEIGHT 15
+
+#define DISASSEMBLY_CLASS_NAME "disassembly"
+#define MAIN_WINDOW_CLASS "dasm"
+#define MAIN_WINDOW_CAPTION "IL DASM"
+
+#define DISASSEMBLY_CLASS_NAMEW L"disassembly"
+#define MAIN_WINDOW_CLASSW L"dasm"
+#define MAIN_WINDOW_CAPTIONW L"IL DASM\0"
+
+#define PHDC (pDIS->hDC)
+#define PRC (pDIS->rcItem)
+
+#define PADDING 28
+
+#define ID_TREEVIEW 1
+#define ID_LISTBOX 2
+
+typedef struct
+{
+ const char *pszNamespace;
+ HTREEITEM hRoot;
+} Namespace_t;
+
+
+//
+// Menu info
+//
+enum
+{
+ IDM_PROGRESS,
+ IDM_OPEN,
+ IDM_DUMP,
+ IDM_DUMP_TREE,
+ IDM_EXIT,
+ IDM_SORT_BY_NAME,
+ IDM_SHOW_PUB,
+ IDM_SHOW_PRIV,
+ IDM_SHOW_FAM,
+ IDM_SHOW_ASM,
+ IDM_SHOW_FAA,
+ IDM_SHOW_FOA,
+ IDM_SHOW_PSCOPE,
+ IDM_FULL_INFO,
+ IDM_BYTES,
+ IDM_TOKENS,
+ IDM_SOURCELINES,
+ IDM_EXPANDTRY,
+ IDM_QUOTEALLNAMES,
+ IDM_SHOW_HEADER,
+ IDM_SHOW_STAT,
+ IDM_SHOW_METAINFO,
+ IDM_MI_DEBUG,
+ IDM_MI_HEADER,
+ IDM_MI_HEX,
+ IDM_MI_CSV,
+ IDM_MI_UNREX,
+ IDM_MI_SCHEMA,
+ IDM_MI_RAW,
+ IDM_MI_HEAPS,
+ IDM_MI_VALIDATE,
+ IDM_HELP,
+ IDM_ABOUT,
+ IDM_FONT_TREE,
+ IDM_FONT_DASM,
+ IDM_FIND,
+ IDM_FINDNEXT,
+ IDM_TREEVIEWFCN,
+ IDM_CAVERBAL,
+ IDM_DUMPRTF
+};
+
+
+//
+// Bitmaps - keep in same order as in dasm.rc file
+//
+enum
+{
+ CLASS_IMAGE_INDEX,
+ EVENT_IMAGE_INDEX,
+ METHOD_IMAGE_INDEX,
+ NAMESPACE_IMAGE_INDEX,
+ FIELD_IMAGE_INDEX,
+ PROP_IMAGE_INDEX,
+ STATIC_METHOD_IMAGE_INDEX,
+ STATIC_FIELD_IMAGE_INDEX,
+ RED_ARROW_IMAGE_INDEX,
+ CLASSENUM_IMAGE_INDEX,
+ CLASSINT_IMAGE_INDEX,
+ CLASSVAL_IMAGE_INDEX,
+ CLASS_GEN_IMAGE_INDEX,
+ METHOD_GEN_IMAGE_INDEX,
+ STATIC_METHOD_GEN_IMAGE_INDEX,
+ CLASSENUM_GEN_IMAGE_INDEX,
+ CLASSINT_GEN_IMAGE_INDEX,
+ CLASSVAL_GEN_IMAGE_INDEX,
+ LAST_IMAGE_INDEX
+};
+
+#define TREEITEM_TYPE_MEMBER 1
+#define TREEITEM_TYPE_INFO 2
+
+// Member items and info items (under classes)
+typedef struct
+{
+ HTREEITEM hItem;
+ union
+ {
+ mdToken mbMember;
+ char * pszText; // if an info item (extends or implements some class)
+ };
+ BYTE Discriminator;
+} TreeItem_t;
+
+// Class items (under the root)
+typedef struct
+{
+ HTREEITEM hItem;
+ mdTypeDef cl;
+ TreeItem_t *pMembers; // List of subitems
+ DWORD SubItems; // Number of subitems
+ DWORD CurMember; // Used when building member list
+} ClassItem_t;
+
+typedef struct
+{
+ HWND hwndContainer;
+ HWND hwndChild;
+ HMENU hMenu;
+ mdToken tkClass;
+ mdToken tkMember;
+ WCHAR wzFind[120];
+ FINDREPLACEW strFR;
+} DisasmBox_t;
+
+
+
+// For accessing metadata
+extern IMDInternalImport* g_pImport;
+extern PELoader * g_pPELoader;
+extern IMetaDataImport2* g_pPubImport;
+
+//extern DynamicArray<mdToken> g_cl_list;
+extern mdToken * g_cl_list;
+//extern DynamicArray<mdToken> g_cl_enclosing;
+extern mdToken * g_cl_enclosing;
+extern mdTypeDef g_cl_module;
+extern DWORD g_NumClasses;
diff --git a/src/ildasm/html/clicking.htm b/src/ildasm/html/clicking.htm
new file mode 100644
index 0000000000..828193c988
--- /dev/null
+++ b/src/ildasm/html/clicking.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<HTML>
+<HEAD>
+<META HTTP-EQUIV="Content-Type" Content="text/html; charset=Windows-1252">
+<TITLE>Clicking on Tree View Items</TITLE>
+
+<STYLE>
+ BODY {background: white; color: black}
+ h3 {font: 8pt Arial bold}
+ P {font: 10pt Arial}
+ TD {font: 10pt Arial}
+ A {text-decoration: none; color: blue}
+</STYLE>
+
+</HEAD>
+
+<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
+
+<P style="margin-top: 0; margin-bottom: 0"><A NAME="clicking"><font size="4">
+</font></A><B><I><font size="4">CLICKING ON TREE VIEW ITEMS</font></I></B></P>
+<P style="margin-top: 0; margin-bottom: 0">&nbsp;</P>
+
+<font size="2">
+<P style="margin-top: 0; margin-bottom: 0">Double-clicking on various tree view items results in the following actions:
+<UL>
+ <LI><P style="margin-top: 0; margin-bottom: 0">On namespace or any type of class - expanding/collapsing respective subtree</LI>
+ <LI><p style="margin-top: 0; margin-bottom: 0">On manifest, field, method, event, property - showing disassembly of the item in a separate window</LI>
+ <LI><p style="margin-top: 0; margin-bottom: 0">On <B>.class</B> info item - showing partial disassembly of the class in a separate window</LI>
+ <LI><p style="margin-top: 0; margin-bottom: 0">On <B>extends</B> info item - selecting the parent class (if present) in tree view</LI>
+ <LI><p style="margin-top: 0; margin-bottom: 0">On <B>implements</B> info item - selecting the implemented interface (if present) in tree view</LI>
+</UL>
+</font>
+
+</BODY>
+</HTML>
diff --git a/src/ildasm/html/keyboard.htm b/src/ildasm/html/keyboard.htm
new file mode 100644
index 0000000000..6730adcc22
--- /dev/null
+++ b/src/ildasm/html/keyboard.htm
@@ -0,0 +1,166 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<HTML>
+<HEAD>
+<META HTTP-EQUIV="Content-Type" Content="text/html; charset=Windows-1252">
+<TITLE>Keyboard Commands</TITLE>
+
+<STYLE>
+ BODY {background: white; color: black}
+ h3 {font: 8pt Arial bold}
+ P {font: 10pt Arial}
+ TD {font: 10pt Arial}
+ A {text-decoration: none; color: blue}
+</STYLE>
+
+</HEAD>
+
+<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
+<font face="Arial">
+<H1 style="margin-top: 0; margin-bottom: 0"><A NAME="keyboard"><font size="4">
+</font></A><I><font size="4">KEYBOARD COMMANDS</font></I></H1>
+<p style="margin-top: 0; margin-bottom: 0">&nbsp;</p>
+
+<font size="2">
+
+<P style="margin-top: 0; margin-bottom: 0">Hot keys: </P>
+<blockquote>
+ <table border="1" width="90%" id="table1">
+ <tr>
+ <td width="123">
+
+<font size="2" face="Arial">
+
+ <B>Ctrl+O</B></font></td>
+ <td>
+
+<font size="2" face="Arial">
+
+ open a file</font></td>
+ </tr>
+ <tr>
+ <td width="123">
+
+<font size="2" face="Arial">
+
+ <B>Ctrl+D</B>
+</font>
+ </td>
+ <td>
+
+<font size="2" face="Arial">
+
+ disassemble the loaded file into IL source file</font></td>
+ </tr>
+ <tr>
+ <td width="123">
+
+<font size="2" face="Arial">
+
+ <B>Ctrl+T</B></font></td>
+ <td>
+
+<font size="2" face="Arial">
+
+ dump fully expanded tree view into a text file</font></td>
+ </tr>
+ <tr>
+ <td width="123">
+
+<font size="2" face="Arial">
+
+ <B>Ctrl+M</B></font></td>
+ <td>
+
+<font size="2" face="Arial">
+
+ show metadata info in a disassembly window (advanced mode only)</font></td>
+ </tr>
+ <tr>
+ <td width="123">
+
+<font size="2" face="Arial">
+
+ <B>Ctrl+X</B></font></td>
+ <td>
+
+<font size="2" face="Arial">
+
+ exit</font></td>
+ </tr>
+ <tr>
+ <td width="123">
+
+<font size="2" face="Arial">
+
+ <B>F1</B> or
+ <B>Alt+H</B></font></td>
+ <td>
+
+<font size="2" face="Arial">
+
+ Show this help window</font></td>
+ </tr>
+ </table>
+</blockquote>
+<P style="margin-top: 0; margin-bottom: 0">&nbsp;</P>
+
+<p style="margin-top: 0; margin-bottom: 0"></p>
+
+<P style="margin-top: 0; margin-bottom: 0">In tree view:</P>
+
+<blockquote>
+ <table border="1" width="90%" id="table2">
+ <tr>
+ <td width="123">
+
+<font size="2" face="Arial">
+
+ <b>Enter</b></font></td>
+ <td>
+
+<font size="2" face="Arial">
+
+ similar to double clicking (see above)</font></td>
+ </tr>
+ <tr>
+ <td width="123">
+
+<font size="2" face="Arial">
+
+ <b>Cursor right</b></font></td>
+ <td>
+
+<font size="2" face="Arial">
+
+ expand subtree</font></td>
+ </tr>
+ <tr>
+ <td width="123">
+
+<font size="2" face="Arial">
+
+ <b>Cursor left</b></font></td>
+ <td>
+
+<font size="2" face="Arial">
+
+ collapse subtree</font></td>
+ </tr>
+ <tr>
+ <td width="123">
+
+<font size="2" face="Arial">
+
+ <b>Cursor up/down</b></font></td>
+ <td>
+
+<font size="2" face="Arial">
+
+ select previous/next item</font></td>
+ </tr>
+ </table>
+</blockquote>
+</font>
+</font>
+</BODY>
+</HTML>
diff --git a/src/ildasm/html/menu_options.htm b/src/ildasm/html/menu_options.htm
new file mode 100644
index 0000000000..d96f59acfa
--- /dev/null
+++ b/src/ildasm/html/menu_options.htm
@@ -0,0 +1,324 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<HTML>
+<HEAD>
+<META HTTP-EQUIV="Content-Type" Content="text/html; charset=Windows-1252">
+<TITLE>Menu Options</TITLE>
+
+<STYLE>
+ BODY {background: white; color: black}
+ h3 {font: 8pt Arial bold}
+ P {font: 10pt Arial}
+ blockquote {text-indent: 0%}
+ TD {font: 10pt Arial}
+ A {text-decoration: none; color: blue}
+</STYLE>
+
+</HEAD>
+
+<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
+<font face="Arial">
+<P style="margin-top: 0; margin-bottom: 0"><A NAME="menu_options"></A><B><I><font size="4">MENU OPTIONS</font></I></B></P>
+
+<P style="margin-top: 0; margin-bottom: 0">&nbsp;</P>
+<P style="margin-top: 0; margin-bottom: 0"><B>File</B> (Alt+F)</P>
+<font size="2">
+<blockquote>
+ <table border="1" width="90%" id="table1">
+ <tr>
+ <td width="155" valign="top">
+<font size="2" face="Arial">
+ <B>Open</B> (Ctrl+O)</font></td>
+ <td>
+<font size="2" face="Arial">
+ select a PE file to open</font></td>
+ </tr>
+ <tr>
+ <td width="155" valign="top">
+<font size="2" face="Arial">
+ <B>Dump</B> (Ctrl+D)</font></td>
+ <td>
+<font size="2" face="Arial">
+ dump the current PE file to an IL source file</font></td>
+ </tr>
+ <tr>
+ <td width="155" valign="top">
+<font size="2" face="Arial">
+ <B>Dump TreeView</B> (Ctrl+T)</font></td>
+ <td>
+<font size="2" face="Arial">
+ dump the fully expanded tree view of current PE file to a text file</font></td>
+ </tr>
+ <tr>
+ <td width="155" valign="top">
+<font size="2" face="Arial">
+ <B>Exit</B> (Ctrl+X)</font></td>
+ <td>
+<font size="2" face="Arial">
+ close the current PE file and exit</font></td>
+ </tr>
+ </table>
+</blockquote>
+</font>
+<p style="margin-top: 0; margin-bottom: 0">
+</P>
+
+<P style="margin-top: 0; margin-bottom: 0">&nbsp;</P>
+<P style="margin-top: 0; margin-bottom: 0"><B>View</B> (Alt+V)</P>
+
+<font size="2">
+<blockquote>
+ <table border="1" width="90%" id="table2">
+ <tr>
+ <td width="155" valign="top">
+
+<font size="2" face="Arial">
+ <B>Set Fonts</B></font></td>
+ <td colspan="2" valign="top">
+
+<font size="2" face="Arial">
+ set the fonts for tree view and disassembly windows. Default fonts
+ are MS Sans Serif 8 for tree view and Courier 10 for Disassembly
+ windows</font></td>
+ </tr>
+ <tr>
+ <td width="155" valign="top">
+
+<font size="2" face="Arial">
+ <B>Sort by name</B></font></td>
+ <td colspan="2" valign="top">
+
+<font size="2" face="Arial">
+ (on/off) sort the items in tree view by name</font></td>
+ </tr>
+ <tr>
+ <td width="155" valign="top">
+
+<font size="2" face="Arial">
+ <B>Show Public</B></font></td>
+ <td colspan="2" valign="top">
+
+<font size="2" face="Arial">
+ (on/off) show or dump the items having public accessibility</font></td>
+ </tr>
+ <tr>
+ <td width="155" valign="top">
+
+<font size="2" face="Arial">
+ <B>Show Private</B></font></td>
+ <td colspan="2" valign="top">
+
+<font size="2" face="Arial">
+ (on/off) show or dump the items having private accessibility</font></td>
+ </tr>
+ <tr>
+ <td width="155" valign="top">
+
+<font size="2" face="Arial">
+ <B>Show Family</B></font></td>
+ <td colspan="2" valign="top">
+
+<font size="2" face="Arial">
+ (on/off) show or dump the items having family accessibility</font></td>
+ </tr>
+ <tr>
+ <td width="155" valign="top">
+
+<font size="2" face="Arial">
+ <B>Show Assembly</B></font></td>
+ <td colspan="2" valign="top">
+
+<font size="2" face="Arial">
+ (on/off) show or dump the items having assembly accessibility</font></td>
+ </tr>
+ <tr>
+ <td width="155" valign="top">
+
+<font size="2" face="Arial">
+ <B>Show FamANDAssem</B></font></td>
+ <td colspan="2" valign="top">
+
+<font size="2" face="Arial">
+ (on/off) show or dump the items having family-and-assembly
+ accessibility</font></td>
+ </tr>
+ <tr>
+ <td width="155" valign="top">
+
+<font size="2" face="Arial">
+ <B>Show FamORAssem</B></font></td>
+ <td colspan="2" valign="top">
+
+<font size="2" face="Arial">
+ (on/off) show or dump the items having family-or-assembly
+ accessibility</font></td>
+ </tr>
+ <tr>
+ <td width="155" valign="top">
+
+<font size="2" face="Arial">
+ <B>Show PrivateScope</B></font></td>
+ <td colspan="2" valign="top">
+
+<font size="2" face="Arial">
+ (on/off) show or dump the items having private scope accessibility</font></td>
+ </tr>
+ <tr>
+ <td width="155" valign="top">
+
+<font size="2" face="Arial">
+ <B>Show Member Types</B></font></td>
+ <td colspan="2" valign="top">
+
+<font size="2" face="Arial">
+ (on/off) show types of members ('method','field',etc.) in tree view nodes</font></td>
+ </tr>
+ <tr>
+ <td width="155" valign="top">
+
+<font size="2" face="Arial">
+ <B>Show bytes</B>
+</font>
+ </td>
+ <td colspan="2" valign="top">
+
+<font size="2" face="Arial">
+ (on/off) show the actual IL code in hexadecimal (as comments) when
+ disassembling the methods</font></td>
+ </tr>
+ <tr>
+ <td width="155" valign="top">
+
+<font size="2" face="Arial">
+ <B>Show token values</B></font></td>
+ <td colspan="2" valign="top">
+
+<font size="2" face="Arial">
+ (on/off) show token values in hexadecimal (as comments)</font></td>
+ </tr>
+ <tr>
+ <td width="155" valign="top">
+
+<font size="2" face="Arial">
+ <B>Show source lines</B></font></td>
+ <td colspan="2" valign="top">
+
+<font size="2" face="Arial">
+ (on/off) show the original source code (as comments, if the original
+ source is available)</font></td>
+ </tr>
+ <tr>
+ <td width="155" valign="top">
+
+<font size="2" face="Arial">
+ <B>Quote all names</B></font></td>
+ <td colspan="2" valign="top">
+
+<font size="2" face="Arial">
+ (on/off) include all names in single quotes (when off, only illegal
+ names are quoted)</font></td>
+ </tr>
+ <tr>
+ <td width="155" valign="top">
+
+<font size="2" face="Arial">
+ <B>Expand try/catch</B></font></td>
+ <td colspan="2" valign="top">
+
+<font size="2" face="Arial">
+ (on/off) present SEH clauses in expanded form when possible (<B>try { ... } catch ExceptionClass { ... }</B>)</font></td>
+ </tr>
+ <tr>
+ <td width="155" valign="top">
+
+<font size="2" face="Arial">
+ <B>COR Header</B></font></td>
+ <td colspan="2" valign="top">
+
+<font size="2" face="Arial">
+ show contents of COR header in a disassembly window"</font></td>
+ </tr>
+ <tr>
+ <td width="155" valign="top">
+
+<font size="2" face="Arial">
+ <B>Statistics</B> <br>
+ (advanced mode only)</font></td>
+ <td colspan="2" valign="top">
+
+<font size="2" face="Arial">
+ show PE file statistics in a disassembly window</font></td>
+ </tr>
+ <tr>
+ <td width="155" rowspan="6" valign="top">
+
+<font size="2" face="Arial">
+ <B>MetaInfo</B> <br>
+ (advanced mode only)</font></td>
+ <td width="16%" valign="top">
+
+<font size="2" face="Arial">
+ <B>Header</B>
+</font>
+ </td>
+ <td valign="top">
+
+<font size="2" face="Arial">
+ (on/off) show metadata info as header summary</font></td>
+ </tr>
+ <tr>
+ <td width="16%" valign="top">
+
+<font size="2" face="Arial">
+ <B>More HEX</B></font></td>
+ <td valign="top">
+
+<font size="2" face="Arial">
+ (on/off) show token and attribute values (in hexadecimal) in
+ metadata info</font></td>
+ </tr>
+ <tr>
+ <td width="16%" valign="top">
+
+<font size="2" face="Arial">
+ <B>CSV</B></font></td>
+ <td valign="top">
+
+<font size="2" face="Arial">
+ (on/off) show metadata info as comma-separated values</font></td>
+ </tr>
+ <tr>
+ <td width="16%" valign="top">
+
+<font size="2" face="Arial">
+ <B>Unresolved ext</B></font></td>
+ <td valign="top">
+
+<font size="2" face="Arial">
+ (on/off) add list of unresolved external references to metadata info</font></td>
+ </tr>
+ <tr>
+ <td width="16%" valign="top">
+
+<font size="2" face="Arial">
+ <B>Validate</B></font></td>
+ <td valign="top">
+
+<font size="2" face="Arial">
+ (on/off) show metadata validation results</font></td>
+ </tr>
+ <tr>
+ <td width="16%" valign="top">
+
+<font size="2" face="Arial">
+ <B>Show!</B> (Ctrl+M)</font></td>
+ <td valign="top">
+
+<font size="2" face="Arial">
+ show the metadata info in a disassembly window</font></td>
+ </tr>
+ </table>
+</blockquote>
+</font>
+</font>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/src/ildasm/html/tree_view_icons.htm b/src/ildasm/html/tree_view_icons.htm
new file mode 100644
index 0000000000..d39e7e811d
--- /dev/null
+++ b/src/ildasm/html/tree_view_icons.htm
@@ -0,0 +1,102 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<HTML>
+<HEAD>
+<META HTTP-EQUIV="Content-Type" Content="text/html; charset=Windows-1252">
+<TITLE>Tree View Icons</TITLE>
+
+<STYLE>
+ BODY {background: white; color: black}
+ h3 {font: 8pt Arial bold}
+ P {font: 10pt Arial}
+ TD {font: 10pt Arial}
+ A {text-decoration: none; color: blue}
+</STYLE>
+
+</HEAD>
+
+<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
+<font face="Arial">
+
+<H1 style="margin-top: 0; margin-bottom: 0"><A NAME="tree_view_icons">
+</A><I><font size="4">TREE VIEW ICONS</font></I></H1>
+<p style="margin-top: 0; margin-bottom: 0">&nbsp;</p>
+
+<table border="1" width="82%" id="table1" cellpadding="3" cellspacing="3" >
+<font size="2">
+ <tr>
+ <td width="148" valign="top"><b>Namespace</b></td>
+ <td align="center" valign="top">
+ <img border="0" src="tree_view_icons_files/namespace.gif" width="15" height="15"></td>
+ <td width="321" valign="top">(Blue shield)</td>
+ </tr>
+ <tr>
+ <td width="148" valign="top"><b>Class</b></td>
+ <td align="center" valign="top">
+ <img border="0" src="tree_view_icons_files/class.gif" width="15" height="15"></td>
+ <td width="321" valign="top">(Blue rectangle with three outputs)</td>
+ </tr>
+ <tr>
+ <td width="148" valign="top"><b>Interface</b></td>
+ <td align="center" valign="top">
+ <img border="0" src="tree_view_icons_files/interface.gif" width="15" height="15"></td>
+ <td width="321" valign="top">(Blue rectangle with three outputs marked 'I')</td>
+ </tr>
+ <tr>
+ <td width="148" valign="top"><b>Value Class</b></td>
+ <td align="center" valign="top">
+ <img border="0" src="tree_view_icons_files/value_class.gif" width="15" height="15"></td>
+ <td width="321" valign="top">(Brown rectangle with three outputs)</td>
+ </tr>
+ <tr>
+ <td width="148" valign="top"><b>Enum</b></td>
+ <td align="center" valign="top">
+ <img border="0" src="tree_view_icons_files/enum.gif" width="15" height="15"></td>
+ <td width="321" valign="top">(Brown rectangle with three outputs marked 'E')</td>
+ </tr>
+ <tr>
+ <td width="148" valign="top"><b>Method</b></td>
+ <td align="center" valign="top">
+ <img border="0" src="tree_view_icons_files/method.gif" width="15" height="15"></td>
+ <td width="321" valign="top">(Magenta rectangle)</td>
+ </tr>
+ <tr>
+ <td width="148" valign="top"><b>Static method</b></td>
+ <td align="center" valign="top">
+ <img border="0" src="tree_view_icons_files/static_method.gif" width="15" height="15"></td>
+ <td width="321" valign="top">(Magenta rectangle marked 'S')</td>
+ </tr>
+ <tr>
+ <td width="148" valign="top"><b>Field</b></td>
+ <td align="center" valign="top">
+ <img border="0" src="tree_view_icons_files/field.gif" width="15" height="15"></td>
+ <td width="321" valign="top">(Cyan diamond)</td>
+ </tr>
+ <tr>
+ <td width="148" valign="top"><b>Static field</b></td>
+ <td align="center" valign="top">
+ <img border="0" src="tree_view_icons_files/static_field.gif" width="15" height="15"></td>
+ <td width="321" valign="top">(Cyan diamond marked 'S')</td>
+ </tr>
+ <tr>
+ <td width="148" valign="top"><b>Event</b></td>
+ <td align="center" valign="top">
+ <img border="0" src="tree_view_icons_files/event.gif" width="15" height="15"></td>
+ <td width="321" valign="top">(Green point-down triangle)</td>
+ </tr>
+ <tr>
+ <td width="148" valign="top"><b>Property</b></td>
+ <td align="center" valign="top">
+ <img border="0" src="tree_view_icons_files/property.gif" width="15" height="15"></td>
+ <td width="321" valign="top">(Red point-up triangle)</td>
+ </tr>
+ <tr>
+ <td width="148" valign="top"><b>Manifest or a class info item</b></td>
+ <td align="center" valign="top">
+ <img border="0" src="tree_view_icons_files/manifest_classinfo.GIF" width="15" height="15"></td>
+ <td width="321" valign="top">(Red point-right triangle)</td>
+ </tr>
+</font></table>
+
+</font>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/src/ildasm/html/tree_view_icons_files/class.gif b/src/ildasm/html/tree_view_icons_files/class.gif
new file mode 100644
index 0000000000..53d1494a33
--- /dev/null
+++ b/src/ildasm/html/tree_view_icons_files/class.gif
Binary files differ
diff --git a/src/ildasm/html/tree_view_icons_files/enum.gif b/src/ildasm/html/tree_view_icons_files/enum.gif
new file mode 100644
index 0000000000..af7a94ee0b
--- /dev/null
+++ b/src/ildasm/html/tree_view_icons_files/enum.gif
Binary files differ
diff --git a/src/ildasm/html/tree_view_icons_files/event.gif b/src/ildasm/html/tree_view_icons_files/event.gif
new file mode 100644
index 0000000000..00de688ab8
--- /dev/null
+++ b/src/ildasm/html/tree_view_icons_files/event.gif
Binary files differ
diff --git a/src/ildasm/html/tree_view_icons_files/field.gif b/src/ildasm/html/tree_view_icons_files/field.gif
new file mode 100644
index 0000000000..0b6ed0a74b
--- /dev/null
+++ b/src/ildasm/html/tree_view_icons_files/field.gif
Binary files differ
diff --git a/src/ildasm/html/tree_view_icons_files/interface.gif b/src/ildasm/html/tree_view_icons_files/interface.gif
new file mode 100644
index 0000000000..21664cc715
--- /dev/null
+++ b/src/ildasm/html/tree_view_icons_files/interface.gif
Binary files differ
diff --git a/src/ildasm/html/tree_view_icons_files/manifest_classinfo.GIF b/src/ildasm/html/tree_view_icons_files/manifest_classinfo.GIF
new file mode 100644
index 0000000000..8811686023
--- /dev/null
+++ b/src/ildasm/html/tree_view_icons_files/manifest_classinfo.GIF
Binary files differ
diff --git a/src/ildasm/html/tree_view_icons_files/manifest_classinfo.jpg b/src/ildasm/html/tree_view_icons_files/manifest_classinfo.jpg
new file mode 100644
index 0000000000..8a752429eb
--- /dev/null
+++ b/src/ildasm/html/tree_view_icons_files/manifest_classinfo.jpg
Binary files differ
diff --git a/src/ildasm/html/tree_view_icons_files/manifest_classinfo.png b/src/ildasm/html/tree_view_icons_files/manifest_classinfo.png
new file mode 100644
index 0000000000..a68d41dd02
--- /dev/null
+++ b/src/ildasm/html/tree_view_icons_files/manifest_classinfo.png
Binary files differ
diff --git a/src/ildasm/html/tree_view_icons_files/method.gif b/src/ildasm/html/tree_view_icons_files/method.gif
new file mode 100644
index 0000000000..d96cfe4e0b
--- /dev/null
+++ b/src/ildasm/html/tree_view_icons_files/method.gif
Binary files differ
diff --git a/src/ildasm/html/tree_view_icons_files/namespace.gif b/src/ildasm/html/tree_view_icons_files/namespace.gif
new file mode 100644
index 0000000000..4001293dc0
--- /dev/null
+++ b/src/ildasm/html/tree_view_icons_files/namespace.gif
Binary files differ
diff --git a/src/ildasm/html/tree_view_icons_files/property.gif b/src/ildasm/html/tree_view_icons_files/property.gif
new file mode 100644
index 0000000000..08edbf854c
--- /dev/null
+++ b/src/ildasm/html/tree_view_icons_files/property.gif
Binary files differ
diff --git a/src/ildasm/html/tree_view_icons_files/static_field.gif b/src/ildasm/html/tree_view_icons_files/static_field.gif
new file mode 100644
index 0000000000..d8d6ff3ca3
--- /dev/null
+++ b/src/ildasm/html/tree_view_icons_files/static_field.gif
Binary files differ
diff --git a/src/ildasm/html/tree_view_icons_files/static_method.gif b/src/ildasm/html/tree_view_icons_files/static_method.gif
new file mode 100644
index 0000000000..5d982e1fc8
--- /dev/null
+++ b/src/ildasm/html/tree_view_icons_files/static_method.gif
Binary files differ
diff --git a/src/ildasm/html/tree_view_icons_files/value_class.gif b/src/ildasm/html/tree_view_icons_files/value_class.gif
new file mode 100644
index 0000000000..d4546f510f
--- /dev/null
+++ b/src/ildasm/html/tree_view_icons_files/value_class.gif
Binary files differ
diff --git a/src/ildasm/ildasm.chm b/src/ildasm/ildasm.chm
new file mode 100644
index 0000000000..166b1ca936
--- /dev/null
+++ b/src/ildasm/ildasm.chm
Binary files differ
diff --git a/src/ildasm/ildasm.hhp b/src/ildasm/ildasm.hhp
new file mode 100644
index 0000000000..71d47f5ff7
--- /dev/null
+++ b/src/ildasm/ildasm.hhp
@@ -0,0 +1,36 @@
+[OPTIONS]
+Binary Index=No
+Compatibility=1.1 or later
+Compiled file=ildasm.chm
+Contents file=dasmhlp.hhc
+Default Font=Arial,8,0
+Default Window=Main
+Default topic=html\menu_options.htm
+Display compile progress=No
+Full-text search=Yes
+Language=0x409 English (United States)
+Title=MSIL Disassembler Help
+
+[WINDOWS]
+Main="MSIL Disassembler Help","dasmhlp.hhc",,"html\menu_options.htm","html\menu_options.htm",,,,,0x42520,185,0x3006,[253,102,1070,702],,0x8,,,,,0
+
+
+[FILES]
+html\clicking.htm
+html\keyboard.htm
+html\menu_options.htm
+html\tree_view_icons.htm
+ildasm.hhp
+map.h
+
+[ALIAS]
+CLICKING=html\clicking.htm
+KEYBOARD=html\keyboard.htm
+MENU_OPTIONS=html\menu_options.htm
+TREE_VIEW_ICONS=html\tree_view_icons.htm
+
+[MAP]
+#include map.h
+
+[INFOTYPES]
+
diff --git a/src/ildasm/ildasmpch.cpp b/src/ildasm/ildasmpch.cpp
new file mode 100644
index 0000000000..5ca4dcfefb
--- /dev/null
+++ b/src/ildasm/ildasmpch.cpp
@@ -0,0 +1,8 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+//
+// This is just to build the PCH for ildasm
+#include "ildasmpch.h"
diff --git a/src/ildasm/ildasmpch.h b/src/ildasm/ildasmpch.h
new file mode 100644
index 0000000000..757e9111d3
--- /dev/null
+++ b/src/ildasm/ildasmpch.h
@@ -0,0 +1,26 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#if !defined(_ILDASMPCH_H)
+#define _ILDASMPCH_H
+
+#define OEMRESOURCE
+#define INITGUID
+
+#include <windows.h>
+#include <cor.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <winuser.h>
+#include <commctrl.h>
+#include <commdlg.h>
+#include <richedit.h>
+#include <shellapi.h>
+#include <htmlhelp.h>
+#include <conio.h>
+
+#endif
diff --git a/src/ildasm/map.h b/src/ildasm/map.h
new file mode 100644
index 0000000000..21fcc0da71
--- /dev/null
+++ b/src/ildasm/map.h
@@ -0,0 +1,9 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#define MENU_OPTIONS 1
+#define TREE_VIEW_ICONS 2
+#define CLICKING 3
+#define KEYBOARD 4
diff --git a/src/ildasm/method.bmp b/src/ildasm/method.bmp
new file mode 100644
index 0000000000..b76bb93ef7
--- /dev/null
+++ b/src/ildasm/method.bmp
Binary files differ
diff --git a/src/ildasm/methodg.bmp b/src/ildasm/methodg.bmp
new file mode 100644
index 0000000000..dfa4c68c10
--- /dev/null
+++ b/src/ildasm/methodg.bmp
Binary files differ
diff --git a/src/ildasm/namespace.bmp b/src/ildasm/namespace.bmp
new file mode 100644
index 0000000000..6ac839ee65
--- /dev/null
+++ b/src/ildasm/namespace.bmp
Binary files differ
diff --git a/src/ildasm/prop.bmp b/src/ildasm/prop.bmp
new file mode 100644
index 0000000000..857e69c3fe
--- /dev/null
+++ b/src/ildasm/prop.bmp
Binary files differ
diff --git a/src/ildasm/rcdll/ildasmrc.nativeproj b/src/ildasm/rcdll/ildasmrc.nativeproj
new file mode 100644
index 0000000000..11066deba8
--- /dev/null
+++ b/src/ildasm/rcdll/ildasmrc.nativeproj
@@ -0,0 +1,18 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="dogfood">
+ <!--Import the settings-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.props" />
+ <!--Leaf project Properties-->
+ <PropertyGroup>
+ <OutputName>ildasmrc</OutputName>
+ <TargetType>DYNLINK</TargetType>
+ <LinkSubsystem>windows</LinkSubsystem>
+ <RCAdditionalOptions>$(RCAdditionalOptions) -r</RCAdditionalOptions>
+ <LinkResourceOnlyDll>true</LinkResourceOnlyDll>
+ </PropertyGroup>
+ <!--Leaf Project Items-->
+ <ItemGroup>
+ <RCResourceFile Include="..\dasm.rc" />
+ </ItemGroup>
+ <!--Import the targets-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.targets" />
+</Project>
diff --git a/src/ildasm/redarrow.bmp b/src/ildasm/redarrow.bmp
new file mode 100644
index 0000000000..ce94dc8fb2
--- /dev/null
+++ b/src/ildasm/redarrow.bmp
Binary files differ
diff --git a/src/ildasm/resource.h b/src/ildasm/resource.h
new file mode 100644
index 0000000000..bf993b6dcf
--- /dev/null
+++ b/src/ildasm/resource.h
@@ -0,0 +1,325 @@
+// ==++==
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// ==--==
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by dasm.rc
+//
+
+#include <copyrightstring.h>
+
+#define IDS_FILE 1
+#define IDS_VIEW 2
+#define IDS_HELP 3
+#define IDS_OPEN 4
+#define IDS_DUMP 5
+#define IDS_DUMPTREE 6
+#define IDS_EXIT 7
+#define IDS_FONTS 8
+#define IDS_FONT_TREE 9
+#define IDS_FONT_DASM 10
+#define IDS_SORT_BY_NAME 11
+#define IDS_SHOW_PUB 12
+#define IDS_SHOW_PRIV 13
+#define IDS_SHOW_FAM 14
+#define IDS_SHOW_ASM 15
+#define IDS_SHOW_FAA 16
+#define IDS_SHOW_FOA 17
+#define IDS_SHOW_PSCOPE 18
+#define IDS_FULL_INFO 19
+#define IDS_BYTES 20
+#define IDS_TOKENS 21
+#define IDS_SOURCELINES 22
+#define IDS_QUOTEALLNAMES 23
+#define IDS_EXPANDTRY 24
+#define IDS_SHOW_HEADER 25
+#define IDS_SHOW_STAT 26
+#define IDS_METAINFO 27
+#define IDS_MI_HEADER 28
+#define IDS_MI_HEX 29
+#define IDS_MI_CSV 30
+#define IDS_MI_UNREX 31
+#define IDS_MI_DEBUG 32
+#define IDS_MI_SCHEMA 33
+#define IDS_MI_RAW 34
+#define IDS_MI_HEAPS 35
+#define IDS_MI_VALIDATE 36
+#define IDS_SHOW_METAINFO 37
+#define IDS_ABOUT 38
+#define IDS_ABOUT_COPYRIGHTINFO 39
+#define IDS_PRODUCTNAME 40
+#define IDS_MAINWINDOWCAPTION 41
+#define IDS_MAINWINDOWCAPTIONAPPEND 42
+#define IDS_NETHEADER 43
+#define IDS_STATISTICS 44
+#define IDS_METAINFOTEXT 45
+#define IDS_FIND 46
+#define IDS_FINDNEXT 47
+#define IDS_RTL 48
+#define IDS_TREEVIEWFCN 49
+#define IDS_CAVERBAL 50
+#define IDS_DUMPRTF 51
+
+#define IDI_ICON2 136
+#define IDD_DIALOG1 137
+#define IDD_ABOUT 149
+#define IDR_MAINMENU 149
+#define IDI_ICON1 150
+
+#define IDS_USAGE_TITLE 200
+#define IDS_USAGE_01 IDS_USAGE_TITLE + 1
+#define IDS_USAGE_02 IDS_USAGE_01 + 1
+#define IDS_USAGE_03 IDS_USAGE_02 + 1
+#define IDS_USAGE_04 IDS_USAGE_03 + 1
+#define IDS_USAGE_04A IDS_USAGE_04 + 1
+#define IDS_USAGE_04B IDS_USAGE_04A + 1
+#define IDS_USAGE_05 IDS_USAGE_04B + 1
+#ifdef OWNER_OPTION_ENABLED
+#define IDS_USAGE_06 IDS_USAGE_05 + 1
+#else
+#define IDS_USAGE_06 IDS_USAGE_05
+#endif
+#define IDS_USAGE_07 IDS_USAGE_06 + 1
+#define IDS_USAGE_08 IDS_USAGE_07 + 1
+#define IDS_USAGE_09 IDS_USAGE_08 + 1
+#define IDS_USAGE_10 IDS_USAGE_09 + 1
+#ifdef _DEBUG
+#define IDS_USAGE_10A IDS_USAGE_10 + 1
+#else
+#define IDS_USAGE_10A IDS_USAGE_10
+#endif
+#define IDS_USAGE_11 IDS_USAGE_10A + 1
+#define IDS_USAGE_12 IDS_USAGE_11 + 1
+#define IDS_USAGE_13 IDS_USAGE_12 + 1
+#define IDS_USAGE_14 IDS_USAGE_13 + 1
+#define IDS_USAGE_15 IDS_USAGE_14 + 1
+#define IDS_USAGE_15A IDS_USAGE_15 + 1
+#define IDS_USAGE_15B IDS_USAGE_15A + 1
+#define IDS_USAGE_16 IDS_USAGE_15B + 1
+#define IDS_USAGE_17 IDS_USAGE_16 + 1
+#define IDS_USAGE_18 IDS_USAGE_17 + 1
+#define IDS_USAGE_19 IDS_USAGE_18 + 1
+#define IDS_USAGE_20 IDS_USAGE_19 + 1
+#define IDS_USAGE_21 IDS_USAGE_20 + 1
+#define IDS_USAGE_21A IDS_USAGE_21 + 1
+#define IDS_USAGE_21B IDS_USAGE_21A + 1
+#define IDS_USAGE_21C IDS_USAGE_21B + 1
+#define IDS_USAGE_22 IDS_USAGE_21C + 1
+#define IDS_USAGE_23 IDS_USAGE_22 + 1
+#define IDS_USAGE_24 IDS_USAGE_23 + 1
+#define IDS_USAGE_25 IDS_USAGE_24 + 1
+#define IDS_USAGE_26 IDS_USAGE_25 + 1
+#define IDS_USAGE_27 IDS_USAGE_26 + 1
+#define IDS_USAGE_28 IDS_USAGE_27 + 1
+#define IDS_USAGE_29 IDS_USAGE_28 + 1
+#define IDS_USAGE_30 IDS_USAGE_29 + 1
+#define IDS_USAGE_31 IDS_USAGE_30 + 1
+#define IDS_USAGE_32 IDS_USAGE_31 + 1
+#define IDS_USAGE_33 IDS_USAGE_32 + 1
+#define IDS_USAGE_34 IDS_USAGE_33 + 1
+#define IDS_USAGE_35 IDS_USAGE_34 + 1
+#define IDS_USAGE_36 IDS_USAGE_35 + 1
+#define IDS_USAGE_37 IDS_USAGE_36 + 1
+#define IDS_USAGE_38 IDS_USAGE_37 + 1
+#define IDS_USAGE_39 IDS_USAGE_38 + 1
+#define IDS_USAGE_40 IDS_USAGE_39 + 1
+#define IDS_USAGE_41 IDS_USAGE_40 + 1
+#define IDS_USAGE_42 IDS_USAGE_41 + 1
+#define IDS_USAGE_43 IDS_USAGE_42 + 1
+
+#define IDB_CLASS 300
+#define IDB_EVENT 301
+#define IDB_METHOD 302
+#define IDB_NAMESPACE 303
+#define IDB_FIELD 304
+#define IDB_PROP 305
+#define IDB_STATICMETHOD 306
+#define IDB_STATICFIELD 307
+#define IDB_REDARROW 308
+#define IDB_CLASSENUM 309
+#define IDB_CLASSINT 310
+#define IDB_CLASSVAL 311
+
+#define IDB_CLASS_GEN 312
+#define IDB_METHOD_GEN 313
+#define IDB_STATICMETHOD_GEN 314
+#define IDB_CLASSENUM_GEN 315
+#define IDB_CLASSINT_GEN 316
+#define IDB_CLASSVAL_GEN 317
+
+#define IDS_E_INITLDR 401
+#define IDS_E_FILEOPEN 402
+#define IDS_E_NOCORHDR 403
+#define IDS_E_BADCORHDR 404
+#define IDS_E_OPENMD 405
+#define IDS_E_COPYRIGHT 406
+#define IDS_E_DASMABORT 407
+#define IDS_E_DASMOK 408
+#define IDS_E_PARTDASM 409
+#define IDS_E_INSTRDT 410
+#define IDS_E_NOCOMPR 411
+#define IDS_E_CLSENUM 412
+#define IDS_E_SELFNSTD 413
+#define IDS_E_NOENCLOS 414
+#define IDS_E_INVALIDTK 415
+#define IDS_E_UNEXPTYPE 416
+#define IDS_E_AUTOCA 417
+#define IDS_E_PARAMSEQNO 418
+#define IDS_E_METHBEG 419
+#define IDS_E_DASMERR 420
+#define IDS_E_DASMNATIVE 421
+#define IDS_E_METHODRT 422
+#define IDS_E_NORVA 423
+#define IDS_E_MEMBRENUM 424
+#define IDS_E_ODDMEMBER 425
+#define IDS_E_ENUMINIT 426
+#define IDS_E_NODATA 427
+#define IDS_E_VTFUTABLE 428
+#define IDS_E_BOGUSRVA 429
+#define IDS_E_EATJTABLE 430
+#define IDS_E_EATJSIZE 431
+#define IDS_E_RESFLAGS 432
+#define IDS_E_MIHENTRY 433
+#define IDS_E_CODEMGRTBL 434
+#define IDS_E_IMPORTDATA 435
+#define IDS_E_COMIMAGE 436
+#define IDS_E_MDDETAILS 437
+#define IDS_E_MISTART 438
+#define IDS_E_MIEND 439
+#define IDS_E_ONLYITEMS 440
+#define IDS_E_ROGUEPTR 441
+#define IDS_E_DECOMPRESS 442
+#define IDS_E_COMPRESSED 443
+#define IDS_E_CODESIZE 444
+#define IDS_E_BOGUSLVSIG 445
+#define IDS_E_INSTRDECOD 446
+#define IDS_E_INSTRTYPE 447
+#define IDS_E_ARGINDEX 448
+#define IDS_E_LVINDEX 449
+#define IDS_E_SECTHEADER 451
+#define IDS_E_BADTOKENTYPE 452
+#define IDS_E_MDAIMPORT 454
+#define IDS_E_MDAFROMMDI 455
+#define IDS_E_MDIIMPORT 456
+#define IDS_E_NOMANIFEST 457
+
+#define IDS_E_MULTIPLEINPUT 458
+#define IDS_E_INVALIDOPTION 459
+#define IDS_PROGRESSBOX 460
+#define IDS_DISASSEMBLING 461
+#define IDS_PB_FILE 462
+#define IDS_PB_FILE1 463
+#define IDS_PB_TOFILE 464
+#define IDS_PB_TOFILE1 465
+#define IDS_PB_CLASSESDONE 466
+#define IDS_PB_GLOBALSDONE 467
+#define IDS_PB_CANCEL 468
+#define IDS_PB_WRITINGDATA 469
+#define IDS_W_CREATEDW32RES 470
+#define IDS_E_CORRUPTW32RES 471
+#define IDS_E_CANTOPENW32RES 472
+#define IDS_E_CANTACCESSW32RES 473
+#define IDS_CANTVIEW_TX 474
+#define IDS_CANTVIEW_HD 475
+#define IDS_ONLYPEINGUI 476
+#define IDS_BADFILETYPE 477
+#define IDS_E_CANTOPENOUT 478
+#define IDS_E_CANTCREATEPROC 479
+#define IDS_TEXTTOOLARGEFORGUI 480
+#define IDS_FILTER_IN 481
+#define IDS_FILTER_OUT 482
+#define IDS_FILTER_OUT2 483
+#define IDS_CANNOTOPENFILE 484
+#define IDS_UNABLETOREGLIBS 485
+#define IDS_ERRORREOPENINGFILE 486
+#define IDS_ASSEMNAMETOOLONG 487
+#define IDS_ASMREFNAMETOOLONG 488
+#define IDS_ERRORCAPTION 489
+#define IDS_ILDASM_TITLE 490
+#define IDS_VERSION 491
+#define IDS_W_CREATEDMRES 492
+#define IDS_E_READINGMRES 493
+#define IDS_E_SUPPRESSED 494
+#define IDS_LEGALCOPYRIGHT 495
+#define IDS_E_INVALIDRECORD 496
+
+#define IDC_CHECK1 1000
+#define IDC_CHECK2 1001
+#define IDC_CHECK3 1002
+#define IDC_CHECK4 1003
+#define IDC_CHECK5 1004
+#define IDC_CHECK6 1005
+#define IDC_CHECK7 1006
+#define IDC_CHECK8 1007
+#define IDC_CHECK9 1008
+#define IDC_CHECK10 1009
+#define IDC_CHECK11 1010
+#define IDC_CHECK12 1011
+#define IDC_CHECK13 1012
+#define IDC_CHECK14 1013
+#define IDC_CHECK15 1014
+#define IDC_CHECK16 1015
+#define IDC_CHECK17 1016
+#define IDC_CHECK18 1017
+#define IDC_CHECK19 1018
+#define IDC_CHECK20 1019
+#define IDC_RADIO1 1020
+#define IDC_RADIO2 1021
+#define IDC_ABOUT_LINE1 1021
+#define ID_ABOUT_COPYRIGHTINFO 1021
+#define IDC_ABOUT_COPYRIGHTINFO 1021
+#define IDC_RADIO3 1022
+#define ID_ABOUT_OK 1022
+#define IDC_ABOUT_LINE2 1023
+#define IDC_ABOUT_PRODUCTNAME 1023
+#define IDC_ABOUT_LINE3 1024
+#define IDC_ABOUT_VERSION 1024
+#define IDC_ABOUT_LEGALCOPYRIGHT 1025
+#define ID_EXPORT 32771
+#define ID_HELP_ABOUT 32772
+#define ID_HELP_CONTENTS 32773
+#define ID_FILE_DUMP 32774
+#define ID_FILE_DUMP_TREEVIEW 32775
+#define ID_FILE_EXIT 32776
+#define ID_VIEW_SORTBYNAME 32778
+#define ID_VIEW_SHOWPUBLIC 32779
+#define ID_VIEW_SHOWPRIVATE 32780
+#define ID_VIEW_SHOWFAMILY 32781
+#define ID_VIEW_SHOWASSEMBLY 32782
+#define ID_VIEW_SHOWFAMANDASSEM 32783
+#define ID_VIEW_SHOWFAMORASSEM 32784
+#define ID_VIEW_SHOWPRIVATESCOPE 32785
+#define ID_VIEW_SHOWMEMBERTYPES 32786
+#define ID_VIEW_SHOWBYTES 32787
+#define ID_VIEW_SHOWTOKENVALUES 32788
+#define ID_VIEW_SHOWSOURCELINES 32789
+#define ID_VIEW_QUOTEALLNAMES 32790
+#define ID_VIEW_EXPANDTRYCATCH 32791
+#define ID_VIEW_NETRUNTIMEHEADER 32792
+#define ID_VIEW_STATISTICS 32793
+#define ID_VIEW_SETFONTS_TREEVIEW 32795
+#define ID_VIEW_SETFONTS_DISASSEMBLY 32796
+#define ID_VIEW_METAINFO_HEADER 32797
+#define ID_VIEW_METAINFO_MOREHEX 32798
+#define ID_VIEW_METAINFO_CSV 32799
+#define ID_VIEW_METAINFO_UNRESOLVEDEXT 32800
+#define ID_VIEW_METAINFO_DEBUG 32801
+#define ID_VIEW_METAINFO_SCHEMA 32802
+#define ID_VIEW_METAINFO_RAW 32803
+#define ID_VIEW_METAINFO_HEAPS 32804
+#define ID_VIEW_METAINFO_VALIDATE 32805
+#define ID_VIEW_METAINFO_SHOW 32806
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_3D_CONTROLS 1
+#define _APS_NEXT_RESOURCE_VALUE 151
+#define _APS_NEXT_COMMAND_VALUE 32774
+#define _APS_NEXT_CONTROL_VALUE 1026
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/ildasm/staticfield.bmp b/src/ildasm/staticfield.bmp
new file mode 100644
index 0000000000..70edc432c1
--- /dev/null
+++ b/src/ildasm/staticfield.bmp
Binary files differ
diff --git a/src/ildasm/staticmethod.bmp b/src/ildasm/staticmethod.bmp
new file mode 100644
index 0000000000..bc87d243ae
--- /dev/null
+++ b/src/ildasm/staticmethod.bmp
Binary files differ
diff --git a/src/ildasm/staticmethodg.bmp b/src/ildasm/staticmethodg.bmp
new file mode 100644
index 0000000000..fedc1c56da
--- /dev/null
+++ b/src/ildasm/staticmethodg.bmp
Binary files differ
diff --git a/src/ildasm/util.hpp b/src/ildasm/util.hpp
new file mode 100644
index 0000000000..fdcc8a8268
--- /dev/null
+++ b/src/ildasm/util.hpp
@@ -0,0 +1,23 @@
+// ==++==
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// ==--==
+//
+// util.hpp
+//
+// Miscellaneous useful functions
+//
+#ifndef _H_UTIL
+#define _H_UTIL
+
+#include <objbase.h>
+
+#if defined(_DEBUG)
+#include <crtdbg.h>
+#undef _ASSERTE // utilcode defines a custom _ASSERTE
+#endif
+
+#include "utilcode.h"
+
+#endif /* _H_UTIL */
diff --git a/src/ildasm/windasm.cpp b/src/ildasm/windasm.cpp
new file mode 100644
index 0000000000..43732f939d
--- /dev/null
+++ b/src/ildasm/windasm.cpp
@@ -0,0 +1,698 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+/************************************************************************************************
+ * *
+ * File: winmain.cpp *
+ * *
+ * Purpose: Main program for graphic COM+ 2.0 disassembler ILDASM.exe *
+ * *
+ ************************************************************************************************/
+#include "ildasmpch.h"
+
+#include "dynamicarray.h"
+
+#define DO_DASM_GUI
+#include "dasmgui.h"
+#include "dasmenum.hpp"
+#include "dis.h"
+#include <ndpversion.h>
+#include "resource.h"
+
+#include "new.hpp"
+
+#define MODE_DUMP_ALL 0
+#define MODE_DUMP_CLASS 1
+#define MODE_DUMP_CLASS_METHOD 2
+#define MODE_DUMP_CLASS_METHOD_SIG 3
+#define MODE_GUI 4
+
+// All externs are defined in DASM.CPP
+extern BOOL g_fDumpIL;
+extern BOOL g_fDumpHeader;
+extern BOOL g_fDumpAsmCode;
+extern BOOL g_fDumpTokens;
+extern BOOL g_fDumpStats;
+extern BOOL g_fDumpClassList;
+extern BOOL g_fDumpTypeList;
+extern BOOL g_fDumpSummary;
+extern BOOL g_fDecompile; // still in progress
+extern BOOL g_fShowRefs;
+
+extern BOOL g_fDumpToPerfWriter;
+
+extern BOOL g_fShowBytes;
+extern BOOL g_fShowSource;
+extern BOOL g_fInsertSourceLines;
+extern BOOL g_fTryInCode;
+extern BOOL g_fQuoteAllNames;
+extern BOOL g_fShowProgressBar;
+extern HINSTANCE g_hResources;
+extern BOOL g_fTDC;
+extern BOOL g_fShowCA;
+extern BOOL g_fCAVerbal;
+
+extern char g_pszClassToDump[];
+extern char g_pszMethodToDump[];
+extern char g_pszSigToDump[];
+
+extern char g_szAsmCodeIndent[];
+
+extern DWORD g_Mode;
+
+extern char g_szInputFile[]; // in UTF-8
+extern WCHAR g_wszFullInputFile[]; // in UTF-16
+extern char g_szOutputFile[]; // in UTF-8
+extern char* g_pszObjFileName;
+extern FILE* g_pFile;
+
+extern BOOL g_fLimitedVisibility;
+#if defined(_DEBUG) && defined(FEATURE_PREJIT)
+extern BOOL g_fNGenNativeMetadata;
+#endif
+extern BOOL g_fHidePub;
+extern BOOL g_fHidePriv;
+extern BOOL g_fHideFam;
+extern BOOL g_fHideAsm;
+extern BOOL g_fHideFAA;
+extern BOOL g_fHideFOA;
+extern BOOL g_fHidePrivScope;
+extern BOOL g_fProject;
+
+extern unsigned g_uCodePage;
+extern unsigned g_uConsoleCP;
+extern BOOL g_fForwardDecl;
+extern BOOL g_fUseProperName;
+
+#include "../tools/metainfo/mdinfo.h"
+extern BOOL g_fDumpMetaInfo;
+extern ULONG g_ulMetaInfoFilter;
+HINSTANCE g_hInstance;
+HANDLE hConsoleOut=NULL;
+HANDLE hConsoleErr=NULL;
+// These are implemented in DASM.CPP:
+BOOL Init();
+void Uninit();
+void Cleanup();
+void DumpMetaInfo(__in __nullterminated const WCHAR* pszFileName, __in __nullterminated const char* pszObjFileName, void* GUICookie);
+FILE* OpenOutput(__in __nullterminated const char* szFileName);
+
+// Do we only view an IL-dasm window in GUI mode?
+// TRUE when we're in GUI mode and we specified a particular method from the cmd line
+BOOL IsGuiILOnly()
+{
+ return (g_Mode & MODE_GUI) && (g_pszMethodToDump[0] != 0);
+}
+
+void PrintLogo()
+{
+ printf("Microsoft (R) .NET Framework IL Disassembler. Version " VER_FILEVERSION_STR);
+ printf("\n%S\n\n", RstrW(IDS_LEGALCOPYRIGHT_LOGO));
+}
+void SyntaxCon()
+{
+ DWORD l;
+
+ for(l=IDS_USAGE_01; l<= IDS_USAGE_23; l++) printf(RstrANSI(l));
+ if(g_fTDC)
+ {
+ for(l=IDS_USAGE_24; l<= IDS_USAGE_32; l++) printf(RstrANSI(l));
+ for(l=IDS_USAGE_34; l<= IDS_USAGE_36; l++) printf(RstrANSI(l));
+ for(l=IDS_USAGE_37; l<= IDS_USAGE_39; l++) printf(RstrANSI(l));
+ }
+ else printf(RstrANSI(IDS_USAGE_40));
+ for(l=IDS_USAGE_41; l<= IDS_USAGE_42; l++) printf(RstrANSI(l));
+
+}
+
+char* CheckForDQuotes(__inout __nullterminated char* sz)
+{
+ char* ret = sz;
+ if(*sz == '"')
+ {
+ ret++;
+ sz[strlen(sz)-1] = 0;
+ }
+ return ret;
+}
+
+char* EqualOrColon(__in __nullterminated char* szArg)
+{
+ char* pchE = strchr(szArg,'=');
+ char* pchC = strchr(szArg,':');
+ char* ret;
+ if(pchE == NULL) ret = pchC;
+ else if(pchC == NULL) ret = pchE;
+ else ret = (pchE < pchC)? pchE : pchC;
+ return ret;
+}
+
+void GetInputFileFullPath()
+{
+ // We need the input file's full path to make uses of it later, despite changing CurrentDirectory
+
+ // First, convert back up to UTF16
+ DWORD len = (DWORD) strlen(g_szInputFile) + 16;
+ WCHAR* wzArg = new WCHAR[len];
+ memset(wzArg, 0, len * sizeof(WCHAR));
+ WszMultiByteToWideChar(g_uConsoleCP, 0, g_szInputFile, -1, wzArg, len);
+
+ // Get the full path
+ len = GetFullPathName(wzArg, MAX_PATH, g_wszFullInputFile, NULL);
+ VDELETE(wzArg);
+}
+
+int ProcessOneArg(__in __nullterminated char* szArg, __out char** ppszObjFileName)
+{
+ char szOpt[128];
+ if(strlen(szArg) == 0) return 0;
+ if ((strcmp(szArg, "/?") == 0) || (strcmp(szArg, "-?") == 0)) return 1;
+
+ if((szArg[0] == '/') || (szArg[0] == '-'))
+ {
+ strncpy_s(szOpt,128, &szArg[1],10);
+ szOpt[3] = 0;
+ if (_stricmp(szOpt, "dec") == 0)
+ {
+ g_fDecompile = TRUE;
+ }
+ else if (_stricmp(szOpt, "hea") == 0)
+ {
+ g_fDumpHeader = TRUE;
+ }
+ else if (_stricmp(szOpt, "adv") == 0)
+ {
+ g_fTDC = TRUE;
+ }
+ else if (_stricmp(szOpt, "tok") == 0)
+ {
+ g_fDumpTokens = TRUE;
+ }
+ else if (_stricmp(szOpt, "noi") == 0)
+ {
+ g_fDumpAsmCode = FALSE;
+ }
+ else if (_stricmp(szOpt, "noc") == 0)
+ {
+ g_fShowCA = FALSE;
+ }
+ else if (_stricmp(szOpt, "cav") == 0)
+ {
+ g_fCAVerbal = TRUE;
+ }
+ else if (_stricmp(szOpt, "not") == 0)
+ {
+ g_fTryInCode = FALSE;
+ }
+ else if (_stricmp(szOpt, "raw") == 0)
+ {
+ g_fTryInCode = FALSE;
+ }
+ else if (_stricmp(szOpt, "byt") == 0)
+ {
+ g_fShowBytes = TRUE;
+ }
+ else if (_stricmp(szOpt, "sou") == 0)
+ {
+ g_fShowSource = TRUE;
+ }
+ else if (_stricmp(szOpt, "lin") == 0)
+ {
+ g_fInsertSourceLines = TRUE;
+ }
+ else if ((_stricmp(szOpt, "sta") == 0)&&g_fTDC)
+ {
+ g_fDumpStats = g_fTDC;
+ }
+ else if ((_stricmp(szOpt, "cla") == 0)&&g_fTDC)
+ {
+ g_fDumpClassList = g_fTDC;
+ }
+ else if (_stricmp(szOpt, "typ") == 0)
+ {
+ g_fDumpTypeList = TRUE;
+ }
+ else if (_stricmp(szOpt, "sum") == 0)
+ {
+ g_fDumpSummary = TRUE;
+ }
+ else if (_stricmp(szOpt, "per") == 0)
+ {
+ g_fDumpToPerfWriter = TRUE;
+ }
+ else if (_stricmp(szOpt, "for") == 0)
+ {
+ g_fForwardDecl = TRUE;
+ }
+ else if (_stricmp(szOpt, "ref") == 0)
+ {
+ g_fShowRefs = TRUE;
+ }
+ else if (_stricmp(szOpt, "pub") == 0)
+ {
+ g_fLimitedVisibility = TRUE;
+ g_fHidePub = FALSE;
+ }
+#if defined(_DEBUG) && defined(FEATURE_PREJIT)
+ else if (_stricmp(szOpt, "nat") == 0)
+ {
+ g_fNGenNativeMetadata = TRUE;
+ }
+#endif
+ else if (_stricmp(szOpt, "pre") == 0)
+ {
+ //g_fPrettyPrint = TRUE;
+ }
+ else if (_stricmp(szOpt, "pro") == 0)
+ {
+ g_fProject = TRUE;
+ }
+ else if (_stricmp(szOpt, "vis") == 0)
+ {
+ char *pc = EqualOrColon(szArg);
+ char *pStr;
+ if(pc == NULL) return -1;
+ do {
+ pStr = pc+1;
+ pStr = CheckForDQuotes(pStr);
+ if((pc = strchr(pStr,'+'))) *pc=0;
+ if (!_stricmp(pStr,"pub")) g_fHidePub = FALSE;
+ else if(!_stricmp(pStr,"pri")) g_fHidePriv = FALSE;
+ else if(!_stricmp(pStr,"fam")) g_fHideFam = FALSE;
+ else if(!_stricmp(pStr,"asm")) g_fHideAsm = FALSE;
+ else if(!_stricmp(pStr,"faa")) g_fHideFAA = FALSE;
+ else if(!_stricmp(pStr,"foa")) g_fHideFOA = FALSE;
+ else if(!_stricmp(pStr,"psc")) g_fHidePrivScope = FALSE;
+ } while(pc);
+ g_fLimitedVisibility = g_fHidePub ||
+ g_fHidePriv ||
+ g_fHideFam ||
+ g_fHideAsm ||
+ g_fHideFAA ||
+ g_fHideFOA ||
+ g_fHidePrivScope;
+ }
+ else if (_stricmp(szOpt, "nob") == 0)
+ {
+ g_fShowProgressBar = FALSE;
+ }
+ else if (_stricmp(szOpt, "quo") == 0)
+ {
+ g_fQuoteAllNames = TRUE;
+ }
+ else if (_stricmp(szOpt, "utf") == 0)
+ {
+ g_uCodePage = CP_UTF8;
+ }
+ else if (_stricmp(szOpt, "uni") == 0)
+ {
+ g_uCodePage = 0xFFFFFFFF;
+ }
+ else if (_stricmp(szOpt, "rtf") == 0)
+ {
+ g_fDumpRTF = TRUE;
+ g_fDumpHTML = FALSE;
+ }
+ else if (_stricmp(szOpt, "htm") == 0)
+ {
+ g_fDumpRTF = FALSE;
+ g_fDumpHTML = TRUE;
+ }
+ else if (_stricmp(szOpt, "all") == 0)
+ {
+ g_fDumpStats = g_fTDC;
+ g_fDumpHeader = TRUE;
+ g_fShowBytes = TRUE;
+ g_fDumpClassList = g_fTDC;
+ g_fDumpTokens = TRUE;
+ }
+ else if (_stricmp(szOpt, "ite") == 0)
+ {
+ char *pStr = EqualOrColon(szArg);
+ char *p, *q;
+ if(pStr == NULL) return -1;
+ pStr++;
+ pStr = CheckForDQuotes(pStr);
+ // treat it as meaning "dump only class X" or "class X method Y"
+ p = strchr(pStr, ':');
+
+ if (p == NULL)
+ {
+ // dump one class
+ g_Mode = MODE_DUMP_CLASS;
+ strcpy_s(g_pszClassToDump, MAX_CLASSNAME_LENGTH, pStr);
+ }
+ else
+ {
+ *p++ = '\0';
+ if (*p != ':') return -1;
+
+ strcpy_s(g_pszClassToDump, MAX_CLASSNAME_LENGTH, pStr);
+
+ p++;
+
+ q = strchr(p, '(');
+ if (q == NULL)
+ {
+ // dump class::method
+ g_Mode = MODE_DUMP_CLASS_METHOD;
+ strcpy_s(g_pszMethodToDump, MAX_MEMBER_LENGTH, p);
+ }
+ else
+ {
+ // dump class::method(sig)
+ g_Mode = MODE_DUMP_CLASS_METHOD_SIG;
+ *q = '\0';
+ strcpy_s(g_pszMethodToDump, MAX_MEMBER_LENGTH, p);
+ // get rid of external parentheses:
+ q++;
+ strcpy_s(g_pszSigToDump, MAX_SIGNATURE_LENGTH, q);
+ }
+ }
+ }
+ else if ((_stricmp(szOpt, "met") == 0)&&g_fTDC)
+ {
+ if(g_fTDC)
+ {
+ char *pStr = EqualOrColon(szArg);
+ g_fDumpMetaInfo = TRUE;
+ if(pStr)
+ {
+ char szOptn[64];
+ strncpy_s(szOptn, 64, pStr+1,10);
+ szOptn[3] = 0; // recognize metainfo specifier by first 3 chars
+ if (_stricmp(szOptn, "hex") == 0) g_ulMetaInfoFilter |= MDInfo::dumpMoreHex;
+ else if(_stricmp(szOptn, "csv") == 0) g_ulMetaInfoFilter |= MDInfo::dumpCSV;
+ else if(_stricmp(szOptn, "mdh") == 0) g_ulMetaInfoFilter |= MDInfo::dumpHeader;
+ else if(_stricmp(szOptn, "raw") == 0) g_ulMetaInfoFilter |= MDInfo::dumpRaw;
+ else if(_stricmp(szOptn, "hea") == 0) g_ulMetaInfoFilter |= MDInfo::dumpRawHeaps;
+ else if(_stricmp(szOptn, "sch") == 0) g_ulMetaInfoFilter |= MDInfo::dumpSchema;
+ else if(_stricmp(szOptn, "unr") == 0) g_ulMetaInfoFilter |= MDInfo::dumpUnsat;
+ else if(_stricmp(szOptn, "val") == 0) g_ulMetaInfoFilter |= MDInfo::dumpValidate;
+ else if(_stricmp(szOptn, "sta") == 0) g_ulMetaInfoFilter |= MDInfo::dumpStats;
+ else return -1;
+ }
+ }
+ }
+ else if (_stricmp(szOpt, "obj") == 0)
+ {
+ char *pStr = EqualOrColon(szArg);
+ if(pStr == NULL) return -1;
+ pStr++;
+ pStr = CheckForDQuotes(pStr);
+ *ppszObjFileName = new char[strlen(pStr)+1];
+ strcpy_s(*ppszObjFileName,strlen(pStr)+1,pStr);
+ }
+ else if (_stricmp(szOpt, "out") == 0)
+ {
+ char *pStr = EqualOrColon(szArg);
+ if(pStr == NULL) return -1;
+ pStr++;
+ pStr = CheckForDQuotes(pStr);
+ if(*pStr == 0) return -1;
+ if(_stricmp(pStr,"con"))
+ {
+ strncpy_s(g_szOutputFile, MAX_FILENAME_LENGTH, pStr,MAX_FILENAME_LENGTH-1);
+ g_szOutputFile[MAX_FILENAME_LENGTH-1] = 0;
+ }
+ else
+ g_fShowProgressBar = FALSE;
+
+ g_Mode &= ~MODE_GUI;
+ }
+ else if (_stricmp(szOpt, "tex") == 0)
+ {
+ g_Mode &= ~MODE_GUI;
+ g_fShowProgressBar = FALSE;
+ }
+ else
+ {
+ PrintLogo();
+ printf(RstrANSI(IDS_E_INVALIDOPTION),szArg); //"INVALID COMMAND LINE OPTION: %s\n\n",szArg);
+ return -1;
+ }
+ }
+ else
+ {
+ if(g_szInputFile[0])
+ {
+ PrintLogo();
+ printf(RstrANSI(IDS_E_MULTIPLEINPUT)); //"MULTIPLE INPUT FILES SPECIFIED\n\n");
+ return -1; // check if it was already specified
+ }
+ szArg = CheckForDQuotes(szArg);
+ strncpy_s(g_szInputFile, MAX_FILENAME_LENGTH,szArg,MAX_FILENAME_LENGTH-1);
+ g_szInputFile[MAX_FILENAME_LENGTH-1] = 0;
+ GetInputFileFullPath();
+ }
+ return 0;
+}
+
+char* UTF8toANSI(__in __nullterminated char* szUTF)
+{
+ ULONG32 L = (ULONG32) strlen(szUTF)+16;
+ WCHAR* wzUnicode = new WCHAR[L];
+ memset(wzUnicode,0,L*sizeof(WCHAR));
+ WszMultiByteToWideChar(CP_UTF8,0,szUTF,-1,wzUnicode,L);
+ L <<= 2;
+ char* szANSI = new char[L];
+ memset(szANSI,0,L);
+ WszWideCharToMultiByte(g_uConsoleCP,0,wzUnicode,-1,szANSI,L,NULL,NULL);
+ VDELETE(wzUnicode);
+ return szANSI;
+}
+char* ANSItoUTF8(__in __nullterminated char* szANSI)
+{
+ ULONG32 L = (ULONG32) strlen(szANSI)+16;
+ WCHAR* wzUnicode = new WCHAR[L];
+ memset(wzUnicode,0,L*sizeof(WCHAR));
+ WszMultiByteToWideChar(g_uConsoleCP,0,szANSI,-1,wzUnicode,L);
+ L *= 3;
+ char* szUTF = new char[L];
+ memset(szUTF,0,L);
+ WszWideCharToMultiByte(CP_UTF8,0,wzUnicode,-1,szUTF,L,NULL,NULL);
+ VDELETE(wzUnicode);
+ return szUTF;
+}
+
+int ParseCmdLineW(__in __nullterminated WCHAR* wzCmdLine, __out char** ppszObjFileName)
+{
+ int argc,ret=0;
+ LPWSTR* argv= CommandLineToArgvW(wzCmdLine,&argc);
+ char* szArg = new char[2048];
+ for(int i=1; i < argc; i++)
+ {
+ memset(szArg,0,2048);
+ WszWideCharToMultiByte(CP_UTF8,0,argv[i],-1,szArg,2048,NULL,NULL);
+ if(ret = ProcessOneArg(szArg,ppszObjFileName)) break;
+ }
+ VDELETE(szArg);
+ return ret;
+}
+
+int ParseCmdLineA(__in __nullterminated char* szCmdLine, __out char** ppszObjFileName)
+{
+ if((szCmdLine == NULL)||(*szCmdLine == 0)) return 0;
+
+ // ANSI to UTF-8
+ char* szCmdLineUTF = ANSItoUTF8(szCmdLine);
+
+ // Split into argv[]
+ int argc=0, ret = 0;
+ DynamicArray<char*> argv;
+ char* pch;
+ char* pchend;
+ bool bUnquoted = true;
+
+ pch = szCmdLineUTF;
+ pchend = pch+strlen(szCmdLineUTF);
+ while(pch)
+ {
+ for(; *pch == ' '; pch++); // skip the blanks
+ argv[argc++] = pch;
+ for(; pch < pchend; pch++)
+ {
+ if(*pch == '"') bUnquoted = !bUnquoted;
+ else if((*pch == ' ')&&bUnquoted) break;
+ }
+
+ if(pch < pchend) *pch++ = 0;
+ else break;
+ }
+
+ for(int i=1; i < argc; i++)
+ {
+ if(ret = ProcessOneArg(argv[i],ppszObjFileName)) break;
+ }
+ VDELETE(szCmdLineUTF);
+ return ret;
+}
+
+int APIENTRY WinMain(HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ __in LPSTR lpCmdLine,
+ int nCmdShow)
+{
+ // ildasm does not need to be SO-robust.
+ SO_NOT_MAINLINE_FUNCTION;
+
+ // SWI has requested that the exact form of the function call below be used. For details see http://swi/SWI%20Docs/Detecting%20Heap%20Corruption.doc
+ (void)HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
+
+#ifdef _DEBUG
+ DisableThrowCheck();
+#endif
+
+ int iCommandLineParsed = 0;
+ WCHAR* wzCommandLine = NULL;
+ char* szCommandLine = NULL;
+
+ g_fUseProperName = TRUE;
+
+ g_hInstance = hInstance;
+ g_Mode = MODE_GUI;
+ g_pszClassToDump[0]=0;
+ g_pszMethodToDump[0]=0;
+ g_pszSigToDump[0]=0;
+ memset(g_szInputFile,0,MAX_FILENAME_LENGTH);
+ memset(g_szOutputFile,0,MAX_FILENAME_LENGTH);
+#if defined(_DEBUG)
+ g_fTDC = TRUE;
+#endif
+
+#undef GetCommandLineW
+#undef CreateProcessW
+ g_pszObjFileName = NULL;
+
+ g_szAsmCodeIndent[0] = 0;
+ hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
+ hConsoleErr = GetStdHandle(STD_ERROR_HANDLE);
+
+ // Dev11 #5320 - pull the localized resource loader up so if ParseCmdLineW need resources, they're already loaded
+ g_hResources = LoadLocalizedResourceDLLForSDK(L"ildasmrc.dll");
+
+ iCommandLineParsed = ParseCmdLineW((wzCommandLine = GetCommandLineW()),&g_pszObjFileName);
+
+ if(!g_fLimitedVisibility)
+ {
+ g_fHidePub = FALSE;
+ g_fHidePriv = FALSE;
+ g_fHideFam = FALSE;
+ g_fHideAsm = FALSE;
+ g_fHideFAA = FALSE;
+ g_fHideFOA = FALSE;
+ g_fHidePrivScope = FALSE;
+ }
+ if(hConsoleOut != INVALID_HANDLE_VALUE) //First pass: console
+ {
+ g_uConsoleCP = GetConsoleOutputCP();
+
+ if(iCommandLineParsed)
+ {
+ if(iCommandLineParsed > 0) PrintLogo();
+ SyntaxCon();
+ exit((iCommandLineParsed == 1) ? 0 : 1);
+ }
+ if(!(g_Mode & MODE_GUI))
+ {
+ DWORD exitCode = 1;
+ if(g_szInputFile[0] == 0)
+ {
+ SyntaxCon();
+ exit(1);
+ }
+ g_pFile = NULL;
+ if(g_szOutputFile[0])
+ {
+ g_pFile = OpenOutput(g_szOutputFile);
+ if(g_pFile == NULL)
+ {
+ char sz[4096];
+ sprintf_s(sz,4096,RstrUTF(IDS_E_CANTOPENOUT)/*"Unable to open '%s' for output."*/, g_szOutputFile);
+ g_uCodePage = CP_ACP;
+ printError(NULL,sz);
+ exit(1);
+ }
+ }
+ else // console output -- force the code page to ANSI
+ {
+ g_uCodePage = g_uConsoleCP;
+ g_fDumpRTF = FALSE;
+ g_fDumpHTML = FALSE;
+ }
+ if (Init() == TRUE)
+ {
+ exitCode = DumpFile() ? 0 : 1;
+ Cleanup();
+ }
+ Uninit();
+ exit(exitCode);
+ }
+ else // if GUI ordered, restart as WinApp
+ {
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si;
+ memset(&pi, 0, sizeof(PROCESS_INFORMATION) );
+ memset(&si, 0, sizeof(STARTUPINFO) );
+ si.cb = sizeof(STARTUPINFO);
+ si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
+ si.wShowWindow = SW_SHOW;
+ si.hStdOutput = INVALID_HANDLE_VALUE;
+ si.hStdInput = INVALID_HANDLE_VALUE;
+ si.hStdError = INVALID_HANDLE_VALUE;
+ // Create the child process.
+ if(CreateProcessW(NULL,
+ wzCommandLine, // command line
+ NULL, // process security attributes
+ NULL, // primary thread security attributes
+ TRUE, // handles are inherited
+ DETACHED_PROCESS, // creation flags
+ NULL, // use parent's environment
+ NULL, // use parent's current directory
+ (LPSTARTUPINFOW)&si, // STARTUPINFO pointer
+ &pi)==0) // receives PROCESS_INFORMATION
+ {
+ printf(RstrANSI(IDS_E_CANTCREATEPROC));//"Failed to CreateProcess\n\n");
+ exit(1);
+ }
+ exit(0);
+ }
+ }
+ else //Second pass: WinApp
+ {
+ g_uCodePage = CP_UTF8;
+ g_Mode = MODE_GUI;
+ g_fDumpHTML = FALSE;
+
+ if(g_szInputFile[0])
+ {
+ char* pch = strrchr(g_szInputFile,'.');
+ if(pch && (!_strcmpi(pch+1,"lib") || !_strcmpi(pch+1,"obj")))
+ {
+ WszMessageBox(NULL,
+ RstrW(IDS_ONLYPEINGUI),//"ILDASM supports only PE files in graphic mode",
+ RstrW(IDS_BADFILETYPE),//"Invalid File Type",
+ MB_OK|MB_ICONERROR|GetDasmMBRTLStyle());
+ return 0;
+ }
+ }
+ if (Init() == TRUE)
+ {
+ CreateGUI();
+ if(g_szInputFile[0])
+ {
+ GUISetModule(g_szInputFile);
+ DumpFile();
+ }
+ GUIMainLoop();
+ Cleanup();
+ DestroyGUI();
+ }
+ Uninit();
+ return 0 ;
+ }
+ return 0;
+}
+
diff --git a/src/tools/metainfo/.gitmirrorall b/src/tools/metainfo/.gitmirrorall
new file mode 100644
index 0000000000..9ee5c57b99
--- /dev/null
+++ b/src/tools/metainfo/.gitmirrorall
@@ -0,0 +1 @@
+This folder will be mirrored by the Git-TFS Mirror recursively. \ No newline at end of file
diff --git a/src/tools/metainfo/Native.rc b/src/tools/metainfo/Native.rc
new file mode 100644
index 0000000000..13e7ae2af2
--- /dev/null
+++ b/src/tools/metainfo/Native.rc
@@ -0,0 +1,9 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#define FX_VER_FILEDESCRIPTION_STR "Microsoft Common Language Runtime Metadata Info\0"
+
+#include <fxver.h>
+#include <fxver.rc>
diff --git a/src/tools/metainfo/mdinfo.cpp b/src/tools/metainfo/mdinfo.cpp
new file mode 100644
index 0000000000..b0db3591b9
--- /dev/null
+++ b/src/tools/metainfo/mdinfo.cpp
@@ -0,0 +1,4320 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include <stdio.h>
+#include <windows.h>
+#include <objbase.h>
+#include <crtdbg.h>
+#include <assert.h>
+
+#include <corpriv.h>
+#include <cor.h>
+#include "assert.h"
+#include "corerror.h"
+#include <winwrap.h>
+#include <prettyprintsig.h>
+
+#include <cahlpr.h>
+#include <limits.h>
+
+#include "mdinfo.h"
+
+#define LEGACY_ACTIVATION_SHIM_LOAD_LIBRARY WszLoadLibrary
+#define LEGACY_ACTIVATION_SHIM_DEFINE_CoInitializeEE
+#include "LegacyActivationShim.h"
+
+#define ENUM_BUFFER_SIZE 10
+#define TAB_SIZE 8
+
+#define NumItems(s) (sizeof(s) / sizeof(s[0]))
+
+#define ISFLAG(p,x) if (Is##p##x(flags)) strcat_s(sFlags,STRING_BUFFER_LEN, "["#x "] ");
+
+extern HRESULT _FillVariant(
+ BYTE bCPlusTypeFlag,
+ void const *pValue,
+ ULONG cbValue,
+ VARIANT *pvar);
+
+// Validator declarations.
+extern DWORD g_ValModuleType;
+#include <ivehandler.h>
+
+// Tables for mapping element type to text
+char *g_szMapElementType[] =
+{
+ "End", // 0x0
+ "Void", // 0x1
+ "Boolean",
+ "Char",
+ "I1",
+ "UI1",
+ "I2", // 0x6
+ "UI2",
+ "I4",
+ "UI4",
+ "I8",
+ "UI8",
+ "R4",
+ "R8",
+ "String",
+ "Ptr", // 0xf
+ "ByRef", // 0x10
+ "ValueClass",
+ "Class",
+ "Var",
+ "MDArray", // 0x14
+ "GenericInst",
+ "TypedByRef",
+ "VALUEARRAY",
+ "I",
+ "U",
+ "R", // 0x1a
+ "FNPTR",
+ "Object",
+ "SZArray",
+ "MVar",
+ "CMOD_REQD",
+ "CMOD_OPT",
+ "INTERNAL",
+};
+
+char *g_szMapUndecorateType[] =
+{
+ "", // 0x0
+ "void",
+ "boolean",
+ "Char",
+ "byte",
+ "unsigned byte",
+ "short",
+ "unsigned short",
+ "int",
+ "unsigned int",
+ "long",
+ "unsigned long",
+ "float",
+ "double",
+ "String",
+ "*", // 0xf
+ "ByRef",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "Function Pointer",
+ "Object",
+ "",
+ "",
+ "CMOD_REQD",
+ "CMOD_OPT",
+ "INTERNAL",
+};
+
+// Provide enough entries for IMAGE_CEE_CS_CALLCONV_MASK (defined in CorHdr.h)
+char *g_strCalling[] =
+{
+ "[DEFAULT]",
+ "[C]",
+ "[STDCALL]",
+ "[THISCALL]",
+ "[FASTCALL]",
+ "[VARARG]",
+ "[FIELD]",
+ "[LOCALSIG]",
+ "[PROPERTY]",
+ "[UNMANAGED]",
+ "[GENERICINST]",
+ "[NATIVEVARARG]",
+ "[INVALID]",
+ "[INVALID]",
+ "[INVALID]",
+ "[INVALID]"
+};
+
+char *g_szNativeType[] =
+{
+ "NATIVE_TYPE_END(DEPRECATED!)", // = 0x0, //DEPRECATED
+ "NATIVE_TYPE_VOID(DEPRECATED!)", // = 0x1, //DEPRECATED
+ "NATIVE_TYPE_BOOLEAN", // = 0x2, // (4 byte boolean value: TRUE = non-zero, FALSE = 0)
+ "NATIVE_TYPE_I1", // = 0x3,
+ "NATIVE_TYPE_U1", // = 0x4,
+ "NATIVE_TYPE_I2", // = 0x5,
+ "NATIVE_TYPE_U2", // = 0x6,
+ "NATIVE_TYPE_I4", // = 0x7,
+ "NATIVE_TYPE_U4", // = 0x8,
+ "NATIVE_TYPE_I8", // = 0x9,
+ "NATIVE_TYPE_U8", // = 0xa,
+ "NATIVE_TYPE_R4", // = 0xb,
+ "NATIVE_TYPE_R8", // = 0xc,
+ "NATIVE_TYPE_SYSCHAR(DEPRECATED!)", // = 0xd, //DEPRECATED
+ "NATIVE_TYPE_VARIANT(DEPRECATED!)", // = 0xe, //DEPRECATED
+ "NATIVE_TYPE_CURRENCY", // = 0xf,
+ "NATIVE_TYPE_PTR(DEPRECATED!)", // = 0x10, //DEPRECATED
+
+ "NATIVE_TYPE_DECIMAL(DEPRECATED!)", // = 0x11, //DEPRECATED
+ "NATIVE_TYPE_DATE(DEPRECATED!)", // = 0x12, //DEPRECATED
+ "NATIVE_TYPE_BSTR", // = 0x13,
+ "NATIVE_TYPE_LPSTR", // = 0x14,
+ "NATIVE_TYPE_LPWSTR", // = 0x15,
+ "NATIVE_TYPE_LPTSTR", // = 0x16,
+ "NATIVE_TYPE_FIXEDSYSSTRING", // = 0x17,
+ "NATIVE_TYPE_OBJECTREF(DEPRECATED!)", // = 0x18, //DEPRECATED
+ "NATIVE_TYPE_IUNKNOWN", // = 0x19,
+ "NATIVE_TYPE_IDISPATCH", // = 0x1a,
+ "NATIVE_TYPE_STRUCT", // = 0x1b,
+ "NATIVE_TYPE_INTF", // = 0x1c,
+ "NATIVE_TYPE_SAFEARRAY", // = 0x1d,
+ "NATIVE_TYPE_FIXEDARRAY", // = 0x1e,
+ "NATIVE_TYPE_INT", // = 0x1f,
+ "NATIVE_TYPE_UINT", // = 0x20,
+
+ "NATIVE_TYPE_NESTEDSTRUCT(DEPRECATED!)", // = 0x21, //DEPRECATED (use "NATIVE_TYPE_STRUCT)
+
+ "NATIVE_TYPE_BYVALSTR", // = 0x22,
+
+ "NATIVE_TYPE_ANSIBSTR", // = 0x23,
+
+ "NATIVE_TYPE_TBSTR", // = 0x24, // select BSTR or ANSIBSTR depending on platform
+
+
+ "NATIVE_TYPE_VARIANTBOOL", // = 0x25, // (2-byte boolean value: TRUE = -1, FALSE = 0)
+ "NATIVE_TYPE_FUNC", // = 0x26,
+ "NATIVE_TYPE_LPVOID", // = 0x27, // blind pointer (no deep marshaling)
+
+ "NATIVE_TYPE_ASANY", // = 0x28,
+ "<UNDEFINED NATIVE TYPE 0x29>",
+ "NATIVE_TYPE_ARRAY", // = 0x2a,
+ "NATIVE_TYPE_LPSTRUCT", // = 0x2b,
+ "NATIVE_TYPE_CUSTOMMARSHALER", // = 0x2c, // Custom marshaler.
+ "NATIVE_TYPE_ERROR", // = 0x2d, // VT_HRESULT when exporting to a typelib.
+};
+
+
+size_t g_cbCoffNames = 0;
+
+mdMethodDef g_tkEntryPoint = 0; // integration with ILDASM
+
+
+
+// helper to init signature buffer
+void MDInfo::InitSigBuffer()
+{
+ strcpy_s((LPSTR)m_sigBuf.Ptr(), 1, "");
+} // void MDInfo::InitSigBuffer()
+
+// helper to append a string into the signature buffer. If size of signature buffer is not big enough,
+// we will grow it.
+HRESULT MDInfo::AddToSigBuffer(__in_z __in char *string)
+{
+ HRESULT hr;
+ size_t LL = strlen((LPSTR)m_sigBuf.Ptr()) + strlen(string) + 1;
+ IfFailRet( m_sigBuf.ReSizeNoThrow(LL) );
+ strcat_s((LPSTR)m_sigBuf.Ptr(), LL, string);
+ return NOERROR;
+} // HRESULT MDInfo::AddToSigBuffer()
+
+MDInfo::MDInfo(IMetaDataImport2 *pImport, IMetaDataAssemblyImport *pAssemblyImport, LPCWSTR szScope, strPassBackFn inPBFn, ULONG DumpFilter)
+{ // This constructor is specific to ILDASM/MetaInfo integration
+
+ _ASSERTE(pImport != NULL);
+ _ASSERTE(NumItems(g_szMapElementType) == NumItems(g_szMapUndecorateType));
+ _ASSERTE(NumItems(g_szMapElementType) == ELEMENT_TYPE_MAX);
+
+ Init(inPBFn, (DUMP_FILTER)DumpFilter);
+
+ m_pImport = pImport;
+ m_pImport->AddRef();
+ if ((m_pAssemblyImport = pAssemblyImport))
+ m_pAssemblyImport->AddRef();
+ else
+ {
+ HRESULT hr = m_pImport->QueryInterface(IID_IMetaDataAssemblyImport, (void**) &m_pAssemblyImport);
+ if (FAILED(hr))
+ Error("QueryInterface failed for IID_IMetaDataAssemblyImport.", hr);
+ }
+
+} // MDInfo::MDInfo()
+
+MDInfo::MDInfo(IMetaDataDispenserEx *pDispenser, LPCWSTR szScope, strPassBackFn inPBFn, ULONG DumpFilter)
+{
+ HRESULT hr = S_OK;
+ VARIANT value;
+
+ _ASSERTE(pDispenser != NULL && inPBFn != NULL);
+ _ASSERTE(NumItems(g_szMapElementType) == NumItems(g_szMapUndecorateType));
+ _ASSERTE(NumItems(g_szMapElementType) == ELEMENT_TYPE_MAX);
+
+ Init(inPBFn, (DUMP_FILTER)DumpFilter);
+
+ // Attempt to open scope on given file
+ V_VT(&value) = VT_UI4;
+ V_UI4(&value) = MDImportOptionAll;
+ if (FAILED(hr = pDispenser->SetOption(MetaDataImportOption, &value)))
+ Error("SetOption failed.", hr);
+
+ hr = pDispenser->OpenScope(szScope, ofNoTransform, IID_IMetaDataImport2, (IUnknown**)&m_pImport);
+ if (hr == CLDB_E_BADUPDATEMODE)
+ {
+ V_VT(&value) = VT_UI4;
+ V_UI4(&value) = MDUpdateIncremental;
+ if (FAILED(hr = pDispenser->SetOption(MetaDataSetUpdate, &value)))
+ Error("SetOption failed.", hr);
+ hr = pDispenser->OpenScope(szScope, ofNoTransform, IID_IMetaDataImport2, (IUnknown**)&m_pImport);
+ }
+ if (FAILED(hr))
+ Error("OpenScope failed", hr);
+
+ // Query for the IMetaDataAssemblyImport interface.
+ hr = m_pImport->QueryInterface(IID_IMetaDataAssemblyImport, (void**) &m_pAssemblyImport);
+ if (FAILED(hr))
+ Error("QueryInterface failed for IID_IMetaDataAssemblyImport.", hr);
+
+} // MDInfo::MDInfo()
+
+
+MDInfo::MDInfo(IMetaDataDispenserEx *pDispenser, PBYTE pbMetaData, DWORD dwSize, strPassBackFn inPBFn, ULONG DumpFilter)
+{
+ _ASSERTE(pDispenser != NULL && inPBFn != NULL);
+ _ASSERTE(NumItems(g_szMapElementType) == NumItems(g_szMapUndecorateType));
+ _ASSERTE(NumItems(g_szMapElementType) == ELEMENT_TYPE_MAX);
+
+ Init(inPBFn, (DUMP_FILTER)DumpFilter);
+
+ // Attempt to open scope on manifest. It's valid for this to fail, because
+ // the blob we open may just be the assembly resources (the space is
+ // overloaded until we remove LM -a assemblies, at which point this
+ // constructor should probably be removed too).
+ HRESULT hr;
+ VARIANT value;
+ V_VT(&value) = VT_UI4;
+ V_UI4(&value) = MDImportOptionAll;
+ if (FAILED(hr = pDispenser->SetOption(MetaDataImportOption, &value)))
+ Error("SetOption failed.", hr);
+ if (SUCCEEDED(hr = pDispenser->OpenScopeOnMemory(pbMetaData, dwSize, ofNoTransform,
+ IID_IMetaDataImport2, (IUnknown**)&m_pImport)))
+ {
+ // Query for the IMetaDataAssemblyImport interface.
+ hr = m_pImport->QueryInterface(IID_IMetaDataAssemblyImport, (void**) &m_pAssemblyImport);
+ if (FAILED(hr))
+ Error("QueryInterface failed for IID_IMetaDataAssemblyImport.", hr);
+ }
+
+} // MDInfo::MDInfo()
+
+void MDInfo::Init(
+ strPassBackFn inPBFn, // Callback to write text.
+ DUMP_FILTER DumpFilter) // Flags to control the dump.
+{
+ m_VEHandlerReporterPtr = 0;
+ m_pbFn = inPBFn;
+ m_DumpFilter = DumpFilter;
+ m_pTables = NULL;
+ m_pTables2 = NULL;
+ m_pImport = NULL;
+ m_pAssemblyImport = NULL;
+} // void MDInfo::Init()
+
+// Destructor
+MDInfo::~MDInfo()
+{
+ if (m_pImport)
+ m_pImport->Release();
+ if (m_pAssemblyImport)
+ m_pAssemblyImport->Release();
+ if (m_pTables)
+ m_pTables->Release();
+ if (m_pTables2)
+ m_pTables2->Release();
+} // MDInfo::~MDInfo()
+
+//=====================================================================================================================
+//#define EXTERNAL_VE_HANDLER_FOR_MD_VALIDATION
+#ifndef EXTERNAL_VE_HANDLER_FOR_MD_VALIDATION
+
+HINSTANCE GetModuleInst()
+{
+ return NULL;
+} // HINSTANCE GetModuleInst()
+
+typedef HRESULT (*REPORTFCTN)(LPCWSTR, VEContext, HRESULT);
+HRESULT DefaultReporter( // Return status.
+ LPCWSTR szMsg, // Error message.
+ VEContext Context, // Error context (offset,token)
+ HRESULT hrRpt) // Original HRESULT
+{
+ if(szMsg)
+ {
+ printf("%S", szMsg);
+ // include token and offset from Context
+ if(Context.Token) printf(" [token:0x%08X]",Context.Token);
+ if(Context.uOffset) printf(" [at:0x%X]",Context.uOffset);
+ printf(" [hr:0x%08X]\n",hrRpt);
+ fflush(stdout);
+ }
+ return S_OK;
+} // HRESULT DefaultReporter()
+
+class MDVEHandlerClass : public IVEHandler
+{
+public:
+ LONG m_refCount;
+ REPORTFCTN m_fnReport;
+
+ MDVEHandlerClass() { m_refCount=0; m_fnReport=DefaultReporter; };
+ virtual ~MDVEHandlerClass() { };
+
+ //-----------------------------------------------------------
+ // IUnknown support
+ //-----------------------------------------------------------
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, void** pInterface)
+ {
+ if (id == IID_IVEHandler)
+ *pInterface = (IVEHandler*)this;
+ /*
+ else if (id == IID_IUnknown)
+ *pInterface = (IUnknown*)(IVEHandler*)this;
+ */
+ else
+ {
+ *pInterface = NULL;
+ return E_NOINTERFACE;
+ }
+
+ AddRef();
+ return S_OK;
+ }
+ ULONG STDMETHODCALLTYPE AddRef()
+ {
+ return InterlockedIncrement(&m_refCount);
+ }
+
+ ULONG STDMETHODCALLTYPE Release()
+ {
+ LONG refCount = InterlockedDecrement(&m_refCount);
+ if (refCount == 0) delete this;
+ return (refCount);
+ }
+ //-----------------------------------------------------------
+ // IVEHandler support
+ //-----------------------------------------------------------
+ HRESULT STDMETHODCALLTYPE SetReporterFtn(__int64 lFnPtr)
+ {
+ m_fnReport = lFnPtr ? reinterpret_cast<REPORTFCTN>(lFnPtr)
+ : DefaultReporter;
+ return S_OK;
+ };
+
+//*****************************************************************************
+// The Verification Event Handler itself. Declared in VEHandler.h as virtual, may be overridden
+//*****************************************************************************
+ HRESULT STDMETHODCALLTYPE VEHandler(HRESULT hrRpt, VEContext Context, SAFEARRAY *psa)
+ {
+ WCHAR rcBuf[1024]; // Resource string.
+ WCHAR rcMsg[1024]; // Error message.
+ BYTE *marker; // User text.
+ HRESULT hr;
+ ULONG32 k;
+ WCHAR *pWsz[1024]; // is more than 1024 string arguments likely?
+
+ // Return warnings without text.
+ if (!FAILED(hrRpt))
+ return (hrRpt);
+ memset(pWsz,0,sizeof(pWsz));
+
+ ULONG32 nVars;
+ // Convert safearray of variants into va_list
+ if(psa && (nVars = psa->rgsabound[0].cElements))
+ {
+ WCHAR *pwsz;
+ VARIANT *pVar;
+ ULONG32 i,l;
+ BYTE *pval;
+
+ _ASSERTE(psa->fFeatures & FADF_VARIANT);
+ _ASSERTE(psa->cDims == 1);
+ marker = new BYTE[nVars*sizeof(double)]; // double being the largest variant element
+ for(i=0,pVar=(VARIANT *)(psa->pvData),pval=marker; i < nVars; pVar++,i++)
+ {
+ switch(V_VT(pVar))
+ {
+ case VT_I1:
+ *(int *)pval = V_I1(pVar);
+ pval += sizeof(int);
+ break;
+
+ case VT_UI1:
+ *(int *)pval = V_UI1(pVar);
+ pval += sizeof(int);
+ break;
+
+
+ case VT_I2:
+ *(int *)pval = V_I2(pVar);
+ pval += sizeof(int);
+ break;
+
+ case VT_UI2:
+ *(int *)pval = V_UI2(pVar);
+ pval += sizeof(int);
+ break;
+
+ case VT_I8:
+ case VT_UI8:
+ *(INT64 *)pval = V_I8(pVar);
+ pval += sizeof(INT64);
+ break;
+
+
+ case VT_BYREF|VT_I1:
+ case VT_BYREF|VT_UI1: // it's ASCII string, convert it to UNICODE
+ {
+ PBYTE pb = V_UI1REF(pVar);
+ l = (ULONG32)strlen((char *)pb)+1;
+ pwsz = new WCHAR[l];
+ WszMultiByteToWideChar(CP_ACP,0,(char*)pb,-1,pwsz,l);
+ for(k=0; pWsz[k]; k++);
+ pWsz[k] = pwsz;
+
+ *(WCHAR **)pval = pwsz;
+ pval += sizeof(WCHAR *);
+ break;
+ }
+
+ default:
+ *(int *)pval = V_I4(pVar);
+ pval += sizeof(int);
+ break;
+ }
+ }
+ }
+ else
+ marker = NULL;
+
+ // If this is one of our errors, then grab the error from the rc file.
+ if (HRESULT_FACILITY(hrRpt) == FACILITY_URT)
+ {
+ hr = UtilLoadStringRC(LOWORD(hrRpt), rcBuf, NumItems(rcBuf), true);
+ if (hr == S_OK)
+ {
+ // Format the error.
+ vswprintf_s(rcMsg, NumItems(rcMsg), rcBuf, (va_list) marker);
+ rcMsg[NumItems(rcMsg) - 1] = 0;
+ }
+ }
+ // Otherwise it isn't one of ours, so we need to see if the system can
+ // find the text for it.
+ else
+ {
+ if (WszFormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+ 0, hrRpt, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ rcMsg, NumItems(rcMsg), 0))
+ {
+ hr = S_OK;
+
+ // System messages contain a trailing \r\n, which we don't want normally.
+ int iLen = lstrlenW(rcMsg);
+ if (iLen > 3 && rcMsg[iLen - 2] == '\r' && rcMsg[iLen - 1] == '\n')
+ rcMsg[iLen - 2] = '\0';
+ }
+ else
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+ if(marker) delete [] marker;
+
+ // If we failed to find the message anywhere, then issue a hard coded message.
+ if (FAILED(hr))
+ {
+ swprintf_s(rcMsg, NumItems(rcMsg), L"COM+ Runtime Internal error: 0x%08x", hrRpt);
+ //DEBUG_STMT(DbgWriteEx(rcMsg));
+ }
+
+ // delete WCHAR buffers allocated above (if any)
+ for(k=0; pWsz[k]; k++)
+ {
+ if(pWsz[k])
+ {
+ delete [] pWsz[k];
+ pWsz[k] = NULL;
+ }
+ }
+
+ return (m_fnReport(rcMsg, Context,hrRpt) == S_OK ? S_OK : E_FAIL);
+ };
+
+ static HRESULT STDMETHODCALLTYPE CreateObject(REFIID id, void **object)
+ { return E_NOTIMPL; }
+};
+
+#endif
+//=====================================================================================================================
+// DisplayMD() function
+//
+// Displays the meta data content of a file
+
+void MDInfo::DisplayMD()
+{
+ if ((m_DumpFilter & dumpAssem) && m_pAssemblyImport)
+ DisplayAssemblyInfo();
+ WriteLine("===========================================================");
+ // Metadata itself: Raw or normal view
+ if (m_DumpFilter & (dumpSchema | dumpHeader | dumpCSV | dumpRaw | dumpStats | dumpRawHeaps))
+ DisplayRaw();
+ else
+ {
+ DisplayVersionInfo();
+ DisplayScopeInfo();
+ WriteLine("===========================================================");
+ DisplayGlobalFunctions();
+ DisplayGlobalFields();
+ DisplayGlobalMemberRefs();
+ DisplayTypeDefs();
+ DisplayTypeRefs();
+ DisplayTypeSpecs();
+ DisplayMethodSpecs();
+ DisplayModuleRefs();
+ DisplaySignatures();
+ DisplayAssembly();
+ DisplayUserStrings();
+
+ // WriteLine("============================================================");
+ // WriteLine("Unresolved MemberRefs");
+ // DisplayMemberRefs(0x00000001, "\t");
+
+ VWrite("\n\nCoff symbol name overhead: %d\n", g_cbCoffNames);
+ }
+ WriteLine("===========================================================");
+ if (m_DumpFilter & dumpUnsat)
+ DisplayUnsatInfo();
+ WriteLine("===========================================================");
+ if (m_DumpFilter & dumpValidate)
+ {
+ IMetaDataValidate *pValidate = 0;
+#ifndef EXTERNAL_VE_HANDLER_FOR_MD_VALIDATION
+ MDVEHandlerClass *pVEHandler = 0;
+#else
+ IVEHandler *pVEHandler = 0;
+#endif
+ const char *szErrStr = 0;
+ HRESULT hr = S_OK;
+
+ // Get a pointer to the Validator interface.
+ hr = m_pImport->QueryInterface(IID_IMetaDataValidate, (void **) &pValidate);
+ if (FAILED(hr))
+ {
+ szErrStr = "QueryInterface failed for IMetaDataValidate.";
+ goto ErrExit;
+ }
+
+ // Get a pointer to the VEHandler interface.
+#ifndef EXTERNAL_VE_HANDLER_FOR_MD_VALIDATION
+ if((pVEHandler = new MDVEHandlerClass())) hr = S_OK;
+ else hr = E_FAIL;
+#else
+ hr = CoCreateInstance(CLSID_VEHandlerClass,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_IVEHandler,
+ (void **)&pVEHandler);
+#endif
+ if (FAILED(hr))
+ {
+#ifndef EXTERNAL_VE_HANDLER_FOR_MD_VALIDATION
+ szErrStr = "Failed to create VEHandler.";
+#else
+ szErrStr = "CoCreateInstance(VEHandler) failed.";
+#endif
+ goto ErrExit;
+ }
+
+ if(m_VEHandlerReporterPtr) pVEHandler->SetReporterFtn((__int64)m_VEHandlerReporterPtr);
+
+ hr = pValidate->ValidatorInit(g_ValModuleType, pVEHandler);
+ if (FAILED(hr))
+ {
+ szErrStr = "ValidatorInit failed.";
+ goto ErrExit;
+ }
+
+ hr = pValidate->ValidateMetaData();
+ if (FAILED(hr))
+ {
+ szErrStr = "ValidateMetaData failed to run successfully.";
+ goto ErrExit;
+ }
+ if (hr == S_OK)
+ WriteLine("No warnings or errors found.");
+ else if (hr == VLDTR_S_WRN)
+ WriteLine("Warnings found.");
+ else if (hr == VLDTR_S_ERR)
+ WriteLine("Errors found.");
+ else if (hr == VLDTR_S_WRNERR)
+ WriteLine("Warnings and Errors found.");
+ else
+ VWriteLine("Validator returned unexpected success code, hr=0x%08x.", hr);
+ErrExit:
+ if (pValidate)
+ pValidate->Release();
+#ifdef EXTERNAL_VE_HANDLER_FOR_MD_VALIDATION
+ if (pVEHandler)
+ pVEHandler->Release();
+#endif
+ if (szErrStr)
+ Error(szErrStr, hr);
+ }
+ WriteLine("===========================================================");
+} // MDVEHandlerClass()
+
+int MDInfo::WriteLine(__in_z __in char *str)
+{
+ ULONG32 count = (ULONG32) strlen(str);
+
+ m_pbFn(str);
+ m_pbFn("\n");
+ return count;
+} // int MDInfo::WriteLine()
+
+int MDInfo::Write(__in_z __in char *str)
+{
+ ULONG32 count = (ULONG32) strlen(str);
+
+ m_pbFn(str);
+ return count;
+} // int MDInfo::Write()
+
+int MDInfo::VWriteLine(__in_z __in char *str, ...)
+{
+ va_list marker;
+ int count;
+
+ va_start(marker, str);
+ count = VWriteMarker(str, marker);
+ m_pbFn("\n");
+ va_end(marker);
+ return count;
+} // int MDInfo::VWriteLine()
+
+int MDInfo::VWrite(__in_z __in char *str, ...)
+{
+ va_list marker;
+ int count;
+
+ va_start(marker, str);
+ count = VWriteMarker(str, marker);
+ va_end(marker);
+ return count;
+} // int MDInfo::VWrite()
+
+int MDInfo::VWriteMarker(__in_z __in char *str, va_list marker)
+{
+ HRESULT hr;
+ int count = -1;
+ // Used to allocate 1K, then if not enough, 2K, then 4K.
+ // Faster to allocate 32K right away and be done with it,
+ // we're not running on Commodore 64
+ if (FAILED(hr = m_output.ReSizeNoThrow(STRING_BUFFER_LEN * 8)))
+ Error("ReSize failed.", hr);
+ else
+ {
+ count = vsprintf_s((char *)m_output.Ptr(), STRING_BUFFER_LEN * 8, str, marker);
+ m_pbFn((char *)m_output.Ptr());
+ }
+ return count;
+} // int MDInfo::VWriteToBuffer()
+
+// Error() function -- prints an error and returns
+void MDInfo::Error(const char* szError, HRESULT hr)
+{
+ printf("\n%s\n",szError);
+ if (hr != S_OK)
+ {
+ printf("Failed return code: 0x%08x\n", hr);
+
+ IErrorInfo *pIErr = NULL; // Error interface.
+ BSTR bstrDesc = NULL; // Description text.
+
+ // Try to get an error info object and display the message.
+ if (GetErrorInfo(0, &pIErr) == S_OK &&
+ pIErr->GetDescription(&bstrDesc) == S_OK)
+ {
+ printf("%ls ", bstrDesc);
+ SysFreeString(bstrDesc);
+ }
+
+ // Free the error interface.
+ if (pIErr)
+ pIErr->Release();
+
+ }
+ LegacyActivationShim::CoUninitializeCor();
+#ifndef FEATURE_PAL
+ CoUninitialize();
+#endif
+ exit(hr);
+} // void MDInfo::Error()
+
+// Print out the optional version info included in the MetaData.
+
+void MDInfo::DisplayVersionInfo()
+{
+ if (!(m_DumpFilter & MDInfo::dumpNoLogo))
+ {
+ LPCUTF8 pVersionStr;
+ HRESULT hr = S_OK;
+
+ if (m_pTables == 0)
+ {
+ if (m_pImport)
+ hr = m_pImport->QueryInterface(IID_IMetaDataTables, (void**)&m_pTables);
+ else if (m_pAssemblyImport)
+ hr = m_pAssemblyImport->QueryInterface(IID_IMetaDataTables, (void**)&m_pTables);
+ else
+ return;
+ if (FAILED(hr))
+ Error("QueryInterface failed for IID_IMetaDataTables.", hr);
+ }
+
+ hr = m_pTables->GetString(1, &pVersionStr);
+ if (FAILED(hr))
+ Error("GetString() failed.", hr);
+ if (strstr(pVersionStr, "Version of runtime against which the binary is built : ")
+ == pVersionStr)
+ {
+ WriteLine(const_cast<char *>(pVersionStr));
+ }
+ }
+} // void MDInfo::DisplayVersionInfo()
+
+// Prints out information about the scope
+
+void MDInfo::DisplayScopeInfo()
+{
+ HRESULT hr;
+ mdModule mdm;
+ GUID mvid;
+ WCHAR scopeName[STRING_BUFFER_LEN];
+ WCHAR guidString[STRING_BUFFER_LEN];
+
+ hr = m_pImport->GetScopeProps( scopeName, STRING_BUFFER_LEN, 0, &mvid);
+ if (FAILED(hr)) Error("GetScopeProps failed.", hr);
+
+ VWriteLine("ScopeName : %ls",scopeName);
+
+ if (!(m_DumpFilter & MDInfo::dumpNoLogo))
+ VWriteLine("MVID : %ls",GUIDAsString(mvid, guidString, STRING_BUFFER_LEN));
+
+ hr = m_pImport->GetModuleFromScope(&mdm);
+ if (FAILED(hr)) Error("GetModuleFromScope failed.", hr);
+ DisplayPermissions(mdm, "");
+ DisplayCustomAttributes(mdm, "\t");
+} // void MDInfo::DisplayScopeInfo()
+
+void MDInfo::DisplayRaw()
+{
+ int iDump; // Level of info to dump.
+
+ if (m_pTables == 0)
+ m_pImport->QueryInterface(IID_IMetaDataTables, (void**)&m_pTables);
+ if (m_pTables == 0)
+ Error("Can't get table info.");
+ if (m_pTables2 == 0)
+ m_pImport->QueryInterface(IID_IMetaDataTables2, (void**)&m_pTables2);
+
+ if (m_DumpFilter & dumpCSV)
+ DumpRawCSV();
+ if (m_DumpFilter & (dumpSchema | dumpHeader | dumpRaw | dumpStats))
+ {
+ if (m_DumpFilter & dumpRaw)
+ iDump = 3;
+ else
+ if (m_DumpFilter & dumpSchema)
+ iDump = 2;
+ else
+ iDump = 1;
+
+ DumpRaw(iDump, (m_DumpFilter & dumpStats) != 0);
+ }
+ if (m_DumpFilter & dumpRawHeaps)
+ DumpRawHeaps();
+} // void MDInfo::DisplayRaw()
+
+// return the name of the type of token passed in
+
+char *MDInfo::TokenTypeName(mdToken inToken)
+{
+ switch(TypeFromToken(inToken))
+ {
+ case mdtTypeDef: return "TypeDef";
+ case mdtInterfaceImpl: return "InterfaceImpl";
+ case mdtMethodDef: return "MethodDef";
+ case mdtFieldDef: return "FieldDef";
+ case mdtTypeRef: return "TypeRef";
+ case mdtMemberRef: return "MemberRef";
+ case mdtCustomAttribute:return "CustomAttribute";
+ case mdtParamDef: return "ParamDef";
+ case mdtProperty: return "Property";
+ case mdtEvent: return "Event";
+ case mdtTypeSpec: return "TypeSpec";
+ default: return "[UnknownTokenType]";
+ }
+} // char *MDInfo::TokenTypeName()
+
+// Prints out name of the given memberref
+//
+
+LPCWSTR MDInfo::MemberRefName(mdMemberRef inMemRef, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen)
+{
+ HRESULT hr;
+
+
+ hr = m_pImport->GetMemberRefProps( inMemRef, NULL, buffer, bufLen,
+ NULL, NULL, NULL);
+ if (FAILED(hr)) Error("GetMemberRefProps failed.", hr);
+
+ return buffer;
+} // LPCWSTR MDInfo::MemberRefName()
+
+
+// Prints out information about the given memberref
+//
+
+void MDInfo::DisplayMemberRefInfo(mdMemberRef inMemRef, const char *preFix)
+{
+ HRESULT hr;
+ WCHAR memRefName[STRING_BUFFER_LEN];
+ ULONG nameLen;
+ mdToken token;
+ PCCOR_SIGNATURE pbSigBlob;
+ ULONG ulSigBlob;
+ char newPreFix[STRING_BUFFER_LEN];
+
+
+ hr = m_pImport->GetMemberRefProps( inMemRef, &token, memRefName, STRING_BUFFER_LEN,
+ &nameLen, &pbSigBlob, &ulSigBlob);
+ if (FAILED(hr)) Error("GetMemberRefProps failed.", hr);
+
+ VWriteLine("%s\t\tMember: (%8.8x) %ls: ", preFix, inMemRef, memRefName);
+
+ if (ulSigBlob)
+ DisplaySignature(pbSigBlob, ulSigBlob, preFix);
+ else
+ VWriteLine("%s\t\tERROR: no valid signature ", preFix);
+
+ sprintf_s (newPreFix, STRING_BUFFER_LEN, "\t\t%s", preFix);
+ DisplayCustomAttributes(inMemRef, newPreFix);
+} // void MDInfo::DisplayMemberRefInfo()
+
+// Prints out information about all memberrefs of the given typeref
+//
+
+void MDInfo::DisplayMemberRefs(mdToken tkParent, const char *preFix)
+{
+ HCORENUM memRefEnum = NULL;
+ HRESULT hr;
+ mdMemberRef memRefs[ENUM_BUFFER_SIZE];
+ ULONG count, totalCount = 1;
+
+
+ while (SUCCEEDED(hr = m_pImport->EnumMemberRefs( &memRefEnum, tkParent,
+ memRefs, NumItems(memRefs), &count)) &&
+ count > 0)
+ {
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ VWriteLine("%s\tMemberRef #%d (%08x)", preFix, totalCount, memRefs[i]);
+ VWriteLine("%s\t-------------------------------------------------------", preFix);
+ DisplayMemberRefInfo(memRefs[i], preFix);
+ }
+ }
+ m_pImport->CloseEnum( memRefEnum);
+} // void MDInfo::DisplayMemberRefs()
+
+// Prints out information about all resources in the com object
+//
+
+// Iterates through each typeref and prints out the information of each
+//
+
+void MDInfo::DisplayTypeRefs()
+{
+ HCORENUM typeRefEnum = NULL;
+ mdTypeRef typeRefs[ENUM_BUFFER_SIZE];
+ ULONG count, totalCount=1;
+ HRESULT hr;
+
+ while (SUCCEEDED(hr = m_pImport->EnumTypeRefs( &typeRefEnum,
+ typeRefs, NumItems(typeRefs), &count)) &&
+ count > 0)
+ {
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ VWriteLine("TypeRef #%d (%08x)", totalCount, typeRefs[i]);
+ WriteLine("-------------------------------------------------------");
+ DisplayTypeRefInfo(typeRefs[i]);
+ DisplayMemberRefs(typeRefs[i], "");
+ WriteLine("");
+ }
+ }
+ m_pImport->CloseEnum( typeRefEnum);
+} // void MDInfo::DisplayTypeRefs()
+
+void MDInfo::DisplayTypeSpecs()
+{
+ HCORENUM typespecEnum = NULL;
+ mdTypeSpec typespecs[ENUM_BUFFER_SIZE];
+ ULONG count, totalCount=1;
+ HRESULT hr;
+
+ while (SUCCEEDED(hr = m_pImport->EnumTypeSpecs( &typespecEnum,
+ typespecs, NumItems(typespecs), &count)) &&
+ count > 0)
+ {
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ VWriteLine("TypeSpec #%d (%08x)", totalCount, typespecs[i]);
+ WriteLine("-------------------------------------------------------");
+ DisplayTypeSpecInfo(typespecs[i], "");
+ DisplayMemberRefs(typespecs[i], "");
+ WriteLine("");
+ }
+ }
+ m_pImport->CloseEnum( typespecEnum);
+} // void MDInfo::DisplayTypeSpecs()
+
+void MDInfo::DisplayMethodSpecs()
+{
+ HCORENUM MethodSpecEnum = NULL;
+ mdMethodSpec MethodSpecs[ENUM_BUFFER_SIZE];
+ ULONG count, totalCount=1;
+///// HRESULT hr;
+
+
+///// HACK until I implement EnumMethodSpecs!
+///// while (SUCCEEDED(hr = m_pImport->EnumMethodSpecs( &MethodSpecEnum,
+///// MethodSpecs, NumItems(MethodSpecs), &count)) &&
+///// count > 0)
+ for (ULONG rid=1; m_pImport->IsValidToken(TokenFromRid(rid, mdtMethodSpec)); ++rid)
+ {
+// More hackery
+count = 1;
+MethodSpecs[0] = TokenFromRid(rid, mdtMethodSpec);
+// More hackery
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ VWriteLine("MethodSpec #%d (%08x)", totalCount, MethodSpecs[i]);
+ DisplayMethodSpecInfo(MethodSpecs[i], "");
+ WriteLine("");
+ }
+ }
+ m_pImport->CloseEnum( MethodSpecEnum);
+} // void MDInfo::DisplayMethodSpecs()
+
+
+
+// Called to display the information about all typedefs in the object.
+//
+
+void MDInfo::DisplayTypeDefs()
+{
+ HCORENUM typeDefEnum = NULL;
+ mdTypeDef typeDefs[ENUM_BUFFER_SIZE];
+ ULONG count, totalCount = 1;
+ HRESULT hr;
+
+ while (SUCCEEDED(hr = m_pImport->EnumTypeDefs( &typeDefEnum,
+ typeDefs, NumItems(typeDefs), &count)) &&
+ count > 0)
+ {
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ VWriteLine("TypeDef #%d (%08x)", totalCount, typeDefs[i]);
+ WriteLine("-------------------------------------------------------");
+ DisplayTypeDefInfo(typeDefs[i]);
+ WriteLine("");
+ }
+ }
+ m_pImport->CloseEnum( typeDefEnum);
+} // void MDInfo::DisplayTypeDefs()
+
+// Called to display the information about all modulerefs in the object.
+//
+
+void MDInfo::DisplayModuleRefs()
+{
+ HCORENUM moduleRefEnum = NULL;
+ mdModuleRef moduleRefs[ENUM_BUFFER_SIZE];
+ ULONG count, totalCount = 1;
+ HRESULT hr;
+
+ while (SUCCEEDED(hr = m_pImport->EnumModuleRefs( &moduleRefEnum,
+ moduleRefs, NumItems(moduleRefs), &count)) &&
+ count > 0)
+ {
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ VWriteLine("ModuleRef #%d (%08x)", totalCount, moduleRefs[i]);
+ WriteLine("-------------------------------------------------------");
+ DisplayModuleRefInfo(moduleRefs[i]);
+ DisplayMemberRefs(moduleRefs[i], "");
+ WriteLine("");
+ }
+ }
+ m_pImport->CloseEnum( moduleRefEnum);
+} // void MDInfo::DisplayModuleRefs()
+
+// Prints out information about the given moduleref
+//
+
+void MDInfo::DisplayModuleRefInfo(mdModuleRef inModuleRef)
+{
+ HRESULT hr;
+ WCHAR moduleRefName[STRING_BUFFER_LEN];
+ ULONG nameLen;
+
+
+ hr = m_pImport->GetModuleRefProps( inModuleRef, moduleRefName, STRING_BUFFER_LEN,
+ &nameLen);
+ if (FAILED(hr)) Error("GetModuleRefProps failed.", hr);
+
+ VWriteLine("\t\tModuleRef: (%8.8x) %ls: ", inModuleRef, moduleRefName);
+ DisplayCustomAttributes(inModuleRef, "\t\t");
+} // void MDInfo::DisplayModuleRefInfo()
+
+
+// Called to display the information about all signatures in the object.
+//
+
+void MDInfo::DisplaySignatures()
+{
+ HCORENUM signatureEnum = NULL;
+ mdSignature signatures[ENUM_BUFFER_SIZE];
+ ULONG count, totalCount = 1;
+ HRESULT hr;
+
+ while (SUCCEEDED(hr = m_pImport->EnumSignatures( &signatureEnum,
+ signatures, NumItems(signatures), &count)) &&
+ count > 0)
+ {
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ VWriteLine("Signature #%d (%#08x)", totalCount, signatures[i]);
+ WriteLine("-------------------------------------------------------");
+ DisplaySignatureInfo(signatures[i]);
+ WriteLine("");
+ }
+ }
+ m_pImport->CloseEnum( signatureEnum);
+} // void MDInfo::DisplaySignatures()
+
+
+// Prints out information about the given signature
+//
+
+void MDInfo::DisplaySignatureInfo(mdSignature inSignature)
+{
+ HRESULT hr;
+ PCCOR_SIGNATURE pbSigBlob;
+ ULONG ulSigBlob;
+
+
+ hr = m_pImport->GetSigFromToken( inSignature, &pbSigBlob, &ulSigBlob );
+ if (FAILED(hr)) Error("GetSigFromToken failed.", hr);
+ if(ulSigBlob)
+ DisplaySignature(pbSigBlob, ulSigBlob, "");
+ else
+ VWriteLine("\t\tERROR: no valid signature ");
+} // void MDInfo::DisplaySignatureInfo()
+
+
+// returns the passed-in buffer which is filled with the name of the given
+// member in wide characters
+//
+
+LPCWSTR MDInfo::MemberName(mdToken inToken, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen)
+{
+ HRESULT hr;
+
+
+ hr = m_pImport->GetMemberProps( inToken, NULL, buffer, bufLen,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ if (FAILED(hr)) Error("GetMemberProps failed.", hr);
+
+ return (buffer);
+} // LPCWSTR MDInfo::MemberName()
+
+
+// displays information for the given method
+//
+
+void MDInfo::DisplayMethodInfo(mdMethodDef inMethod, DWORD *pflags)
+{
+ HRESULT hr;
+ mdTypeDef memTypeDef;
+ WCHAR memberName[STRING_BUFFER_LEN];
+ ULONG nameLen;
+ DWORD flags;
+ PCCOR_SIGNATURE pbSigBlob;
+ ULONG ulSigBlob;
+ ULONG ulCodeRVA;
+ ULONG ulImplFlags;
+
+
+ hr = m_pImport->GetMethodProps( inMethod, &memTypeDef, memberName, STRING_BUFFER_LEN,
+ &nameLen, &flags, &pbSigBlob, &ulSigBlob, &ulCodeRVA, &ulImplFlags);
+ if (FAILED(hr)) Error("GetMethodProps failed.", hr);
+ if (pflags)
+ *pflags = flags;
+
+ VWriteLine("\t\tMethodName: %ls (%8.8X)", memberName, inMethod);
+
+ char sFlags[STRING_BUFFER_LEN];
+
+ sFlags[0] = 0;
+ ISFLAG(Md, Public);
+ ISFLAG(Md, Private);
+ ISFLAG(Md, Family);
+ ISFLAG(Md, Assem);
+ ISFLAG(Md, FamANDAssem);
+ ISFLAG(Md, FamORAssem);
+ ISFLAG(Md, PrivateScope);
+ ISFLAG(Md, Static);
+ ISFLAG(Md, Final);
+ ISFLAG(Md, Virtual);
+ ISFLAG(Md, HideBySig);
+ ISFLAG(Md, ReuseSlot);
+ ISFLAG(Md, NewSlot);
+ ISFLAG(Md, Abstract);
+ ISFLAG(Md, SpecialName);
+ ISFLAG(Md, RTSpecialName);
+ ISFLAG(Md, PinvokeImpl);
+ ISFLAG(Md, UnmanagedExport);
+ if (!*sFlags)
+ strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
+
+ if (IsMdInstanceInitializerW(flags, memberName)) strcat_s(sFlags, STRING_BUFFER_LEN, "[.ctor] ");
+ if (IsMdClassConstructorW(flags, memberName)) strcat_s(sFlags,STRING_BUFFER_LEN, "[.cctor] ");
+ // "Reserved" flags
+ ISFLAG(Md, HasSecurity);
+ ISFLAG(Md, RequireSecObject);
+
+ VWriteLine("\t\tFlags : %s (%08x)", sFlags, flags);
+ VWriteLine("\t\tRVA : 0x%08x", ulCodeRVA);
+
+ flags = ulImplFlags;
+ sFlags[0] = 0;
+ ISFLAG(Mi, Native);
+ ISFLAG(Mi, IL);
+ ISFLAG(Mi, OPTIL);
+ ISFLAG(Mi, Runtime);
+ ISFLAG(Mi, Unmanaged);
+ ISFLAG(Mi, Managed);
+ ISFLAG(Mi, ForwardRef);
+ ISFLAG(Mi, PreserveSig);
+ ISFLAG(Mi, InternalCall);
+ ISFLAG(Mi, Synchronized);
+ ISFLAG(Mi, NoInlining);
+ if (!*sFlags)
+ strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
+
+ VWriteLine("\t\tImplFlags : %s (%08x)", sFlags, flags);
+
+ if (ulSigBlob)
+ DisplaySignature(pbSigBlob, ulSigBlob, "");
+ else
+ VWriteLine("\t\tERROR: no valid signature ");
+
+ DisplayGenericParams(inMethod, "\t\t");
+
+} // void MDInfo::DisplayMethodInfo()
+
+// displays the member information for the given field
+//
+
+void MDInfo::DisplayFieldInfo(mdFieldDef inField, DWORD *pdwFlags)
+{
+ HRESULT hr;
+ mdTypeDef memTypeDef;
+ WCHAR memberName[STRING_BUFFER_LEN];
+ ULONG nameLen;
+ DWORD flags;
+ PCCOR_SIGNATURE pbSigBlob;
+ ULONG ulSigBlob;
+ DWORD dwCPlusTypeFlag;
+ void const *pValue;
+ ULONG cbValue;
+ VARIANT defaultValue;
+
+
+ ::VariantInit(&defaultValue);
+ hr = m_pImport->GetFieldProps( inField, &memTypeDef, memberName, STRING_BUFFER_LEN,
+ &nameLen, &flags, &pbSigBlob, &ulSigBlob, &dwCPlusTypeFlag,
+ &pValue, &cbValue);
+ if (FAILED(hr)) Error("GetFieldProps failed.", hr);
+
+ if (pdwFlags)
+ *pdwFlags = flags;
+
+ _FillVariant((BYTE)dwCPlusTypeFlag, pValue, cbValue, &defaultValue);
+
+ char sFlags[STRING_BUFFER_LEN];
+
+ sFlags[0] = 0;
+ ISFLAG(Fd, Public);
+ ISFLAG(Fd, Private);
+ ISFLAG(Fd, Family);
+ ISFLAG(Fd, Assembly);
+ ISFLAG(Fd, FamANDAssem);
+ ISFLAG(Fd, FamORAssem);
+ ISFLAG(Fd, PrivateScope);
+ ISFLAG(Fd, Static);
+ ISFLAG(Fd, InitOnly);
+ ISFLAG(Fd, Literal);
+ ISFLAG(Fd, NotSerialized);
+ ISFLAG(Fd, SpecialName);
+ ISFLAG(Fd, RTSpecialName);
+ ISFLAG(Fd, PinvokeImpl);
+ // "Reserved" flags
+ ISFLAG(Fd, HasDefault);
+ if (!*sFlags)
+ strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
+
+ VWriteLine("\t\tField Name: %ls (%8.8X)", memberName, inField);
+ VWriteLine("\t\tFlags : %s (%08x)", sFlags, flags);
+ if (IsFdHasDefault(flags))
+ VWriteLine("\tDefltValue: (%s) %ls", g_szMapElementType[dwCPlusTypeFlag], VariantAsString(&defaultValue));
+ if (!ulSigBlob) // Signature size should be non-zero for fields
+ VWriteLine("\t\tERROR: no valid signature ");
+ else
+ DisplaySignature(pbSigBlob, ulSigBlob, "");
+
+ ::VariantClear(&defaultValue);
+} // void MDInfo::DisplayFieldInfo()
+
+// displays the RVA for the given global field.
+void MDInfo::DisplayFieldRVA(mdFieldDef inFieldDef)
+{
+ HRESULT hr;
+ ULONG ulRVA;
+
+ hr = m_pImport->GetRVA(inFieldDef, &ulRVA, 0);
+ if (FAILED(hr) && hr != CLDB_E_RECORD_NOTFOUND) Error("GetRVA failed.", hr);
+
+ VWriteLine("\t\tRVA : 0x%08x", ulRVA);
+} // void MDInfo::DisplayFieldRVA()
+
+// displays information about every global function.
+void MDInfo::DisplayGlobalFunctions()
+{
+ WriteLine("Global functions");
+ WriteLine("-------------------------------------------------------");
+ DisplayMethods(mdTokenNil);
+ WriteLine("");
+} // void MDInfo::DisplayGlobalFunctions()
+
+// displays information about every global field.
+void MDInfo::DisplayGlobalFields()
+{
+ WriteLine("Global fields");
+ WriteLine("-------------------------------------------------------");
+ DisplayFields(mdTokenNil, NULL, 0);
+ WriteLine("");
+} // void MDInfo::DisplayGlobalFields()
+
+// displays information about every global memberref.
+void MDInfo::DisplayGlobalMemberRefs()
+{
+ WriteLine("Global MemberRefs");
+ WriteLine("-------------------------------------------------------");
+ DisplayMemberRefs(mdTokenNil, "");
+ WriteLine("");
+} // void MDInfo::DisplayGlobalMemberRefs()
+
+// displays information about every method in a given typedef
+//
+
+void MDInfo::DisplayMethods(mdTypeDef inTypeDef)
+{
+ HCORENUM methodEnum = NULL;
+ mdToken methods[ENUM_BUFFER_SIZE];
+ DWORD flags;
+ ULONG count, totalCount = 1;
+ HRESULT hr;
+
+
+ while (SUCCEEDED(hr = m_pImport->EnumMethods( &methodEnum, inTypeDef,
+ methods, NumItems(methods), &count)) &&
+ count > 0)
+ {
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ VWriteLine("\tMethod #%d (%08x) %s", totalCount, methods[i], (methods[i] == g_tkEntryPoint) ? "[ENTRYPOINT]" : "");
+ WriteLine("\t-------------------------------------------------------");
+ DisplayMethodInfo(methods[i], &flags);
+ DisplayParams(methods[i]);
+ DisplayCustomAttributes(methods[i], "\t\t");
+ DisplayPermissions(methods[i], "\t");
+ DisplayMemberRefs(methods[i], "\t");
+
+ // P-invoke data if present.
+ if (IsMdPinvokeImpl(flags))
+ DisplayPinvokeInfo(methods[i]);
+
+ WriteLine("");
+ }
+ }
+ m_pImport->CloseEnum( methodEnum);
+} // void MDInfo::DisplayMethods()
+
+
+// displays information about every field in a given typedef
+//
+
+void MDInfo::DisplayFields(mdTypeDef inTypeDef, COR_FIELD_OFFSET *rFieldOffset, ULONG cFieldOffset)
+{
+ HCORENUM fieldEnum = NULL;
+ mdToken fields[ENUM_BUFFER_SIZE];
+ ULONG count, totalCount = 1;
+ DWORD flags;
+ HRESULT hr;
+
+
+ while (SUCCEEDED(hr = m_pImport->EnumFields( &fieldEnum, inTypeDef,
+ fields, NumItems(fields), &count)) &&
+ count > 0)
+ {
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ VWriteLine("\tField #%d (%08x)",totalCount, fields[i]);
+ WriteLine("\t-------------------------------------------------------");
+ DisplayFieldInfo(fields[i], &flags);
+ DisplayCustomAttributes(fields[i], "\t\t");
+ DisplayPermissions(fields[i], "\t");
+ DisplayFieldMarshal(fields[i]);
+
+ // RVA if its a global field.
+ if (inTypeDef == mdTokenNil)
+ DisplayFieldRVA(fields[i]);
+
+ // P-invoke data if present.
+ if (IsFdPinvokeImpl(flags))
+ DisplayPinvokeInfo(fields[i]);
+
+ // Display offset if present.
+ if (cFieldOffset)
+ {
+ bool found = false;
+ for (ULONG iLayout = 0; i < cFieldOffset; ++iLayout)
+ {
+ if (RidFromToken(rFieldOffset[iLayout].ridOfField) == RidFromToken(fields[i]))
+ {
+ found = true;
+ VWriteLine("\t\tOffset : 0x%08x", rFieldOffset[iLayout].ulOffset);
+ break;
+ }
+ }
+ _ASSERTE(found);
+ }
+ WriteLine("");
+ }
+ }
+ m_pImport->CloseEnum( fieldEnum);
+} // void MDInfo::DisplayFields()
+
+
+// displays information about every methodImpl in a given typedef
+//
+
+void MDInfo::DisplayMethodImpls(mdTypeDef inTypeDef)
+{
+ HCORENUM methodImplEnum = NULL;
+ mdMethodDef rtkMethodBody[ENUM_BUFFER_SIZE];
+ mdMethodDef rtkMethodDecl[ENUM_BUFFER_SIZE];
+
+ ULONG count, totalCount=1;
+ HRESULT hr;
+
+
+ while (SUCCEEDED(hr = m_pImport->EnumMethodImpls( &methodImplEnum, inTypeDef,
+ rtkMethodBody, rtkMethodDecl, NumItems(rtkMethodBody), &count)) &&
+ count > 0)
+ {
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ VWriteLine("\n\tMethodImpl #%d (%08x)", totalCount, totalCount);
+ WriteLine("\t-------------------------------------------------------");
+ VWriteLine("\t\tMethod Body Token : 0x%08x", rtkMethodBody[i]);
+ VWriteLine("\t\tMethod Declaration Token : 0x%08x", rtkMethodDecl[i]);
+ WriteLine("");
+ }
+ }
+ m_pImport->CloseEnum( methodImplEnum);
+} // void MDInfo::DisplayMethodImpls()
+
+// displays information about the given parameter
+//
+
+void MDInfo::DisplayParamInfo(mdParamDef inParamDef)
+{
+ mdMethodDef md;
+ ULONG num;
+ WCHAR paramName[STRING_BUFFER_LEN];
+ ULONG nameLen;
+ DWORD flags;
+ VARIANT defValue;
+ DWORD dwCPlusFlags;
+ void const *pValue;
+ ULONG cbValue;
+
+
+ ::VariantInit(&defValue);
+ HRESULT hr = m_pImport->GetParamProps( inParamDef, &md, &num, paramName, NumItems(paramName),
+ &nameLen, &flags, &dwCPlusFlags, &pValue, &cbValue);
+ if (FAILED(hr)) Error("GetParamProps failed.", hr);
+
+ _FillVariant((BYTE)dwCPlusFlags, pValue, cbValue, &defValue);
+
+ char sFlags[STRING_BUFFER_LEN];
+ sFlags[0] = 0;
+ ISFLAG(Pd, In);
+ ISFLAG(Pd, Out);
+ ISFLAG(Pd, Optional);
+ // "Reserved" flags.
+ ISFLAG(Pd, HasDefault);
+ ISFLAG(Pd, HasFieldMarshal);
+ if (!*sFlags)
+ strcpy_s(sFlags,STRING_BUFFER_LEN, "[none]");
+
+ VWrite("\t\t\t(%ld) ParamToken : (%08x) Name : %ls flags: %s (%08x)", num, inParamDef, paramName, sFlags, flags);
+ if (IsPdHasDefault(flags))
+ VWriteLine(" Default: (%s) %ls", g_szMapElementType[dwCPlusFlags], VariantAsString(&defValue));
+ else
+ VWriteLine("");
+ DisplayCustomAttributes(inParamDef, "\t\t\t");
+
+ ::VariantClear(&defValue);
+} // void MDInfo::DisplayParamInfo()
+
+
+// displays all parameters for a given memberdef
+//
+
+void MDInfo::DisplayParams(mdMethodDef inMethodDef)
+{
+ HCORENUM paramEnum = NULL;
+ mdParamDef params[ENUM_BUFFER_SIZE];
+ ULONG count, paramCount;
+ bool first = true;
+ HRESULT hr;
+
+
+ while (SUCCEEDED(hr = m_pImport->EnumParams( &paramEnum, inMethodDef,
+ params, NumItems(params), &count)) &&
+ count > 0)
+ {
+ if (first)
+ {
+ m_pImport->CountEnum( paramEnum, &paramCount);
+ VWriteLine("\t\t%d Parameters", paramCount);
+ }
+ for (ULONG i = 0; i < count; i++)
+ {
+ DisplayParamInfo(params[i]);
+ DisplayFieldMarshal(params[i]);
+ }
+ first = false;
+ }
+ m_pImport->CloseEnum( paramEnum);
+} // void MDInfo::DisplayParams()
+
+void MDInfo::DisplayGenericParams(mdToken tk, const char *prefix)
+{
+ HCORENUM paramEnum = NULL;
+ mdParamDef params[ENUM_BUFFER_SIZE];
+ ULONG count, paramCount;
+ bool first = true;
+ HRESULT hr;
+
+
+ while (SUCCEEDED(hr = m_pImport->EnumGenericParams( &paramEnum, tk,
+ params, NumItems(params), &count)) &&
+ count > 0)
+ {
+ if (first)
+ {
+ m_pImport->CountEnum( paramEnum, &paramCount);
+ VWriteLine("%s%d Generic Parameters", prefix, paramCount);
+ }
+ for (ULONG i = 0; i < count; i++)
+ {
+ DisplayGenericParamInfo(params[i], prefix);
+ }
+ first = false;
+ }
+ m_pImport->CloseEnum( paramEnum);
+}
+
+void MDInfo::DisplayGenericParamInfo(mdGenericParam tkParam, const char *prefix)
+{
+ ULONG ulSeq;
+ WCHAR paramName[STRING_BUFFER_LEN];
+ ULONG nameLen;
+ DWORD flags;
+ mdToken tkOwner;
+ char newprefix[30];
+ HCORENUM constraintEnum = NULL;
+ mdParamDef constraints[4];
+ ULONG count, constraintCount;
+ mdToken constraint;
+ mdToken owner;
+ bool first = true;
+
+ HRESULT hr = m_pImport->GetGenericParamProps(tkParam, &ulSeq, &flags, &tkOwner, NULL, paramName, NumItems(paramName), &nameLen);
+ if (FAILED(hr)) Error("GetGenericParamProps failed.", hr);
+
+ VWriteLine("%s\t(%ld) GenericParamToken : (%08x) Name : %ls flags: %08x Owner: %08x", prefix, ulSeq, tkParam, paramName, flags, tkOwner);
+
+ // Any constraints for the GenericParam
+ while (SUCCEEDED(hr = m_pImport->EnumGenericParamConstraints(&constraintEnum, tkParam,
+ constraints, NumItems(constraints), &count)) &&
+ count > 0)
+ {
+ if (first)
+ {
+ m_pImport->CountEnum( constraintEnum, &constraintCount);
+ VWriteLine("%s\t\t%d Constraint(s)", prefix, constraintCount);
+ }
+ VWrite("%s\t\t", prefix);
+ for (ULONG i=0; i< count; ++i)
+ {
+ hr = m_pImport->GetGenericParamConstraintProps(constraints[i], &owner, &constraint);
+ if (owner != tkParam)
+ VWrite("%08x (owner: %08x) ", constraint, owner);
+ else
+ VWrite("%08x ", constraint);
+ }
+ VWriteLine("");
+ }
+ m_pImport->CloseEnum(constraintEnum);
+
+ sprintf_s(newprefix, 30, "%s\t", prefix);
+ DisplayCustomAttributes(tkParam, newprefix);
+}
+
+LPCWSTR MDInfo::TokenName(mdToken inToken, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen)
+{
+ LPCUTF8 pName; // Token name in UTF8.
+
+ if (IsNilToken(inToken))
+ return L"";
+
+ m_pImport->GetNameFromToken(inToken, &pName);
+
+ WszMultiByteToWideChar(CP_UTF8,0, pName,-1, buffer,bufLen);
+
+ return buffer;
+} // LPCWSTR MDInfo::TokenName()
+
+// prints out name of typeref or typedef
+//
+
+LPCWSTR MDInfo::TypeDeforRefName(mdToken inToken, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen)
+{
+ if (RidFromToken(inToken))
+ {
+ if (TypeFromToken(inToken) == mdtTypeDef)
+ return (TypeDefName((mdTypeDef) inToken, buffer, bufLen));
+ else if (TypeFromToken(inToken) == mdtTypeRef)
+ return (TypeRefName((mdTypeRef) inToken, buffer, bufLen));
+ else if (TypeFromToken(inToken) == mdtTypeSpec)
+ return L"[TypeSpec]";
+ else
+ return (L"[InvalidReference]");
+ }
+ else
+ return (L"");
+} // LPCWSTR MDInfo::TypeDeforRefName()
+
+LPCWSTR MDInfo::MemberDeforRefName(mdToken inToken, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen)
+{
+ if (RidFromToken(inToken))
+ {
+ if (TypeFromToken(inToken) == mdtMethodDef || TypeFromToken(inToken) == mdtFieldDef)
+ return (MemberName(inToken, buffer, bufLen));
+ else if (TypeFromToken(inToken) == mdtMemberRef)
+ return (MemberRefName((mdMemberRef) inToken, buffer, bufLen));
+ else
+ return (L"[InvalidReference]");
+ }
+ else
+ return (L"");
+} // LPCWSTR MDInfo::MemberDeforRefName()
+
+// prints out only the name of the given typedef
+//
+//
+
+LPCWSTR MDInfo::TypeDefName(mdTypeDef inTypeDef, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen)
+{
+ HRESULT hr;
+
+ hr = m_pImport->GetTypeDefProps(
+ // [IN] The import scope.
+ inTypeDef, // [IN] TypeDef token for inquiry.
+ buffer, // [OUT] Put name here.
+ bufLen, // [IN] size of name buffer in wide chars.
+ NULL, // [OUT] put size of name (wide chars) here.
+ NULL, // [OUT] Put flags here.
+ NULL); // [OUT] Put base class TypeDef/TypeRef here.
+ if (FAILED(hr))
+ {
+ swprintf_s(buffer, bufLen, L"[Invalid TypeDef]");
+ }
+
+ return buffer;
+} // LPCWSTR MDInfo::TypeDefName()
+
+// prints out all the properties of a given typedef
+//
+
+void MDInfo::DisplayTypeDefProps(mdTypeDef inTypeDef)
+{
+ HRESULT hr;
+ WCHAR typeDefName[STRING_BUFFER_LEN];
+ ULONG nameLen;
+ DWORD flags;
+ mdToken extends;
+ ULONG dwPacking; // Packing size of class, if specified.
+ ULONG dwSize; // Total size of class, if specified.
+
+ hr = m_pImport->GetTypeDefProps(
+ inTypeDef, // [IN] TypeDef token for inquiry.
+ typeDefName, // [OUT] Put name here.
+ STRING_BUFFER_LEN, // [IN] size of name buffer in wide chars.
+ &nameLen, // [OUT] put size of name (wide chars) here.
+ &flags, // [OUT] Put flags here.
+ &extends); // [OUT] Put base class TypeDef/TypeRef here.
+ if (FAILED(hr)) Error("GetTypeDefProps failed.", hr);
+
+ char sFlags[STRING_BUFFER_LEN];
+ WCHAR szTempBuf[STRING_BUFFER_LEN];
+
+ VWriteLine("\tTypDefName: %ls (%8.8X)",typeDefName,inTypeDef);
+ VWriteLine("\tFlags : %s (%08x)",ClassFlags(flags, sFlags), flags);
+ VWriteLine("\tExtends : %8.8X [%s] %ls",extends,TokenTypeName(extends),
+ TypeDeforRefName(extends, szTempBuf, NumItems(szTempBuf)));
+
+ hr = m_pImport->GetClassLayout(inTypeDef, &dwPacking, 0,0,0, &dwSize);
+ if (hr == S_OK)
+ VWriteLine("\tLayout : Packing:%d, Size:%d", dwPacking, dwSize);
+
+ if (IsTdNested(flags))
+ {
+ mdTypeDef tkEnclosingClass;
+
+ hr = m_pImport->GetNestedClassProps(inTypeDef, &tkEnclosingClass);
+ if (hr == S_OK)
+ {
+ VWriteLine("\tEnclosingClass : %ls (%8.8X)", TypeDeforRefName(tkEnclosingClass,
+ szTempBuf, NumItems(szTempBuf)), tkEnclosingClass);
+ }
+ else if (hr == CLDB_E_RECORD_NOTFOUND)
+ WriteLine("ERROR: EnclosingClass not found for NestedClass");
+ else
+ Error("GetNestedClassProps failed.", hr);
+ }
+} // void MDInfo::DisplayTypeDefProps()
+
+// Prints out the name of the given TypeRef
+//
+
+LPCWSTR MDInfo::TypeRefName(mdTypeRef tr, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen)
+{
+ HRESULT hr;
+
+ hr = m_pImport->GetTypeRefProps(
+ tr, // The class ref token.
+ NULL, // Resolution scope.
+ buffer, // Put the name here.
+ bufLen, // Size of the name buffer, wide chars.
+ NULL); // Put actual size of name here.
+ if (FAILED(hr))
+ {
+ swprintf_s(buffer, bufLen, L"[Invalid TypeRef]");
+ }
+
+ return (buffer);
+} // LPCWSTR MDInfo::TypeRefName()
+
+// Prints out all the info of the given TypeRef
+//
+
+void MDInfo::DisplayTypeRefInfo(mdTypeRef tr)
+{
+ HRESULT hr;
+ mdToken tkResolutionScope;
+ WCHAR typeRefName[STRING_BUFFER_LEN];
+ ULONG nameLen;
+
+ hr = m_pImport->GetTypeRefProps(
+ tr, // The class ref token.
+ &tkResolutionScope, // ResolutionScope.
+ typeRefName, // Put the name here.
+ STRING_BUFFER_LEN, // Size of the name buffer, wide chars.
+ &nameLen); // Put actual size of name here.
+
+ if (FAILED(hr)) Error("GetTypeRefProps failed.", hr);
+
+ VWriteLine("Token: 0x%08x", tr);
+ VWriteLine("ResolutionScope: 0x%08x", tkResolutionScope);
+ VWriteLine("TypeRefName: %ls",typeRefName);
+
+ DisplayCustomAttributes(tr, "\t");
+} // void MDInfo::DisplayTypeRefInfo()
+
+
+void MDInfo::DisplayTypeSpecInfo(mdTypeSpec ts, const char *preFix)
+{
+ HRESULT hr;
+ PCCOR_SIGNATURE pvSig;
+ ULONG cbSig;
+ ULONG cb;
+
+ InitSigBuffer();
+
+ hr = m_pImport->GetTypeSpecFromToken(
+ ts, // The class ref token.
+ &pvSig,
+ &cbSig);
+
+ if (FAILED(hr)) Error("GetTypeSpecFromToken failed.", hr);
+
+// DisplaySignature(pvSig, cbSig, preFix);
+
+ if (FAILED(hr = GetOneElementType(pvSig, cbSig, &cb)))
+ goto ErrExit;
+
+ VWriteLine("%s\tTypeSpec :%s", preFix, (LPSTR)m_sigBuf.Ptr());
+
+ // Hex, too?
+ if (m_DumpFilter & dumpMoreHex)
+ {
+ char rcNewPrefix[80];
+ sprintf_s(rcNewPrefix, 80, "%s\tSignature", preFix);
+ DumpHex(rcNewPrefix, pvSig, cbSig, false, 24);
+ }
+ErrExit:
+ return;
+} // void MDInfo::DisplayTypeSpecInfo()
+
+void MDInfo::DisplayMethodSpecInfo(mdMethodSpec ms, const char *preFix)
+{
+ HRESULT hr;
+ PCCOR_SIGNATURE pvSig;
+ ULONG cbSig;
+ mdToken tk;
+
+ InitSigBuffer();
+
+ hr = m_pImport->GetMethodSpecProps(
+ ms, // The MethodSpec token
+ &tk, // The MethodDef or MemberRef
+ &pvSig, // Signature.
+ &cbSig); // Size of signature.
+
+ VWriteLine("%s\tParent : 0x%08x", preFix, tk);
+ DisplaySignature(pvSig, cbSig, preFix);
+//ErrExit:
+ return;
+} // void MDInfo::DisplayMethodSpecInfo()
+
+// Return the passed-in buffer filled with a string detailing the class flags
+// associated with the class.
+//
+
+char *MDInfo::ClassFlags(DWORD flags, __out_ecount(STRING_BUFFER_LEN) char *sFlags)
+{
+ sFlags[0] = 0;
+ ISFLAG(Td, NotPublic);
+ ISFLAG(Td, Public);
+ ISFLAG(Td, NestedPublic);
+ ISFLAG(Td, NestedPrivate);
+ ISFLAG(Td, NestedFamily);
+ ISFLAG(Td, NestedAssembly);
+ ISFLAG(Td, NestedFamANDAssem);
+ ISFLAG(Td, NestedFamORAssem);
+ ISFLAG(Td, AutoLayout);
+ ISFLAG(Td, SequentialLayout);
+ ISFLAG(Td, ExplicitLayout);
+ ISFLAG(Td, Class);
+ ISFLAG(Td, Interface);
+ ISFLAG(Td, Abstract);
+ ISFLAG(Td, Sealed);
+ ISFLAG(Td, SpecialName);
+ ISFLAG(Td, Import);
+ ISFLAG(Td, Serializable);
+ ISFLAG(Td, AnsiClass);
+ ISFLAG(Td, UnicodeClass);
+ ISFLAG(Td, AutoClass);
+ ISFLAG(Td, BeforeFieldInit);
+ ISFLAG(Td, Forwarder);
+ // "Reserved" flags
+ ISFLAG(Td, RTSpecialName);
+ ISFLAG(Td, HasSecurity);
+ ISFLAG(Td, WindowsRuntime);
+ if (!*sFlags)
+ strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
+
+ return sFlags;
+} // char *MDInfo::ClassFlags()
+
+// prints out all info on the given typeDef, including all information that
+// is specific to a given typedef
+//
+
+void MDInfo::DisplayTypeDefInfo(mdTypeDef inTypeDef)
+{
+ DisplayTypeDefProps(inTypeDef);
+
+ // Get field layout information.
+ HRESULT hr = NOERROR;
+ COR_FIELD_OFFSET *rFieldOffset = NULL;
+ ULONG cFieldOffset = 0;
+ hr = m_pImport->GetClassLayout(inTypeDef, NULL, rFieldOffset, 0, &cFieldOffset, NULL);
+ if (SUCCEEDED(hr) && cFieldOffset)
+ {
+ rFieldOffset = new COR_FIELD_OFFSET[cFieldOffset];
+ if (rFieldOffset == NULL)
+ Error("_calloc failed.", E_OUTOFMEMORY);
+ hr = m_pImport->GetClassLayout(inTypeDef, NULL, rFieldOffset, cFieldOffset, &cFieldOffset, NULL);
+ if (FAILED(hr)) { delete [] rFieldOffset; Error("GetClassLayout() failed.", hr); }
+ }
+
+ //No reason to display members if we're displaying fields and methods separately
+ DisplayGenericParams(inTypeDef, "\t");
+ DisplayFields(inTypeDef, rFieldOffset, cFieldOffset);
+ delete [] rFieldOffset;
+ DisplayMethods(inTypeDef);
+ DisplayProperties(inTypeDef);
+ DisplayEvents(inTypeDef);
+ DisplayMethodImpls(inTypeDef);
+ DisplayPermissions(inTypeDef, "");
+
+ DisplayInterfaceImpls(inTypeDef);
+ DisplayCustomAttributes(inTypeDef, "\t");
+} // void MDInfo::DisplayTypeDefInfo()
+
+// print out information about every the given typeDef's interfaceImpls
+//
+
+void MDInfo::DisplayInterfaceImpls(mdTypeDef inTypeDef)
+{
+ HCORENUM interfaceImplEnum = NULL;
+ mdTypeRef interfaceImpls[ENUM_BUFFER_SIZE];
+ ULONG count, totalCount = 1;
+ HRESULT hr;
+
+ while(SUCCEEDED(hr = m_pImport->EnumInterfaceImpls( &interfaceImplEnum,
+ inTypeDef,interfaceImpls,NumItems(interfaceImpls), &count)) &&
+ count > 0)
+ {
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ VWriteLine("\tInterfaceImpl #%d (%08x)", totalCount, interfaceImpls[i]);
+ WriteLine("\t-------------------------------------------------------");
+ DisplayInterfaceImplInfo(interfaceImpls[i]);
+ DisplayPermissions(interfaceImpls[i], "\t");
+ WriteLine("");
+ }
+ }
+ m_pImport->CloseEnum( interfaceImplEnum);
+} // void MDInfo::DisplayInterfaceImpls()
+
+// print the information for the given interface implementation
+//
+
+void MDInfo::DisplayInterfaceImplInfo(mdInterfaceImpl inImpl)
+{
+ mdTypeDef typeDef;
+ mdToken token;
+ HRESULT hr;
+
+ WCHAR szTempBuf[STRING_BUFFER_LEN];
+
+ hr = m_pImport->GetInterfaceImplProps( inImpl, &typeDef, &token);
+ if (FAILED(hr)) Error("GetInterfaceImplProps failed.", hr);
+
+ VWriteLine("\t\tClass : %ls",TypeDeforRefName(typeDef, szTempBuf, NumItems(szTempBuf)));
+ VWriteLine("\t\tToken : %8.8X [%s] %ls",token,TokenTypeName(token), TypeDeforRefName(token, szTempBuf, NumItems(szTempBuf)));
+
+ DisplayCustomAttributes(inImpl, "\t\t");
+} // void MDInfo::DisplayInterfaceImplInfo()
+
+// displays the information for a particular property
+//
+
+void MDInfo::DisplayPropertyInfo(mdProperty inProp)
+{
+ HRESULT hr;
+ mdTypeDef typeDef;
+ WCHAR propName[STRING_BUFFER_LEN];
+ DWORD flags;
+ VARIANT defaultValue;
+ void const *pValue;
+ ULONG cbValue;
+ DWORD dwCPlusTypeFlag;
+ mdMethodDef setter, getter, otherMethod[ENUM_BUFFER_SIZE];
+ ULONG others;
+ PCCOR_SIGNATURE pbSigBlob;
+ ULONG ulSigBlob;
+
+
+ ::VariantInit(&defaultValue);
+
+ hr = m_pImport->GetPropertyProps(
+ inProp, // [IN] property token
+ &typeDef, // [OUT] typedef containing the property declarion.
+
+ propName, // [OUT] Property name
+ STRING_BUFFER_LEN, // [IN] the count of wchar of szProperty
+ NULL, // [OUT] actual count of wchar for property name
+
+ &flags, // [OUT] property flags.
+
+ &pbSigBlob, // [OUT] Signature Blob.
+ &ulSigBlob, // [OUT] Number of bytes in the signature blob.
+
+ &dwCPlusTypeFlag, // [OUT] default value
+ &pValue,
+ &cbValue,
+
+ &setter, // [OUT] setter method of the property
+ &getter, // [OUT] getter method of the property
+
+ otherMethod, // [OUT] other methods of the property
+ ENUM_BUFFER_SIZE, // [IN] size of rmdOtherMethod
+ &others); // [OUT] total number of other method of this property
+
+ if (FAILED(hr)) Error("GetPropertyProps failed.", hr);
+
+ VWriteLine("\t\tProp.Name : %ls (%8.8X)",propName,inProp);
+
+ char sFlags[STRING_BUFFER_LEN];
+
+ sFlags[0] = 0;
+ ISFLAG(Pr, SpecialName);
+ ISFLAG(Pr, RTSpecialName);
+ ISFLAG(Pr, HasDefault);
+ if (!*sFlags)
+ strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
+
+ VWriteLine("\t\tFlags : %s (%08x)", sFlags, flags);
+
+ if (ulSigBlob)
+ DisplaySignature(pbSigBlob, ulSigBlob, "");
+ else
+ VWriteLine("\t\tERROR: no valid signature ");
+
+ WCHAR szTempBuf[STRING_BUFFER_LEN];
+
+ _FillVariant((BYTE)dwCPlusTypeFlag, pValue, cbValue, &defaultValue);
+ VWriteLine("\t\tDefltValue: %ls",VariantAsString(&defaultValue));
+
+ VWriteLine("\t\tSetter : (%08x) %ls",setter,MemberDeforRefName(setter, szTempBuf, NumItems(szTempBuf)));
+ VWriteLine("\t\tGetter : (%08x) %ls",getter,MemberDeforRefName(getter, szTempBuf, NumItems(szTempBuf)));
+
+ // do something with others?
+ VWriteLine("\t\t%ld Others",others);
+ DisplayCustomAttributes(inProp, "\t\t");
+
+ ::VariantClear(&defaultValue);
+} // void MDInfo::DisplayPropertyInfo()
+
+// displays info for each property
+//
+
+void MDInfo::DisplayProperties(mdTypeDef inTypeDef)
+{
+ HCORENUM propEnum = NULL;
+ mdProperty props[ENUM_BUFFER_SIZE];
+ ULONG count, totalCount = 1;
+ HRESULT hr;
+
+
+ while(SUCCEEDED(hr = m_pImport->EnumProperties( &propEnum,
+ inTypeDef,props,NumItems(props), &count)) &&
+ count > 0)
+ {
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ VWriteLine("\tProperty #%d (%08x)", totalCount, props[i]);
+ WriteLine("\t-------------------------------------------------------");
+ DisplayPropertyInfo(props[i]);
+ DisplayPermissions(props[i], "\t");
+ WriteLine("");
+ }
+ }
+ m_pImport->CloseEnum( propEnum);
+} // void MDInfo::DisplayProperties()
+
+// Display all information about a particular event
+//
+
+void MDInfo::DisplayEventInfo(mdEvent inEvent)
+{
+ HRESULT hr;
+ mdTypeDef typeDef;
+ WCHAR eventName[STRING_BUFFER_LEN];
+ DWORD flags;
+ mdToken eventType;
+ mdMethodDef addOn, removeOn, fire, otherMethod[ENUM_BUFFER_SIZE];
+ ULONG totalOther;
+
+
+ hr = m_pImport->GetEventProps(
+ // [IN] The scope.
+ inEvent, // [IN] event token
+ &typeDef, // [OUT] typedef containing the event declarion.
+
+ eventName, // [OUT] Event name
+ STRING_BUFFER_LEN, // [IN] the count of wchar of szEvent
+ NULL, // [OUT] actual count of wchar for event's name
+
+ &flags, // [OUT] Event flags.
+ &eventType, // [OUT] EventType class
+
+ &addOn, // [OUT] AddOn method of the event
+ &removeOn, // [OUT] RemoveOn method of the event
+ &fire, // [OUT] Fire method of the event
+
+ otherMethod, // [OUT] other method of the event
+ NumItems(otherMethod), // [IN] size of rmdOtherMethod
+ &totalOther); // [OUT] total number of other method of this event
+ if (FAILED(hr)) Error("GetEventProps failed.", hr);
+
+ VWriteLine("\t\tName : %ls (%8.8X)",eventName,inEvent);
+
+ char sFlags[STRING_BUFFER_LEN];
+
+ sFlags[0] = 0;
+ ISFLAG(Ev, SpecialName);
+ ISFLAG(Ev, RTSpecialName);
+ if (!*sFlags)
+ strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
+
+ VWriteLine("\t\tFlags : %s (%08x)", sFlags, flags);
+
+ WCHAR szTempBuf[STRING_BUFFER_LEN];
+
+ VWriteLine("\t\tEventType : %8.8X [%s]",eventType,TokenTypeName(eventType));
+ VWriteLine("\t\tAddOnMethd: (%08x) %ls",addOn,MemberDeforRefName(addOn, szTempBuf, NumItems(szTempBuf)));
+ VWriteLine("\t\tRmvOnMethd: (%08x) %ls",removeOn,MemberDeforRefName(removeOn, szTempBuf, NumItems(szTempBuf)));
+ VWriteLine("\t\tFireMethod: (%08x) %ls",fire,MemberDeforRefName(fire, szTempBuf, NumItems(szTempBuf)));
+
+ VWriteLine("\t\t%ld OtherMethods",totalOther);
+
+ DisplayCustomAttributes(inEvent, "\t\t");
+} // void MDInfo::DisplayEventInfo()
+
+// Display information about all events in a typedef
+//
+void MDInfo::DisplayEvents(mdTypeDef inTypeDef)
+{
+ HCORENUM eventEnum = NULL;
+ mdProperty events[ENUM_BUFFER_SIZE];
+ ULONG count, totalCount = 1;
+ HRESULT hr;
+
+
+ while(SUCCEEDED(hr = m_pImport->EnumEvents( &eventEnum,
+ inTypeDef,events,NumItems(events), &count)) &&
+ count > 0)
+ {
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ VWriteLine("\tEvent #%d (%08x)", totalCount, events[i]);
+ WriteLine("\t-------------------------------------------------------");
+ DisplayEventInfo(events[i]);
+ DisplayPermissions(events[i], "\t");
+ WriteLine("");
+ }
+ }
+ m_pImport->CloseEnum( eventEnum);
+} // void MDInfo::DisplayEvents()
+
+
+// print info for the passed-in custom attribute
+// This function is used to print the custom attribute information for both TypeDefs and
+// MethodDefs which need slightly different formatting. preFix helps fix it up.
+//
+
+void MDInfo::DisplayCustomAttributeInfo(mdCustomAttribute inValue, const char *preFix)
+{
+ const BYTE *pValue; // The custom value.
+ ULONG cbValue; // Length of the custom value.
+ HRESULT hr; // A result.
+ mdToken tkObj; // Attributed object.
+ mdToken tkType; // Type of the custom attribute.
+ mdToken tk; // For name lookup.
+ LPCUTF8 pMethName=0; // Name of custom attribute ctor, if any.
+ CQuickBytes qSigName; // Buffer to pretty-print signature.
+ PCCOR_SIGNATURE pSig=0; // Signature of ctor.
+ ULONG cbSig; // Size of the signature.
+ BOOL bCoffSymbol = false; // true for coff symbol CA's.
+ WCHAR rcName[MAX_CLASS_NAME]; // Name of the type.
+
+ hr = m_pImport->GetCustomAttributeProps( // S_OK or error.
+ inValue, // The attribute.
+ &tkObj, // The attributed object
+ &tkType, // The attributes type.
+ (const void**)&pValue, // Put pointer to data here.
+ &cbValue); // Put size here.
+ if (FAILED(hr)) Error("GetCustomAttributeProps failed.", hr);
+
+ VWriteLine("%s\tCustomAttribute Type: %08x", preFix, tkType);
+
+ // Get the name of the memberref or methoddef.
+ tk = tkType;
+ rcName[0] = L'\0';
+ // Get the member name, and the parent token.
+ switch (TypeFromToken(tk))
+ {
+ case mdtMemberRef:
+ hr = m_pImport->GetNameFromToken(tk, &pMethName);
+ if (FAILED(hr)) Error("GetNameFromToken failed.", hr);
+ hr = m_pImport->GetMemberRefProps( tk, &tk, 0, 0, 0, &pSig, &cbSig);
+ if (FAILED(hr)) Error("GetMemberRefProps failed.", hr);
+ break;
+ case mdtMethodDef:
+ hr = m_pImport->GetNameFromToken(tk, &pMethName);
+ if (FAILED(hr)) Error("GetNameFromToken failed.", hr);
+ hr = m_pImport->GetMethodProps(tk, &tk, 0, 0, 0, 0, &pSig, &cbSig, 0, 0);
+ if (FAILED(hr)) Error("GetMethodProps failed.", hr);
+ break;
+ } // switch
+
+ // Get the type name.
+ switch (TypeFromToken(tk))
+ {
+ case mdtTypeDef:
+ hr = m_pImport->GetTypeDefProps(tk, rcName,MAX_CLASS_NAME,0, 0,0);
+ if (FAILED(hr)) Error("GetTypeDefProps failed.", hr);
+ break;
+ case mdtTypeRef:
+ hr = m_pImport->GetTypeRefProps(tk, 0, rcName,MAX_CLASS_NAME,0);
+ if (FAILED(hr)) Error("GetTypeRefProps failed.", hr);
+ break;
+ } // switch
+
+
+ if (pSig && pMethName)
+ {
+ int iLen;
+ LPWSTR pwzName = (LPWSTR)(new WCHAR[iLen= 1+(ULONG32)strlen(pMethName)]);
+ if(pwzName)
+ {
+ WszMultiByteToWideChar(CP_UTF8,0, pMethName,-1, pwzName,iLen);
+ PrettyPrintSigLegacy(pSig, cbSig, pwzName, &qSigName, m_pImport);
+ delete [] pwzName;
+ }
+ }
+
+ VWrite("%s\tCustomAttributeName: %ls", preFix, rcName);
+ if (pSig && pMethName)
+ VWrite(" :: %S", qSigName.Ptr());
+
+ // Keep track of coff overhead.
+ if (!wcscmp(L"__DecoratedName", rcName))
+ {
+ bCoffSymbol = true;
+ g_cbCoffNames += cbValue + 6;
+ }
+ WriteLine("");
+
+ VWriteLine("%s\tLength: %ld", preFix, cbValue);
+ char newPreFix[40];
+ sprintf_s(newPreFix, 40, "%s\tValue ", preFix);
+ DumpHex(newPreFix, pValue, cbValue);
+ if (bCoffSymbol)
+ VWriteLine("%s\t %s", preFix, pValue);
+
+ // Try to decode the constructor blob. This is incomplete, but covers the most popular cases.
+ if (pSig)
+ { // Interpret the signature.
+ PCCOR_SIGNATURE ps = pSig;
+ ULONG cb;
+ ULONG ulData;
+ ULONG cParams;
+ ULONG ulVal;
+ UINT8 u1 = 0;
+ UINT16 u2 = 0;
+ UINT32 u4 = 0;
+ UINT64 u8 = 0;
+ unsigned __int64 uI64;
+ double dblVal;
+ ULONG cbVal;
+ LPCUTF8 pStr;
+ CustomAttributeParser CA(pValue, cbValue);
+ CA.ValidateProlog();
+
+ // Get the calling convention.
+ cb = CorSigUncompressData(ps, &ulData);
+ ps += cb;
+ // Get the count of params.
+ cb = CorSigUncompressData(ps, &cParams);
+ ps += cb;
+ // Get the return value.
+ cb = CorSigUncompressData(ps, &ulData);
+ ps += cb;
+ if (ulData == ELEMENT_TYPE_VOID)
+ {
+ VWrite("%s\tctor args: (", preFix);
+ // For each param...
+ for (ULONG i=0; i<cParams; ++i)
+ { // Get the next param type.
+ cb = CorSigUncompressData(ps, &ulData);
+ ps += cb;
+ if (i) Write(", ");
+ DoObject:
+ switch (ulData)
+ {
+ // For ET_OBJECT, the next byte in the blob is the ET of the actual data.
+ case ELEMENT_TYPE_OBJECT:
+ CA.GetU1(&u1);
+ ulData = u1;
+ goto DoObject;
+ case ELEMENT_TYPE_I1:
+ case ELEMENT_TYPE_U1:
+ CA.GetU1(&u1);
+ ulVal = u1;
+ goto PrintVal;
+ case ELEMENT_TYPE_I2:
+ case ELEMENT_TYPE_U2:
+ CA.GetU2(&u2);
+ ulVal = u2;
+ goto PrintVal;
+ case ELEMENT_TYPE_I4:
+ case ELEMENT_TYPE_U4:
+ CA.GetU4(&u4);
+ ulVal = u4;
+ PrintVal:
+ VWrite("%d", ulVal);
+ break;
+ case ELEMENT_TYPE_STRING:
+ CA.GetString(&pStr, &cbVal);
+ VWrite("\"%s\"", pStr);
+ break;
+ // The only class type that we accept is Type, which is stored as a string.
+ case ELEMENT_TYPE_CLASS:
+ // Eat the class type.
+ cb = CorSigUncompressData(ps, &ulData);
+ ps += cb;
+ // Get the name of the type.
+ CA.GetString(&pStr, &cbVal);
+ VWrite("typeof(%s)", pStr);
+ break;
+ case SERIALIZATION_TYPE_TYPE:
+ CA.GetString(&pStr, &cbVal);
+ VWrite("typeof(%s)", pStr);
+ break;
+ case ELEMENT_TYPE_I8:
+ case ELEMENT_TYPE_U8:
+ CA.GetU8(&u8);
+ uI64 = u8;
+ VWrite("%#lx", uI64);
+ break;
+ case ELEMENT_TYPE_R4:
+ dblVal = CA.GetR4();
+ VWrite("%f", dblVal);
+ break;
+ case ELEMENT_TYPE_R8:
+ dblVal = CA.GetR8();
+ VWrite("%f", dblVal);
+ break;
+ default:
+ // bail...
+ i = cParams;
+ Write(" <can not decode> ");
+ break;
+ }
+ }
+ WriteLine(")");
+ }
+
+ }
+ WriteLine("");
+} // void MDInfo::DisplayCustomAttributeInfo()
+
+// Print all custom values for the given token
+// This function is used to print the custom value information for all tokens.
+// which need slightly different formatting. preFix helps fix it up.
+//
+
+void MDInfo::DisplayCustomAttributes(mdToken inToken, const char *preFix)
+{
+ HCORENUM customAttributeEnum = NULL;
+ mdTypeRef customAttributes[ENUM_BUFFER_SIZE];
+ ULONG count, totalCount = 1;
+ HRESULT hr;
+
+ while(SUCCEEDED(hr = m_pImport->EnumCustomAttributes( &customAttributeEnum, inToken, 0,
+ customAttributes, NumItems(customAttributes), &count)) &&
+ count > 0)
+ {
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ VWriteLine("%sCustomAttribute #%d (%08x)", preFix, totalCount, customAttributes[i]);
+ VWriteLine("%s-------------------------------------------------------", preFix);
+ DisplayCustomAttributeInfo(customAttributes[i], preFix);
+ }
+ }
+ m_pImport->CloseEnum( customAttributeEnum);
+} // void MDInfo::DisplayCustomAttributes()
+
+// Show the passed-in token's permissions
+//
+//
+
+void MDInfo::DisplayPermissions(mdToken tk, const char *preFix)
+{
+ HCORENUM permissionEnum = NULL;
+ mdPermission permissions[ENUM_BUFFER_SIZE];
+ ULONG count, totalCount = 1;
+ HRESULT hr;
+
+
+ while (SUCCEEDED(hr = m_pImport->EnumPermissionSets( &permissionEnum,
+ tk, 0, permissions, NumItems(permissions), &count)) &&
+ count > 0)
+ {
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ VWriteLine("%s\tPermission #%d (%08x)", preFix, totalCount, permissions[i]);
+ VWriteLine("%s\t-------------------------------------------------------", preFix);
+ DisplayPermissionInfo(permissions[i], preFix);
+ WriteLine("");
+ }
+ }
+ m_pImport->CloseEnum( permissionEnum);
+} // void MDInfo::DisplayPermissions()
+
+// print properties of given rolecheck
+//
+//
+
+void MDInfo::DisplayPermissionInfo(mdPermission inPermission, const char *preFix)
+{
+ DWORD dwAction;
+ const BYTE *pvPermission;
+ ULONG cbPermission;
+ char *flagDesc = NULL;
+ char newPreFix[STRING_BUFFER_LEN];
+ HRESULT hr;
+
+
+ hr = m_pImport->GetPermissionSetProps( inPermission, &dwAction,
+ (const void**)&pvPermission, &cbPermission);
+ if (FAILED(hr)) Error("GetPermissionSetProps failed.", hr);
+
+ switch(dwAction)
+ {
+ case dclActionNil: flagDesc = "ActionNil"; break;
+ case dclRequest: flagDesc = "Request"; break;
+ case dclDemand: flagDesc = "Demand"; break;
+ case dclAssert: flagDesc = "Assert"; break;
+ case dclDeny: flagDesc = "Deny"; break;
+ case dclPermitOnly: flagDesc = "PermitOnly"; break;
+ case dclLinktimeCheck: flagDesc = "LinktimeCheck"; break;
+ case dclInheritanceCheck: flagDesc = "InheritanceCheck"; break;
+ case dclRequestMinimum: flagDesc = "RequestMinimum"; break;
+ case dclRequestOptional: flagDesc = "RequestOptional"; break;
+ case dclRequestRefuse: flagDesc = "RequestRefuse"; break;
+ case dclPrejitGrant: flagDesc = "PrejitGrant"; break;
+ case dclPrejitDenied: flagDesc = "PrejitDenied"; break;
+ case dclNonCasDemand: flagDesc = "NonCasDemand"; break;
+ case dclNonCasLinkDemand: flagDesc = "NonCasLinkDemand"; break;
+ case dclNonCasInheritance: flagDesc = "NonCasInheritance"; break;
+
+ }
+ VWriteLine("%s\t\tAction : %s", preFix, flagDesc);
+ VWriteLine("%s\t\tBlobLen : %d", preFix, cbPermission);
+ if (cbPermission)
+ {
+ sprintf_s(newPreFix, STRING_BUFFER_LEN, "%s\tBlob", preFix);
+ DumpHex(newPreFix, pvPermission, cbPermission, false, 24);
+ }
+
+ sprintf_s (newPreFix, STRING_BUFFER_LEN, "\t\t%s", preFix);
+ DisplayCustomAttributes(inPermission, newPreFix);
+} // void MDInfo::DisplayPermissionInfo()
+
+
+// simply prints out the given GUID in standard form
+
+LPWSTR MDInfo::GUIDAsString(GUID inGuid, __out_ecount(bufLen) LPWSTR guidString, ULONG bufLen)
+{
+ StringFromGUID2(inGuid, guidString, bufLen);
+ return guidString;
+} // LPWSTR MDInfo::GUIDAsString()
+
+LPWSTR MDInfo::VariantAsString(VARIANT *pVariant)
+{
+ HRESULT hr = S_OK;
+ if (V_VT(pVariant) == VT_UNKNOWN)
+ {
+ _ASSERTE(V_UNKNOWN(pVariant) == NULL);
+ return (L"<NULL>");
+ }
+ else if (SUCCEEDED(hr = ::VariantChangeType(pVariant, pVariant, 0, VT_BSTR)))
+ return V_BSTR(pVariant);
+ else if (hr == DISP_E_BADVARTYPE && V_VT(pVariant) == VT_I8)
+ {
+ // allocate the bstr.
+ char szStr[32];
+ WCHAR wszStr[32];
+ // Set variant type to bstr.
+ V_VT(pVariant) = VT_BSTR;
+ // Create the ansi string.
+ sprintf_s(szStr, 32, "%I64d", V_CY(pVariant).int64);
+ // Convert to unicode.
+ WszMultiByteToWideChar(CP_ACP, 0, szStr, -1, wszStr, 32);
+ // convert to bstr and set variant value.
+ V_BSTR(pVariant) = ::SysAllocString(wszStr);
+ if (V_BSTR(pVariant) == NULL)
+ Error("SysAllocString() failed.", E_OUTOFMEMORY);
+ return V_BSTR(pVariant);
+ }
+ else
+ return (L"ERROR");
+
+} // LPWSTR MDInfo::VariantAsString()
+
+bool TrySigUncompress(PCCOR_SIGNATURE pData, // [IN] compressed data
+ ULONG *pDataOut, // [OUT] the expanded *pData
+ ULONG *cbCur)
+{
+ ULONG ulSize = CorSigUncompressData(pData, pDataOut);
+ if (ulSize == (ULONG)-1)
+ {
+ *cbCur = ulSize;
+ return false;
+ } else
+ {
+ *cbCur += ulSize;
+ return true;
+ }
+}
+
+void MDInfo::DisplayFieldMarshal(mdToken inToken)
+{
+ PCCOR_SIGNATURE pvNativeType; // [OUT] native type of this field
+ ULONG cbNativeType; // [OUT] the count of bytes of *ppvNativeType
+ HRESULT hr;
+
+
+ hr = m_pImport->GetFieldMarshal( inToken, &pvNativeType, &cbNativeType);
+ if (FAILED(hr) && hr != CLDB_E_RECORD_NOTFOUND) Error("GetFieldMarshal failed.", hr);
+ if (hr != CLDB_E_RECORD_NOTFOUND)
+ {
+ ULONG cbCur = 0;
+ ULONG ulData;
+ ULONG ulStrLoc;
+
+ char szNTDesc[STRING_BUFFER_LEN];
+
+ while (cbCur < cbNativeType)
+ {
+ ulStrLoc = 0;
+
+ ulData = NATIVE_TYPE_MAX;
+ if (!TrySigUncompress(&pvNativeType[cbCur], &ulData, &cbCur))
+ continue;
+ if (ulData >= sizeof(g_szNativeType)/sizeof(*g_szNativeType))
+ {
+ cbCur = (ULONG)-1;
+ continue;
+ }
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "%s ", g_szNativeType[ulData]);
+ switch (ulData)
+ {
+ case NATIVE_TYPE_FIXEDSYSSTRING:
+ {
+ if (cbCur < cbNativeType)
+ {
+ if (!TrySigUncompress(&pvNativeType[cbCur], &ulData, &cbCur))
+ continue;
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "{StringElementCount: %d} ",ulData);
+ }
+ }
+ break;
+ case NATIVE_TYPE_FIXEDARRAY:
+ {
+ if (cbCur < cbNativeType)
+ {
+ if (!TrySigUncompress(&pvNativeType[cbCur], &ulData, &cbCur))
+ continue;
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "{ArrayElementCount: %d",ulData);
+
+ if (cbCur < cbNativeType)
+ {
+ if (!TrySigUncompress(&pvNativeType[cbCur], &ulData, &cbCur))
+ continue;
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, ", ArrayElementType(NT): %d",ulData);
+ }
+
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc,"}");
+ }
+ }
+ break;
+ case NATIVE_TYPE_ARRAY:
+ {
+ if (cbCur < cbNativeType)
+ {
+ BOOL bElemTypeSpecified;
+
+ if (!TrySigUncompress(&pvNativeType[cbCur], &ulData, &cbCur))
+ continue;
+ if (ulData != NATIVE_TYPE_MAX)
+ {
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "{ArrayElementType(NT): %d", ulData);
+ bElemTypeSpecified = TRUE;
+ }
+ else
+ {
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "{");
+ bElemTypeSpecified = FALSE;
+ }
+
+ if (cbCur < cbNativeType)
+ {
+ if (bElemTypeSpecified)
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, ", ");
+
+ if (!TrySigUncompress(&pvNativeType[cbCur], &ulData, &cbCur))
+ continue;
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "SizeParamIndex: %d",ulData);
+
+ if (cbCur < cbNativeType)
+ {
+ if (!TrySigUncompress(&pvNativeType[cbCur], &ulData, &cbCur))
+ continue;
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, ", SizeParamMultiplier: %d",ulData);
+
+ if (cbCur < cbNativeType)
+ {
+ if (!TrySigUncompress(&pvNativeType[cbCur], &ulData, &cbCur))
+ continue;
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, ", SizeConst: %d",ulData);
+ }
+ }
+ }
+
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "}");
+ }
+ }
+ break;
+ case NATIVE_TYPE_SAFEARRAY:
+ {
+ if (cbCur < cbNativeType)
+ {
+ if (!TrySigUncompress(&pvNativeType[cbCur], &ulData, &cbCur))
+ continue;
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "{SafeArraySubType(VT): %d, ",ulData);
+
+ // Extract the element type name if it is specified.
+ if (cbCur < cbNativeType)
+ {
+ LPUTF8 strTemp = NULL;
+ int strLen = 0;
+ int ByteCountLength = 0;
+
+ strLen = CPackedLen::GetLength(&pvNativeType[cbCur], &ByteCountLength);
+ cbCur += ByteCountLength;
+ strTemp = (LPUTF8)(new char[strLen + 1]);
+ if(strTemp)
+ {
+ memcpy(strTemp, (LPUTF8)&pvNativeType[cbCur], strLen);
+ strTemp[strLen] = 0;
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "ElementTypeName: %s}", strTemp);
+ cbCur += strLen;
+ _ASSERTE(cbCur == cbNativeType);
+ delete [] strTemp;
+ }
+ }
+ else
+ {
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "ElementTypeName: }");
+ }
+ }
+ }
+ break;
+ case NATIVE_TYPE_CUSTOMMARSHALER:
+ {
+ LPUTF8 strTemp = NULL;
+ int strLen = 0;
+ int ByteCountLength = 0;
+
+ // Extract the typelib GUID.
+ strLen = CPackedLen::GetLength(&pvNativeType[cbCur], &ByteCountLength);
+ cbCur += ByteCountLength;
+ strTemp = (LPUTF8)(new char[strLen + 1]);
+ if(strTemp)
+ {
+ memcpy(strTemp, (LPUTF8)&pvNativeType[cbCur], strLen);
+ strTemp[strLen] = 0;
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "{Typelib: %s, ", strTemp);
+ cbCur += strLen;
+ _ASSERTE(cbCur < cbNativeType);
+ delete [] strTemp;
+ }
+ // Extract the name of the native type.
+ strLen = CPackedLen::GetLength(&pvNativeType[cbCur], &ByteCountLength);
+ cbCur += ByteCountLength;
+ strTemp = (LPUTF8)(new char[strLen + 1]);
+ if(strTemp)
+ {
+ memcpy(strTemp, (LPUTF8)&pvNativeType[cbCur], strLen);
+ strTemp[strLen] = 0;
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "Native: %s, ", strTemp);
+ cbCur += strLen;
+ _ASSERTE(cbCur < cbNativeType);
+ delete [] strTemp;
+ }
+
+ // Extract the name of the custom marshaler.
+ strLen = CPackedLen::GetLength(&pvNativeType[cbCur], &ByteCountLength);
+ cbCur += ByteCountLength;
+ strTemp = (LPUTF8)(new char[strLen + 1]);
+ if(strTemp)
+ {
+ memcpy(strTemp, (LPUTF8)&pvNativeType[cbCur], strLen);
+ strTemp[strLen] = 0;
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "Marshaler: %s, ", strTemp);
+ cbCur += strLen;
+ _ASSERTE(cbCur < cbNativeType);
+ delete [] strTemp;
+ }
+ // Extract the cookie string.
+ strLen = CPackedLen::GetLength(&pvNativeType[cbCur], &ByteCountLength);
+ cbCur += ByteCountLength;
+ if (strLen > 0)
+ {
+ strTemp = (LPUTF8)(new char[strLen + 1]);
+ if(strTemp)
+ {
+ memcpy(strTemp, (LPUTF8)&pvNativeType[cbCur], strLen);
+ strTemp[strLen] = 0;
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "Cookie: ");
+
+ // Copy the cookie string and transform the embedded nulls into \0's.
+ for (int i = 0; i < strLen - 1; i++, cbCur++)
+ {
+ if (strTemp[i] == 0)
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "\\0");
+ else
+ szNTDesc[ulStrLoc++] = strTemp[i];
+ }
+ szNTDesc[ulStrLoc++] = strTemp[strLen - 1];
+ cbCur++;
+ delete [] strTemp;
+ }
+ }
+ else
+ {
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "Cookie: ");
+ }
+
+ // Finish the custom marshaler native type description.
+ ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "}");
+ _ASSERTE(cbCur <= cbNativeType);
+ }
+ break;
+ default:
+ {
+ // normal nativetype element: do nothing
+ }
+ }
+ VWriteLine("\t\t\t\t%s",szNTDesc);
+ if (ulData >= NATIVE_TYPE_MAX)
+ break;
+ }
+ if (cbCur == (ULONG)-1)
+ {
+ // There was something that we didn't grok in the signature.
+ // Just dump out the blob as hex
+ VWrite("\t\t\t\t{", szNTDesc);
+ while (cbNativeType--)
+ VWrite(" %2.2X", *pvNativeType++);
+ VWriteLine(" }");
+ }
+ }
+} // void MDInfo::DisplayFieldMarshal()
+
+void MDInfo::DisplayPinvokeInfo(mdToken inToken)
+{
+ HRESULT hr = NOERROR;
+ DWORD flags;
+ WCHAR rcImport[512];
+ mdModuleRef tkModuleRef;
+
+ char sFlags[STRING_BUFFER_LEN];
+
+ hr = m_pImport->GetPinvokeMap(inToken, &flags, rcImport,
+ NumItems(rcImport), 0, &tkModuleRef);
+ if (FAILED(hr))
+ {
+ if (hr != CLDB_E_RECORD_NOTFOUND)
+ VWriteLine("ERROR: GetPinvokeMap failed.", hr);
+ return;
+ }
+
+ WriteLine("\t\tPinvoke Map Data:");
+ VWriteLine("\t\tEntry point: %S", rcImport);
+ VWriteLine("\t\tModule ref: %08x", tkModuleRef);
+
+ sFlags[0] = 0;
+ ISFLAG(Pm, NoMangle);
+ ISFLAG(Pm, CharSetNotSpec);
+ ISFLAG(Pm, CharSetAnsi);
+ ISFLAG(Pm, CharSetUnicode);
+ ISFLAG(Pm, CharSetAuto);
+ ISFLAG(Pm, SupportsLastError);
+ ISFLAG(Pm, CallConvWinapi);
+ ISFLAG(Pm, CallConvCdecl);
+ ISFLAG(Pm, CallConvStdcall);
+ ISFLAG(Pm, CallConvThiscall);
+ ISFLAG(Pm, CallConvFastcall);
+
+ ISFLAG(Pm, BestFitEnabled);
+ ISFLAG(Pm, BestFitDisabled);
+ ISFLAG(Pm, BestFitUseAssem);
+ ISFLAG(Pm, ThrowOnUnmappableCharEnabled);
+ ISFLAG(Pm, ThrowOnUnmappableCharDisabled);
+ ISFLAG(Pm, ThrowOnUnmappableCharUseAssem);
+ if (!*sFlags)
+ strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
+
+ VWriteLine("\t\tMapping flags: %s (%08x)", sFlags, flags);
+} // void MDInfo::DisplayPinvokeInfo()
+
+
+/////////////////////////////////////////////////////////////////////////
+// void DisplaySignature(PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob);
+//
+// Display COM+ signature -- taken from cordump.cpp's DumpSignature
+/////////////////////////////////////////////////////////////////////////
+void MDInfo::DisplaySignature(PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob, const char *preFix)
+{
+ ULONG cbCur = 0;
+ ULONG cb;
+ // 428793: Prefix complained correctly about unitialized data.
+ ULONG ulData = (ULONG) IMAGE_CEE_CS_CALLCONV_MAX;
+ ULONG ulArgs;
+ HRESULT hr = NOERROR;
+ ULONG ulSigBlobStart = ulSigBlob;
+
+ // initialize sigBuf
+ InitSigBuffer();
+
+ cb = CorSigUncompressData(pbSigBlob, &ulData);
+ VWriteLine("%s\t\tCallCnvntn: %s", preFix, (g_strCalling[ulData & IMAGE_CEE_CS_CALLCONV_MASK]));
+ if (cb>ulSigBlob)
+ goto ErrExit;
+ cbCur += cb;
+ ulSigBlob -= cb;
+
+ if (ulData & IMAGE_CEE_CS_CALLCONV_HASTHIS)
+ VWriteLine("%s\t\thasThis ", preFix);
+ if (ulData & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS)
+ VWriteLine("%s\t\texplicit ", preFix);
+ if (ulData & IMAGE_CEE_CS_CALLCONV_GENERIC)
+ VWriteLine("%s\t\tgeneric ", preFix);
+
+ // initialize sigBuf
+ InitSigBuffer();
+ if ( isCallConv(ulData,IMAGE_CEE_CS_CALLCONV_FIELD) )
+ {
+
+ // display field type
+ if (FAILED(hr = GetOneElementType(&pbSigBlob[cbCur], ulSigBlob, &cb)))
+ goto ErrExit;
+ VWriteLine("%s\t\tField type: %s", preFix, (LPSTR)m_sigBuf.Ptr());
+ if (cb>ulSigBlob)
+ goto ErrExit;
+ cbCur += cb;
+ ulSigBlob -= cb;
+ }
+ else
+ {
+ if (ulData & IMAGE_CEE_CS_CALLCONV_GENERIC)
+ {
+ ULONG ulTyArgs;
+ cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulTyArgs);
+ if (cb>ulSigBlob)
+ goto ErrExit;
+ cbCur += cb;
+ ulSigBlob -= cb;
+ VWriteLine("%s\t\tType Arity:%d ", preFix, ulTyArgs);
+ }
+ cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulArgs);
+ if (cb>ulSigBlob)
+ goto ErrExit;
+ cbCur += cb;
+ ulSigBlob -= cb;
+
+ if (ulData != IMAGE_CEE_CS_CALLCONV_LOCAL_SIG && ulData != IMAGE_CEE_CS_CALLCONV_GENERICINST)
+ {
+ // display return type when it is not a local varsig
+ if (FAILED(hr = GetOneElementType(&pbSigBlob[cbCur], ulSigBlob, &cb)))
+ goto ErrExit;
+ VWriteLine("%s\t\tReturnType:%s", preFix, (LPSTR)m_sigBuf.Ptr());
+ if (cb>ulSigBlob)
+ goto ErrExit;
+ cbCur += cb;
+ ulSigBlob -= cb;
+ }
+
+ // display count of argument
+ // display arguments
+ if (ulSigBlob)
+ VWriteLine("%s\t\t%ld Arguments", preFix, ulArgs);
+ else
+ VWriteLine("%s\t\tNo arguments.", preFix);
+
+ ULONG i = 0;
+ while (i < ulArgs && ulSigBlob > 0)
+ {
+ ULONG ulDataTemp;
+
+ // Handle the sentinal for varargs because it isn't counted in the args.
+ CorSigUncompressData(&pbSigBlob[cbCur], &ulDataTemp);
+ ++i;
+
+ // initialize sigBuf
+ InitSigBuffer();
+
+ if (FAILED(hr = GetOneElementType(&pbSigBlob[cbCur], ulSigBlob, &cb)))
+ goto ErrExit;
+
+ VWriteLine("%s\t\t\tArgument #%ld: %s",preFix, i, (LPSTR)m_sigBuf.Ptr());
+
+ if (cb>ulSigBlob)
+ goto ErrExit;
+
+ cbCur += cb;
+ ulSigBlob -= cb;
+ }
+ }
+
+ // Nothing consumed but not yet counted.
+ cb = 0;
+
+ErrExit:
+ // We should have consumed all signature blob. If not, dump the sig in hex.
+ // Also dump in hex if so requested.
+ if (m_DumpFilter & dumpMoreHex || ulSigBlob != 0)
+ {
+ // Did we not consume enough, or try to consume too much?
+ if (cb > ulSigBlob)
+ WriteLine("\tERROR IN SIGNATURE: Signature should be larger.");
+ else
+ if (cb < ulSigBlob)
+ {
+ VWrite("\tERROR IN SIGNATURE: Not all of signature blob was consumed. %d byte(s) remain", ulSigBlob);
+ // If it is short, just append it to the end.
+ if (ulSigBlob < 4)
+ {
+ Write(": ");
+ for (; ulSigBlob; ++cbCur, --ulSigBlob)
+ VWrite("%02x ", pbSigBlob[cbCur]);
+ WriteLine("");
+ goto ErrExit2;
+ }
+ WriteLine("");
+ }
+
+ // Any appropriate error message has been issued. Dump sig in hex, as determined
+ // by error or command line switch.
+ cbCur = 0;
+ ulSigBlob = ulSigBlobStart;
+ char rcNewPrefix[80];
+ sprintf_s(rcNewPrefix, 80, "%s\t\tSignature ", preFix);
+ DumpHex(rcNewPrefix, pbSigBlob, ulSigBlob, false, 24);
+ }
+ErrExit2:
+ if (FAILED(hr))
+ Error("ERROR!! Bad signature blob value!");
+ return;
+} // void MDInfo::DisplaySignature()
+
+
+/////////////////////////////////////////////////////////////////////////
+// HRESULT GetOneElementType(mdScope tkScope, BYTE *pbSigBlob, ULONG ulSigBlob, ULONG *pcb)
+//
+// Adds description of element type to the end of buffer -- caller must ensure
+// buffer is large enough.
+/////////////////////////////////////////////////////////////////////////
+HRESULT MDInfo::GetOneElementType(PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob, ULONG *pcb)
+{
+ HRESULT hr = S_OK; // A result.
+ ULONG cbCur = 0;
+ ULONG cb;
+ ULONG ulData = ELEMENT_TYPE_MAX;
+ ULONG ulTemp;
+ int iTemp = 0;
+ mdToken tk;
+
+ cb = CorSigUncompressData(pbSigBlob, &ulData);
+ cbCur += cb;
+
+ // Handle the modifiers.
+ if (ulData & ELEMENT_TYPE_MODIFIER)
+ {
+ if (ulData == ELEMENT_TYPE_SENTINEL)
+ IfFailGo(AddToSigBuffer("<ELEMENT_TYPE_SENTINEL>"));
+ else if (ulData == ELEMENT_TYPE_PINNED)
+ IfFailGo(AddToSigBuffer("PINNED"));
+ else
+ {
+ hr = E_FAIL;
+ goto ErrExit;
+ }
+ if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
+ goto ErrExit;
+ cbCur += cb;
+ goto ErrExit;
+ }
+
+ // Handle the underlying element types.
+ if (ulData >= ELEMENT_TYPE_MAX)
+ {
+ hr = E_FAIL;
+ goto ErrExit;
+ }
+ while (ulData == ELEMENT_TYPE_PTR || ulData == ELEMENT_TYPE_BYREF)
+ {
+ IfFailGo(AddToSigBuffer(" "));
+ IfFailGo(AddToSigBuffer(g_szMapElementType[ulData]));
+ cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
+ cbCur += cb;
+ }
+ IfFailGo(AddToSigBuffer(" "));
+ IfFailGo(AddToSigBuffer(g_szMapElementType[ulData]));
+ if (CorIsPrimitiveType((CorElementType)ulData) ||
+ ulData == ELEMENT_TYPE_TYPEDBYREF ||
+ ulData == ELEMENT_TYPE_OBJECT ||
+ ulData == ELEMENT_TYPE_I ||
+ ulData == ELEMENT_TYPE_U)
+ {
+ // If this is a primitive type, we are done
+ goto ErrExit;
+ }
+ if (ulData == ELEMENT_TYPE_VALUETYPE ||
+ ulData == ELEMENT_TYPE_CLASS ||
+ ulData == ELEMENT_TYPE_CMOD_REQD ||
+ ulData == ELEMENT_TYPE_CMOD_OPT)
+ {
+ cb = CorSigUncompressToken(&pbSigBlob[cbCur], &tk);
+ cbCur += cb;
+
+ // get the name of type ref. Don't care if truncated
+ if (TypeFromToken(tk) == mdtTypeDef || TypeFromToken(tk) == mdtTypeRef)
+ {
+ sprintf_s(m_tempFormatBuffer, STRING_BUFFER_LEN, " %ls",TypeDeforRefName(tk, m_szTempBuf, NumItems(m_szTempBuf)));
+ IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
+ }
+ else
+ {
+ _ASSERTE(TypeFromToken(tk) == mdtTypeSpec);
+ sprintf_s(m_tempFormatBuffer, STRING_BUFFER_LEN, " %8x", tk);
+ IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
+ }
+ if (ulData == ELEMENT_TYPE_CMOD_REQD ||
+ ulData == ELEMENT_TYPE_CMOD_OPT)
+ {
+ if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
+ goto ErrExit;
+ cbCur += cb;
+ }
+
+ goto ErrExit;
+ }
+ if (ulData == ELEMENT_TYPE_SZARRAY)
+ {
+ // display the base type of SZARRAY
+ if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
+ goto ErrExit;
+ cbCur += cb;
+ goto ErrExit;
+ }
+ // instantiated type
+ if (ulData == ELEMENT_TYPE_GENERICINST)
+ {
+ // display the type constructor
+ if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
+ goto ErrExit;
+ cbCur += cb;
+ ULONG numArgs;
+ cb = CorSigUncompressData(&pbSigBlob[cbCur], &numArgs);
+ cbCur += cb;
+ IfFailGo(AddToSigBuffer("<"));
+
+ while (numArgs > 0)
+ {
+ if (cbCur > ulSigBlob)
+ goto ErrExit;
+ if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
+ goto ErrExit;
+ cbCur += cb;
+ --numArgs;
+ if (numArgs > 0)
+ IfFailGo(AddToSigBuffer(","));
+ }
+ IfFailGo(AddToSigBuffer(">"));
+ goto ErrExit;
+ }
+ if (ulData == ELEMENT_TYPE_VAR)
+ {
+ ULONG index;
+ cb = CorSigUncompressData(&pbSigBlob[cbCur], &index);
+ cbCur += cb;
+ sprintf_s(m_tempFormatBuffer, STRING_BUFFER_LEN, "!%d", index);
+ IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
+ goto ErrExit;
+ }
+ if (ulData == ELEMENT_TYPE_MVAR)
+ {
+ ULONG index;
+ cb = CorSigUncompressData(&pbSigBlob[cbCur], &index);
+ cbCur += cb;
+ sprintf_s(m_tempFormatBuffer, STRING_BUFFER_LEN, "!!%d", index);
+ IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
+ goto ErrExit;
+ }
+ if (ulData == ELEMENT_TYPE_FNPTR)
+ {
+ cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
+ cbCur += cb;
+ if (ulData & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS)
+ IfFailGo(AddToSigBuffer(" explicit"));
+ if (ulData & IMAGE_CEE_CS_CALLCONV_HASTHIS)
+ IfFailGo(AddToSigBuffer(" hasThis"));
+
+ IfFailGo(AddToSigBuffer(" "));
+ IfFailGo(AddToSigBuffer(g_strCalling[ulData & IMAGE_CEE_CS_CALLCONV_MASK]));
+
+ // Get number of args
+ ULONG numArgs;
+ cb = CorSigUncompressData(&pbSigBlob[cbCur], &numArgs);
+ cbCur += cb;
+
+ // do return type
+ if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
+ goto ErrExit;
+ cbCur += cb;
+
+ IfFailGo(AddToSigBuffer("("));
+ while (numArgs > 0)
+ {
+ if (cbCur > ulSigBlob)
+ goto ErrExit;
+ if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
+ goto ErrExit;
+ cbCur += cb;
+ --numArgs;
+ if (numArgs > 0)
+ IfFailGo(AddToSigBuffer(","));
+ }
+ IfFailGo(AddToSigBuffer(" )"));
+ goto ErrExit;
+ }
+
+ if(ulData != ELEMENT_TYPE_ARRAY) return E_FAIL;
+
+ // display the base type of SDARRAY
+ if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
+ goto ErrExit;
+ cbCur += cb;
+
+ // display the rank of MDARRAY
+ cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
+ cbCur += cb;
+ sprintf_s(m_tempFormatBuffer, STRING_BUFFER_LEN, " %d", ulData);
+ IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
+ if (ulData == 0)
+ // we are done if no rank specified
+ goto ErrExit;
+
+ // how many dimensions have size specified?
+ cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
+ cbCur += cb;
+ sprintf_s(m_tempFormatBuffer, STRING_BUFFER_LEN, " %d", ulData);
+ IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
+ while (ulData)
+ {
+ cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulTemp);
+ sprintf_s(m_tempFormatBuffer, STRING_BUFFER_LEN, " %d", ulTemp);
+ IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
+ cbCur += cb;
+ ulData--;
+ }
+ // how many dimensions have lower bounds specified?
+ cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
+ cbCur += cb;
+ sprintf_s(m_tempFormatBuffer, STRING_BUFFER_LEN, " %d", ulData);
+ IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
+ while (ulData)
+ {
+
+ cb = CorSigUncompressSignedInt(&pbSigBlob[cbCur], &iTemp);
+ sprintf_s(m_tempFormatBuffer, STRING_BUFFER_LEN, " %d", iTemp);
+ IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
+ cbCur += cb;
+ ulData--;
+ }
+
+ErrExit:
+ if (cbCur > ulSigBlob)
+ hr = E_FAIL;
+ *pcb = cbCur;
+ return hr;
+} // HRESULT MDInfo::GetOneElementType()
+
+// Display the fields of the N/Direct custom value structure.
+
+void MDInfo::DisplayCorNativeLink(COR_NATIVE_LINK *pCorNLnk, const char *preFix)
+{
+ // Print the LinkType.
+ char *curField = "\tLink Type : ";
+ switch(pCorNLnk->m_linkType)
+ {
+ case nltNone:
+ VWriteLine("%s%s%s(%02x)", preFix, curField, "nltNone", pCorNLnk->m_linkType);
+ break;
+ case nltAnsi:
+ VWriteLine("%s%s%s(%02x)", preFix, curField, "nltAnsi", pCorNLnk->m_linkType);
+ break;
+ case nltUnicode:
+ VWriteLine("%s%s%s(%02x)", preFix, curField, "nltUnicode", pCorNLnk->m_linkType);
+ break;
+ case nltAuto:
+ VWriteLine("%s%s%s(%02x)", preFix, curField, "nltAuto", pCorNLnk->m_linkType);
+ break;
+ default:
+ _ASSERTE(!"Invalid Native Link Type!");
+ }
+
+ // Print the link flags
+ curField = "\tLink Flags : ";
+ switch(pCorNLnk->m_flags)
+ {
+ case nlfNone:
+ VWriteLine("%s%s%s(%02x)", preFix, curField, "nlfNone", pCorNLnk->m_flags);
+ break;
+ case nlfLastError:
+ VWriteLine("%s%s%s(%02x)", preFix, curField, "nlfLastError", pCorNLnk->m_flags);
+ break;
+ default:
+ _ASSERTE(!"Invalid Native Link Flags!");
+ }
+
+ // Print the entry point.
+ WCHAR memRefName[STRING_BUFFER_LEN];
+ HRESULT hr;
+ hr = m_pImport->GetMemberRefProps( pCorNLnk->m_entryPoint, NULL, memRefName,
+ STRING_BUFFER_LEN, NULL, NULL, NULL);
+ if (FAILED(hr)) Error("GetMemberRefProps failed.", hr);
+ VWriteLine("%s\tEntry Point : %ls (0x%08x)", preFix, memRefName, pCorNLnk->m_entryPoint);
+} // void MDInfo::DisplayCorNativeLink()
+
+// Fills given varaint with value given in pValue and of type in bCPlusTypeFlag
+//
+// Taken from MetaInternal.cpp
+
+HRESULT _FillVariant(
+ BYTE bCPlusTypeFlag,
+ const void *pValue,
+ ULONG cbValue,
+ VARIANT *pvar)
+{
+ HRESULT hr = NOERROR;
+ switch (bCPlusTypeFlag)
+ {
+ case ELEMENT_TYPE_BOOLEAN:
+ V_VT(pvar) = VT_BOOL;
+ V_BOOL(pvar) = *((BYTE*)pValue); //*((UNALIGNED VARIANT_BOOL *)pValue);
+ break;
+ case ELEMENT_TYPE_I1:
+ V_VT(pvar) = VT_I1;
+ V_I1(pvar) = *((CHAR*)pValue);
+ break;
+ case ELEMENT_TYPE_U1:
+ V_VT(pvar) = VT_UI1;
+ V_UI1(pvar) = *((BYTE*)pValue);
+ break;
+ case ELEMENT_TYPE_I2:
+ V_VT(pvar) = VT_I2;
+ V_I2(pvar) = GET_UNALIGNED_VAL16(pValue);
+ break;
+ case ELEMENT_TYPE_U2:
+ case ELEMENT_TYPE_CHAR:
+ V_VT(pvar) = VT_UI2;
+ V_UI2(pvar) = GET_UNALIGNED_VAL16(pValue);
+ break;
+ case ELEMENT_TYPE_I4:
+ V_VT(pvar) = VT_I4;
+ V_I4(pvar) = GET_UNALIGNED_VAL32(pValue);
+ break;
+ case ELEMENT_TYPE_U4:
+ V_VT(pvar) = VT_UI4;
+ V_UI4(pvar) = GET_UNALIGNED_VAL32(pValue);
+ break;
+ case ELEMENT_TYPE_R4:
+ {
+ V_VT(pvar) = VT_R4;
+ __int32 Value = GET_UNALIGNED_VAL32(pValue);
+ V_R4(pvar) = (float &)Value;
+ }
+ break;
+ case ELEMENT_TYPE_R8:
+ {
+ V_VT(pvar) = VT_R8;
+ __int64 Value = GET_UNALIGNED_VAL64(pValue);
+ V_R8(pvar) = (double &) Value;
+ }
+
+ break;
+ case ELEMENT_TYPE_STRING:
+ {
+ V_VT(pvar) = VT_BSTR;
+ WCHAR *TempString;;
+#if BIGENDIAN
+ TempString = (WCHAR *)alloca(cbValue);
+ memcpy(TempString, pValue, cbValue);
+ SwapStringLength(TempString, cbValue/sizeof(WCHAR));
+#else
+ TempString = (WCHAR *)pValue;
+#endif
+ // allocated bstr here
+ V_BSTR(pvar) = ::SysAllocStringLen((LPWSTR)TempString, cbValue/sizeof(WCHAR));
+ if (V_BSTR(pvar) == NULL)
+ hr = E_OUTOFMEMORY;
+ }
+ break;
+ case ELEMENT_TYPE_CLASS:
+ V_VT(pvar) = VT_UNKNOWN;
+ V_UNKNOWN(pvar) = NULL;
+ // _ASSERTE( GET_UNALIGNED_VAL32(pValue) == 0);
+ break;
+ case ELEMENT_TYPE_I8:
+ V_VT(pvar) = VT_I8;
+ V_CY(pvar).int64 = GET_UNALIGNED_VAL64(pValue);
+ break;
+ case ELEMENT_TYPE_U8:
+ V_VT(pvar) = VT_UI8;
+ V_CY(pvar).int64 = GET_UNALIGNED_VAL64(pValue);
+ break;
+ case ELEMENT_TYPE_VOID:
+ V_VT(pvar) = VT_EMPTY;
+ break;
+ default:
+ _ASSERTE(!"bad constant value type!");
+ }
+
+ return hr;
+} // HRESULT _FillVariant()
+
+void MDInfo::DisplayAssembly()
+{
+ if (m_pAssemblyImport)
+ {
+ DisplayAssemblyInfo();
+ DisplayAssemblyRefs();
+ DisplayFiles();
+ DisplayExportedTypes();
+ DisplayManifestResources();
+ }
+} // void MDInfo::DisplayAssembly()
+
+void MDInfo::DisplayAssemblyInfo()
+{
+ HRESULT hr;
+ mdAssembly mda;
+ const BYTE *pbPublicKey;
+ ULONG cbPublicKey;
+ ULONG ulHashAlgId;
+ WCHAR szName[STRING_BUFFER_LEN];
+ ASSEMBLYMETADATA MetaData;
+ DWORD dwFlags;
+
+ hr = m_pAssemblyImport->GetAssemblyFromScope(&mda);
+ if (hr == CLDB_E_RECORD_NOTFOUND)
+ return;
+ else if (FAILED(hr)) Error("GetAssemblyFromScope() failed.", hr);
+
+ // Get the required sizes for the arrays of locales, processors etc.
+ ZeroMemory(&MetaData, sizeof(ASSEMBLYMETADATA));
+ hr = m_pAssemblyImport->GetAssemblyProps(mda,
+ NULL, NULL, // Public Key.
+ NULL, // Hash Algorithm.
+ NULL, 0, NULL, // Name.
+ &MetaData,
+ NULL); // Flags.
+ if (FAILED(hr)) Error("GetAssemblyProps() failed.", hr);
+
+ // Allocate space for the arrays in the ASSEMBLYMETADATA structure.
+ if (MetaData.cbLocale)
+ MetaData.szLocale = new WCHAR[MetaData.cbLocale];
+ if (MetaData.ulProcessor)
+ MetaData.rProcessor = new DWORD[MetaData.ulProcessor];
+ if (MetaData.ulOS)
+ MetaData.rOS = new OSINFO[MetaData.ulOS];
+
+ hr = m_pAssemblyImport->GetAssemblyProps(mda,
+ (const void **)&pbPublicKey, &cbPublicKey,
+ &ulHashAlgId,
+ szName, STRING_BUFFER_LEN, NULL,
+ &MetaData,
+ &dwFlags);
+ if (FAILED(hr)) Error("GetAssemblyProps() failed.", hr);
+ WriteLine("Assembly");
+ WriteLine("-------------------------------------------------------");
+ VWriteLine("\tToken: 0x%08x", mda);
+ VWriteLine("\tName : %ls", szName);
+ DumpHex("\tPublic Key ", pbPublicKey, cbPublicKey, false, 24);
+ VWriteLine("\tHash Algorithm : 0x%08x", ulHashAlgId);
+ DisplayASSEMBLYMETADATA(&MetaData);
+ if(MetaData.szLocale) delete [] MetaData.szLocale;
+ if(MetaData.rProcessor) delete [] MetaData.rProcessor;
+ if(MetaData.rOS) delete [] MetaData.rOS;
+
+ char sFlags[STRING_BUFFER_LEN];
+ DWORD flags = dwFlags;
+
+ sFlags[0] = 0;
+ ISFLAG(Af, PublicKey);
+ ISFLAG(Af, Retargetable);
+ ISFLAG(AfContentType_, WindowsRuntime);
+
+ if (!*sFlags)
+ strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
+
+ VWriteLine("\tFlags : %s (%08x)", sFlags, dwFlags);
+ DisplayCustomAttributes(mda, "\t");
+ DisplayPermissions(mda, "\t");
+ WriteLine("");
+} // void MDInfo::DisplayAssemblyInfo()
+
+void MDInfo::DisplayAssemblyRefs()
+{
+ HCORENUM assemblyRefEnum = NULL;
+ mdAssemblyRef AssemblyRefs[ENUM_BUFFER_SIZE];
+ ULONG count;
+ ULONG totalCount = 1;
+ HRESULT hr;
+
+ while (SUCCEEDED(hr = m_pAssemblyImport->EnumAssemblyRefs( &assemblyRefEnum,
+ AssemblyRefs, NumItems(AssemblyRefs), &count)) &&
+ count > 0)
+ {
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ VWriteLine("AssemblyRef #%d (%08x)", totalCount, AssemblyRefs[i]);
+ WriteLine("-------------------------------------------------------");
+ DisplayAssemblyRefInfo(AssemblyRefs[i]);
+ WriteLine("");
+ }
+ }
+ m_pAssemblyImport->CloseEnum(assemblyRefEnum);
+} // void MDInfo::DisplayAssemblyRefs()
+
+void MDInfo::DisplayAssemblyRefInfo(mdAssemblyRef inAssemblyRef)
+{
+ HRESULT hr;
+ const BYTE *pbPublicKeyOrToken;
+ ULONG cbPublicKeyOrToken;
+ WCHAR szName[STRING_BUFFER_LEN];
+ ASSEMBLYMETADATA MetaData;
+ const BYTE *pbHashValue;
+ ULONG cbHashValue;
+ DWORD dwFlags;
+
+ VWriteLine("\tToken: 0x%08x", inAssemblyRef);
+
+ // Get sizes for the arrays in the ASSEMBLYMETADATA structure.
+ ZeroMemory(&MetaData, sizeof(ASSEMBLYMETADATA));
+ hr = m_pAssemblyImport->GetAssemblyRefProps(inAssemblyRef,
+ NULL, NULL, // Public Key or Token.
+ NULL, 0, NULL, // Name.
+ &MetaData,
+ NULL, NULL, // HashValue.
+ NULL); // Flags.
+ if (FAILED(hr)) Error("GetAssemblyRefProps() failed.", hr);
+
+ // Allocate space for the arrays in the ASSEMBLYMETADATA structure.
+ if (MetaData.cbLocale)
+ MetaData.szLocale = new WCHAR[MetaData.cbLocale];
+ if (MetaData.ulProcessor)
+ MetaData.rProcessor = new DWORD[MetaData.ulProcessor];
+ if (MetaData.ulOS)
+ MetaData.rOS = new OSINFO[MetaData.ulOS];
+
+ hr = m_pAssemblyImport->GetAssemblyRefProps(inAssemblyRef,
+ (const void **)&pbPublicKeyOrToken, &cbPublicKeyOrToken,
+ szName, STRING_BUFFER_LEN, NULL,
+ &MetaData,
+ (const void **)&pbHashValue, &cbHashValue,
+ &dwFlags);
+ if (FAILED(hr)) Error("GetAssemblyRefProps() failed.", hr);
+
+ DumpHex("\tPublic Key or Token", pbPublicKeyOrToken, cbPublicKeyOrToken, false, 24);
+ VWriteLine("\tName: %ls", szName);
+ DisplayASSEMBLYMETADATA(&MetaData);
+ if(MetaData.szLocale) delete [] MetaData.szLocale;
+ if(MetaData.rProcessor) delete [] MetaData.rProcessor;
+ if(MetaData.rOS) delete [] MetaData.rOS;
+ DumpHex("\tHashValue Blob", pbHashValue, cbHashValue, false, 24);
+
+ char sFlags[STRING_BUFFER_LEN];
+ DWORD flags = dwFlags;
+
+ sFlags[0] = 0;
+ ISFLAG(Af, PublicKey);
+ ISFLAG(Af, Retargetable);
+ ISFLAG(AfContentType_, WindowsRuntime);
+#if 0
+ ISFLAG(Af, LegacyLibrary);
+ ISFLAG(Af, LegacyPlatform);
+ ISFLAG(Af, Library);
+ ISFLAG(Af, Platform);
+#endif
+ if (!*sFlags)
+ strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
+
+ VWriteLine("\tFlags: %s (%08x)", sFlags, dwFlags);
+ DisplayCustomAttributes(inAssemblyRef, "\t");
+ WriteLine("");
+} // void MDInfo::DisplayAssemblyRefInfo()
+
+void MDInfo::DisplayFiles()
+{
+ HCORENUM fileEnum = NULL;
+ mdFile Files[ENUM_BUFFER_SIZE];
+ ULONG count;
+ ULONG totalCount = 1;
+ HRESULT hr;
+
+ while (SUCCEEDED(hr = m_pAssemblyImport->EnumFiles( &fileEnum,
+ Files, NumItems(Files), &count)) &&
+ count > 0)
+ {
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ VWriteLine("File #%d (%08x)", totalCount, Files[i]);
+ WriteLine("-------------------------------------------------------");
+ DisplayFileInfo(Files[i]);
+ WriteLine("");
+ }
+ }
+ m_pAssemblyImport->CloseEnum(fileEnum);
+} // void MDInfo::DisplayFiles()
+
+void MDInfo::DisplayFileInfo(mdFile inFile)
+{
+ HRESULT hr;
+ WCHAR szName[STRING_BUFFER_LEN];
+ const BYTE *pbHashValue;
+ ULONG cbHashValue;
+ DWORD dwFlags;
+
+ VWriteLine("\tToken: 0x%08x", inFile);
+
+ hr = m_pAssemblyImport->GetFileProps(inFile,
+ szName, STRING_BUFFER_LEN, NULL,
+ (const void **)&pbHashValue, &cbHashValue,
+ &dwFlags);
+ if (FAILED(hr)) Error("GetFileProps() failed.", hr);
+ VWriteLine("\tName : %ls", szName);
+ DumpHex("\tHashValue Blob ", pbHashValue, cbHashValue, false, 24);
+
+ char sFlags[STRING_BUFFER_LEN];
+ DWORD flags = dwFlags;
+
+ sFlags[0] = 0;
+ ISFLAG(Ff, ContainsMetaData);
+ ISFLAG(Ff, ContainsNoMetaData);
+ if (!*sFlags)
+ strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
+
+ VWriteLine("\tFlags : %s (%08x)", sFlags, dwFlags);
+ DisplayCustomAttributes(inFile, "\t");
+ WriteLine("");
+
+} // MDInfo::DisplayFileInfo()
+
+void MDInfo::DisplayExportedTypes()
+{
+ HCORENUM comTypeEnum = NULL;
+ mdExportedType ExportedTypes[ENUM_BUFFER_SIZE];
+ ULONG count;
+ ULONG totalCount = 1;
+ HRESULT hr;
+
+ while (SUCCEEDED(hr = m_pAssemblyImport->EnumExportedTypes( &comTypeEnum,
+ ExportedTypes, NumItems(ExportedTypes), &count)) &&
+ count > 0)
+ {
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ VWriteLine("ExportedType #%d (%08x)", totalCount, ExportedTypes[i]);
+ WriteLine("-------------------------------------------------------");
+ DisplayExportedTypeInfo(ExportedTypes[i]);
+ WriteLine("");
+ }
+ }
+ m_pAssemblyImport->CloseEnum(comTypeEnum);
+} // void MDInfo::DisplayExportedTypes()
+
+void MDInfo::DisplayExportedTypeInfo(mdExportedType inExportedType)
+{
+ HRESULT hr;
+ WCHAR szName[STRING_BUFFER_LEN];
+ mdToken tkImplementation;
+ mdTypeDef tkTypeDef;
+ DWORD dwFlags;
+ char sFlags[STRING_BUFFER_LEN];
+
+ VWriteLine("\tToken: 0x%08x", inExportedType);
+
+ hr = m_pAssemblyImport->GetExportedTypeProps(inExportedType,
+ szName, STRING_BUFFER_LEN, NULL,
+ &tkImplementation,
+ &tkTypeDef,
+ &dwFlags);
+ if (FAILED(hr)) Error("GetExportedTypeProps() failed.", hr);
+ VWriteLine("\tName: %ls", szName);
+ VWriteLine("\tImplementation token: 0x%08x", tkImplementation);
+ VWriteLine("\tTypeDef token: 0x%08x", tkTypeDef);
+ VWriteLine("\tFlags : %s (%08x)",ClassFlags(dwFlags, sFlags), dwFlags);
+ DisplayCustomAttributes(inExportedType, "\t");
+ WriteLine("");
+} // void MDInfo::DisplayExportedTypeInfo()
+
+void MDInfo::DisplayManifestResources()
+{
+ HCORENUM manifestResourceEnum = NULL;
+ mdManifestResource ManifestResources[ENUM_BUFFER_SIZE];
+ ULONG count;
+ ULONG totalCount = 1;
+ HRESULT hr;
+
+ while (SUCCEEDED(hr = m_pAssemblyImport->EnumManifestResources( &manifestResourceEnum,
+ ManifestResources, NumItems(ManifestResources), &count)) &&
+ count > 0)
+ {
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ VWriteLine("ManifestResource #%d (%08x)", totalCount, ManifestResources[i]);
+ WriteLine("-------------------------------------------------------");
+ DisplayManifestResourceInfo(ManifestResources[i]);
+ WriteLine("");
+ }
+ }
+ m_pAssemblyImport->CloseEnum(manifestResourceEnum);
+} // void MDInfo::DisplayManifestResources()
+
+void MDInfo::DisplayManifestResourceInfo(mdManifestResource inManifestResource)
+{
+ HRESULT hr;
+ WCHAR szName[STRING_BUFFER_LEN];
+ mdToken tkImplementation;
+ DWORD dwOffset;
+ DWORD dwFlags;
+
+ VWriteLine("\tToken: 0x%08x", inManifestResource);
+
+ hr = m_pAssemblyImport->GetManifestResourceProps(inManifestResource,
+ szName, STRING_BUFFER_LEN, NULL,
+ &tkImplementation,
+ &dwOffset,
+ &dwFlags);
+ if (FAILED(hr)) Error("GetManifestResourceProps() failed.", hr);
+ VWriteLine("Name: %ls", szName);
+ VWriteLine("Implementation token: 0x%08x", tkImplementation);
+ VWriteLine("Offset: 0x%08x", dwOffset);
+
+ char sFlags[STRING_BUFFER_LEN];
+ DWORD flags = dwFlags;
+
+ sFlags[0] = 0;
+ ISFLAG(Mr, Public);
+ ISFLAG(Mr, Private);
+ if (!*sFlags)
+ strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
+
+ VWriteLine("\tFlags: %s (%08x)", sFlags, dwFlags);
+ DisplayCustomAttributes(inManifestResource, "\t");
+ WriteLine("");
+} // void MDInfo::DisplayManifestResourceInfo()
+
+void MDInfo::DisplayASSEMBLYMETADATA(ASSEMBLYMETADATA *pMetaData)
+{
+ ULONG i;
+
+ VWriteLine("\tVersion: %d.%d.%d.%d", pMetaData->usMajorVersion, pMetaData->usMinorVersion, pMetaData->usBuildNumber, pMetaData->usRevisionNumber);
+ VWriteLine("\tMajor Version: 0x%08x", pMetaData->usMajorVersion);
+ VWriteLine("\tMinor Version: 0x%08x", pMetaData->usMinorVersion);
+ VWriteLine("\tBuild Number: 0x%08x", pMetaData->usBuildNumber);
+ VWriteLine("\tRevision Number: 0x%08x", pMetaData->usRevisionNumber);
+ VWriteLine("\tLocale: %ls", pMetaData->cbLocale ? pMetaData->szLocale : L"<null>");
+ for (i = 0; i < pMetaData->ulProcessor; i++)
+ VWriteLine("\tProcessor #%ld: 0x%08x", i+1, pMetaData->rProcessor[i]);
+ for (i = 0; i < pMetaData->ulOS; i++)
+ {
+ VWriteLine("\tOS #%ld:", i+1);
+ VWriteLine("\t\tOS Platform ID: 0x%08x", pMetaData->rOS[i].dwOSPlatformId);
+ VWriteLine("\t\tOS Major Version: 0x%08x", pMetaData->rOS[i].dwOSMajorVersion);
+ VWriteLine("\t\tOS Minor Version: 0x%08x", pMetaData->rOS[i].dwOSMinorVersion);
+ }
+} // void MDInfo::DisplayASSEMBLYMETADATA()
+
+void MDInfo::DisplayUserStrings()
+{
+ HCORENUM stringEnum = NULL; // string enumerator.
+ mdString Strings[ENUM_BUFFER_SIZE]; // String tokens from enumerator.
+ CQuickArray<WCHAR> rUserString; // Buffer to receive string.
+ WCHAR *szUserString; // Working pointer into buffer.
+ ULONG chUserString; // Size of user string.
+ CQuickArray<char> rcBuf; // Buffer to hold the BLOB version of the string.
+ char *szBuf; // Working pointer into buffer.
+ ULONG chBuf; // Saved size of the user string.
+ ULONG count; // Items returned from enumerator.
+ ULONG totalCount = 1; // Running count of strings.
+ bool bUnprint = false; // Is an unprintable character found?
+ HRESULT hr; // A result.
+ while (SUCCEEDED(hr = m_pImport->EnumUserStrings( &stringEnum,
+ Strings, NumItems(Strings), &count)) &&
+ count > 0)
+ {
+ if (totalCount == 1)
+ { // If only one, it is the NULL string, so don't print it.
+ WriteLine("User Strings");
+ WriteLine("-------------------------------------------------------");
+ }
+ for (ULONG i = 0; i < count; i++, totalCount++)
+ {
+ do { // Try to get the string into the existing buffer.
+ hr = m_pImport->GetUserString( Strings[i], rUserString.Ptr(),(ULONG32)rUserString.MaxSize(), &chUserString);
+ if (hr == CLDB_S_TRUNCATION)
+ { // Buffer wasn't big enough, try to enlarge it.
+ if (FAILED(rUserString.ReSizeNoThrow(chUserString)))
+ Error("malloc failed.", E_OUTOFMEMORY);
+ continue;
+ }
+ } while (hr == CLDB_S_TRUNCATION);
+ if (FAILED(hr)) Error("GetUserString failed.", hr);
+
+ szUserString = rUserString.Ptr();
+ chBuf = chUserString;
+
+ VWrite("%08x : (%2d) L\"", Strings[i], chUserString);
+ for (ULONG j=0; j<chUserString; j++)
+ {
+ switch (*szUserString)
+ {
+ case 0:
+ Write("\\0"); break;
+ case L'\r':
+ Write("\\r"); break;
+ case L'\n':
+ Write("\\n"); break;
+ case L'\t':
+ Write("\\t"); break;
+ default:
+ if (iswprint(*szUserString))
+ VWrite("%lc", *szUserString);
+ else
+ {
+ bUnprint = true;
+ Write(".");
+ }
+ break;
+ }
+ ++szUserString;
+ if((j>0)&&((j&0x7F)==0)) WriteLine("");
+ }
+ WriteLine("\"");
+
+ // Print the user string as a blob if an unprintable character is found.
+ if (bUnprint)
+ {
+ bUnprint = false;
+ szUserString = rUserString.Ptr();
+ if (FAILED(hr = rcBuf.ReSizeNoThrow(81))) //(chBuf * 5 + 1);
+ Error("ReSize failed.", hr);
+ szBuf = rcBuf.Ptr();
+ ULONG j,k;
+ WriteLine("\t\tUser string has unprintables, hex format below:");
+ for (j = 0,k=0; j < chBuf; j++)
+ {
+ sprintf_s (&szBuf[k*5], 81, "%04x ", szUserString[j]);
+ k++;
+ if((k==16)||(j == (chBuf-1)))
+ {
+ szBuf[k*5] = '\0';
+ VWriteLine("\t\t%s", szBuf);
+ k=0;
+ }
+ }
+ }
+ }
+ }
+ if (stringEnum)
+ m_pImport->CloseEnum(stringEnum);
+} // void MDInfo::DisplayUserStrings()
+
+void MDInfo::DisplayUnsatInfo()
+{
+ HRESULT hr = S_OK;
+
+ HCORENUM henum = 0;
+ mdToken tk;
+ ULONG cMethods;
+
+ Write("\nUnresolved Externals\n");
+ Write("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
+
+ while ( (hr = m_pImport->EnumUnresolvedMethods(
+ &henum,
+ &tk,
+ 1,
+ &cMethods)) == S_OK && cMethods )
+ {
+ if ( TypeFromToken(tk) == mdtMethodDef )
+ {
+ // a method definition without implementation
+ DisplayMethodInfo( tk );
+ }
+ else if ( TypeFromToken(tk) == mdtMemberRef )
+ {
+ // an unresolved MemberRef to a global function
+ DisplayMemberRefInfo( tk, "" );
+ }
+ else
+ {
+ _ASSERTE(!"Unknown token kind!");
+ }
+ }
+ m_pImport->CloseEnum(henum);
+} // void MDInfo::DisplayUnsatInfo()
+
+//*******************************************************************************
+// This code is used for debugging purposes only. This will just print out the
+// entire database.
+//*******************************************************************************
+const char *MDInfo::DumpRawNameOfType(ULONG iType)
+{
+ if (iType <= iRidMax)
+ {
+ const char *pNameTable;
+ m_pTables->GetTableInfo(iType, 0,0,0,0, &pNameTable);
+ return pNameTable;
+ }
+ else
+ // Is the field a coded token?
+ if (iType <= iCodedTokenMax)
+ {
+ int iCdTkn = iType - iCodedToken;
+ const char *pNameCdTkn;
+ m_pTables->GetCodedTokenInfo(iCdTkn, 0,0, &pNameCdTkn);
+ return pNameCdTkn;
+ }
+
+ // Fixed type.
+ switch (iType)
+ {
+ case iBYTE:
+ return "BYTE";
+ case iSHORT:
+ return "short";
+ case iUSHORT:
+ return "USHORT";
+ case iLONG:
+ return "long";
+ case iULONG:
+ return "ULONG";
+ case iSTRING:
+ return "string";
+ case iGUID:
+ return "GUID";
+ case iBLOB:
+ return "blob";
+ }
+ // default:
+ static char buf[30];
+ sprintf_s(buf, 30, "unknown type 0x%02x", iType);
+ return buf;
+} // const char *MDInfo::DumpRawNameOfType()
+
+void MDInfo::DumpRawCol(ULONG ixTbl, ULONG ixCol, ULONG rid, bool bStats)
+{
+ ULONG ulType; // Type of a column.
+ ULONG ulVal; // Value of a column.
+ LPCUTF8 pString; // Pointer to a string.
+ const void *pBlob; // Pointer to a blob.
+ ULONG cb; // Size of something.
+
+ m_pTables->GetColumn(ixTbl, ixCol, rid, &ulVal);
+ m_pTables->GetColumnInfo(ixTbl, ixCol, 0, 0, &ulType, 0);
+
+ if (ulType <= iRidMax)
+ {
+ const char *pNameTable;
+ m_pTables->GetTableInfo(ulType, 0,0,0,0, &pNameTable);
+ VWrite("%s[%x]", pNameTable, ulVal);
+ }
+ else
+ // Is the field a coded token?
+ if (ulType <= iCodedTokenMax)
+ {
+ int iCdTkn = ulType - iCodedToken;
+ const char *pNameCdTkn;
+ m_pTables->GetCodedTokenInfo(iCdTkn, 0,0, &pNameCdTkn);
+ VWrite("%s[%08x]", pNameCdTkn, ulVal);
+ }
+ else
+ {
+ // Fixed type.
+ switch (ulType)
+ {
+ case iBYTE:
+ VWrite("%02x", ulVal);
+ break;
+ case iSHORT:
+ case iUSHORT:
+ VWrite("%04x", ulVal);
+ break;
+ case iLONG:
+ case iULONG:
+ VWrite("%08x", ulVal);
+ break;
+ case iSTRING:
+ if (ulVal && (m_DumpFilter & dumpNames))
+ {
+ m_pTables->GetString(ulVal, &pString);
+ VWrite("(%x)\"%s\"", ulVal, pString);
+ }
+ else
+ VWrite("string#%x", ulVal);
+ if (bStats && ulVal)
+ {
+ m_pTables->GetString(ulVal, &pString);
+ cb = (ULONG) strlen(pString) + 1;
+ VWrite("(%d)", cb);
+ }
+ break;
+ case iGUID:
+ VWrite("guid#%x", ulVal);
+ if (bStats && ulVal)
+ {
+ VWrite("(16)");
+ }
+ break;
+ case iBLOB:
+ VWrite("blob#%x", ulVal);
+ if (bStats && ulVal)
+ {
+ m_pTables->GetBlob(ulVal, &cb, &pBlob);
+ cb += 1;
+ if (cb > 128)
+ cb += 1;
+ if (cb > 16535)
+ cb += 1;
+ VWrite("(%d)", cb);
+ }
+ break;
+ default:
+ VWrite("unknown type 0x%04x", ulVal);
+ break;
+ }
+ }
+} // void MDInfo::DumpRawCol()
+
+ULONG MDInfo::DumpRawColStats(ULONG ixTbl, ULONG ixCol, ULONG cRows)
+{
+ ULONG rslt = 0;
+ ULONG ulType; // Type of a column.
+ ULONG ulVal; // Value of a column.
+ LPCUTF8 pString; // Pointer to a string.
+ const void *pBlob; // Pointer to a blob.
+ ULONG cb; // Size of something.
+
+ m_pTables->GetColumnInfo(ixTbl, ixCol, 0, 0, &ulType, 0);
+
+ if (IsHeapType(ulType))
+ {
+ for (ULONG rid=1; rid<=cRows; ++rid)
+ {
+ m_pTables->GetColumn(ixTbl, ixCol, rid, &ulVal);
+ // Fixed type.
+ switch (ulType)
+ {
+ case iSTRING:
+ if (ulVal)
+ {
+ m_pTables->GetString(ulVal, &pString);
+ cb = (ULONG) strlen(pString);
+ rslt += cb + 1;
+ }
+ break;
+ case iGUID:
+ if (ulVal)
+ rslt += 16;
+ break;
+ case iBLOB:
+ if (ulVal)
+ {
+ m_pTables->GetBlob(ulVal, &cb, &pBlob);
+ rslt += cb + 1;
+ if (cb > 128)
+ rslt += 1;
+ if (cb > 16535)
+ rslt += 1;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return rslt;
+} // ULONG MDInfo::DumpRawColStats()
+
+int MDInfo::DumpHex(
+ const char *szPrefix, // String prefix for first line.
+ const void *pvData, // The data to print.
+ ULONG cbData, // Bytes of data to print.
+ int bText, // If true, also dump text.
+ ULONG nLine) // Bytes per line to print.
+{
+ const BYTE *pbData = static_cast<const BYTE*>(pvData);
+ ULONG i; // Loop control.
+ ULONG nPrint; // Number to print in an iteration.
+ ULONG nSpace; // Spacing calculations.
+ ULONG nPrefix; // Size of the prefix.
+ ULONG nLines=0; // Number of lines printed.
+ const char *pPrefix; // For counting spaces in the prefix.
+
+ // Round down to 8 characters.
+ nLine = nLine & ~0x7;
+
+ for (nPrefix=0, pPrefix=szPrefix; *pPrefix; ++pPrefix)
+ {
+ if (*pPrefix == '\t')
+ nPrefix = (nPrefix + 8) & ~7;
+ else
+ ++nPrefix;
+ }
+ //nPrefix = strlen(szPrefix);
+ do
+ { // Write the line prefix.
+ if (szPrefix)
+ VWrite("%s:", szPrefix);
+ else
+ VWrite("%*s:", nPrefix, "");
+ szPrefix = 0;
+ ++nLines;
+
+ // Calculate spacing.
+ nPrint = min(cbData, nLine);
+ nSpace = nLine - nPrint;
+
+ // dump in hex.
+ for(i=0; i<nPrint; i++)
+ {
+ if ((i&7) == 0)
+ Write(" ");
+ VWrite("%02x ", pbData[i]);
+ }
+ if (bText)
+ {
+ // Space out to the text spot.
+ if (nSpace)
+ VWrite("%*s", nSpace*3+nSpace/8, "");
+ // Dump in text.
+ Write(">");
+ for(i=0; i<nPrint; i++)
+ VWrite("%c", (isprint(pbData[i])) ? pbData[i] : ' ');
+ // Space out the text, and finish the line.
+ VWrite("%*s<", nSpace, "");
+ }
+ VWriteLine("");
+
+ // Next data to print.
+ cbData -= nPrint;
+ pbData += nPrint;
+ }
+ while (cbData > 0);
+
+ return nLines;
+} // int MDInfo::DumpHex()
+
+void MDInfo::DumpRawHeaps()
+{
+ HRESULT hr; // A result.
+ ULONG ulSize; // Bytes in a heap.
+ const BYTE *pData; // Pointer to a blob.
+ ULONG cbData; // Size of a blob.
+ ULONG oData; // Offset of current blob.
+ char rcPrefix[30]; // To format line prefix.
+
+ m_pTables->GetBlobHeapSize(&ulSize);
+ VWriteLine("");
+ VWriteLine("Blob Heap: %d(%#x) bytes", ulSize,ulSize);
+ oData = 0;
+ do
+ {
+ m_pTables->GetBlob(oData, &cbData, (const void**)&pData);
+ sprintf_s(rcPrefix, 30, "%5x,%-2x", oData, cbData);
+ DumpHex(rcPrefix, pData, cbData);
+ hr = m_pTables->GetNextBlob(oData, &oData);
+ }
+ while (hr == S_OK);
+
+ m_pTables->GetStringHeapSize(&ulSize);
+ VWriteLine("");
+ VWriteLine("String Heap: %d(%#x) bytes", ulSize,ulSize);
+ oData = 0;
+ const char *pString;
+ do
+ {
+ m_pTables->GetString(oData, &pString);
+ if (m_DumpFilter & dumpMoreHex)
+ {
+ sprintf_s(rcPrefix, 30, "%08x", oData);
+ DumpHex(rcPrefix, pString, (ULONG)strlen(pString)+1);
+ }
+ else
+ if (*pString != 0)
+ VWrite("%08x: %s\n", oData, pString);
+ hr = m_pTables->GetNextString(oData, &oData);
+ }
+ while (hr == S_OK);
+ VWriteLine("");
+
+ DisplayUserStrings();
+
+} // void MDInfo::DumpRawHeaps()
+
+
+void MDInfo::DumpRaw(int iDump, bool bunused)
+{
+ ULONG cTables; // Tables in the database.
+ ULONG cCols; // Columns in a table.
+ ULONG cRows; // Rows in a table.
+ ULONG cbRow; // Bytes in a row of a table.
+ ULONG iKey; // Key column of a table.
+ const char *pNameTable; // Name of a table.
+ ULONG oCol; // Offset of a column.
+ ULONG cbCol; // Size of a column.
+ ULONG ulType; // Type of a column.
+ const char *pNameColumn; // Name of a column.
+ ULONG ulSize;
+
+ // Heaps is easy -- there is a specific bit for that.
+ bool bStats = (m_DumpFilter & dumpStats) != 0;
+ // Rows are harder. Was there something else that limited data?
+ BOOL bRows = (m_DumpFilter & (dumpSchema | dumpHeader)) == 0;
+ BOOL bSchema = bRows || (m_DumpFilter & dumpSchema);
+ // (m_DumpFilter & (dumpSchema | dumpHeader | dumpCSV | dumpRaw | dumpStats | dumpRawHeaps))
+
+ if (m_pTables2)
+ {
+ // Get the raw metadata header.
+ const BYTE *pbData = NULL;
+ const BYTE *pbStream = NULL; // One of the stream.s
+ const BYTE *pbMd = NULL; // The metadata stream.
+ ULONG cbData = 0;
+ ULONG cbStream = 0; // One of the streams.
+ ULONG cbMd = 0; // The metadata stream.
+ const char *pName;
+ HRESULT hr = S_OK;
+ ULONG ix;
+
+ m_pTables2->GetMetaDataStorage((const void**)&pbData, &cbData);
+
+ // Per the ECMA spec, the section data looks like this:
+ struct MDSTORAGESIGNATURE
+ {
+ ULONG lSignature; // "Magic" signature.
+ USHORT iMajorVer; // Major file version.
+ USHORT iMinorVer; // Minor file version.
+ ULONG iExtraData; // Offset to next structure of information
+ ULONG iVersionString; // Length of version string
+ BYTE pVersion[0]; // Version string
+ };
+ struct MDSTORAGEHEADER
+ {
+ BYTE fFlags; // STGHDR_xxx flags.
+ BYTE pad;
+ USHORT iStreams; // How many streams are there.
+ };
+ const MDSTORAGESIGNATURE *pStorage = (const MDSTORAGESIGNATURE *) pbData;
+ const MDSTORAGEHEADER *pSHeader = (const MDSTORAGEHEADER *)(pbData + sizeof(MDSTORAGESIGNATURE) + pStorage->iVersionString);
+
+ VWriteLine("Metadata section: 0x%08x, version: %d.%d, extra: %d, version len: %d, version: %s", pStorage->lSignature, pStorage->iMajorVer, pStorage->iMinorVer, pStorage->iExtraData, pStorage->iVersionString, pStorage->pVersion);
+ VWriteLine(" flags: 0x%02x, streams: %d", pSHeader->fFlags, pSHeader->iStreams);
+ if (m_DumpFilter & dumpMoreHex)
+ {
+ const BYTE *pbEnd = pbData;
+ ULONG cb = sizeof(MDSTORAGESIGNATURE) + pStorage->iVersionString + sizeof(MDSTORAGEHEADER);
+ hr = m_pTables2->GetMetaDataStreamInfo(0, &pName, (const void**)&pbEnd, &cbStream);
+ if (hr == S_OK)
+ cb = (ULONG)(pbEnd - pbData);
+ DumpHex(" ", pbData, cb);
+ }
+
+ for (ix=0; hr == S_OK; ++ix)
+ {
+ hr = m_pTables2->GetMetaDataStreamInfo(ix, &pName, (const void**)&pbStream, &cbStream);
+ if (hr != S_OK)
+ break;
+ if (strcmp(pName, "#~") == 0 || strcmp(pName, "#-") == 0)
+ {
+ pbMd = pbStream;
+ cbMd = cbStream;
+ }
+
+ VWriteLine("Stream %d: name: %s, size %d", ix, pName, cbStream);
+ // hex for individual stream headers in metadata section dump. hex for
+ // the streams themselves distributed throughout the dump.
+ }
+
+ if (pbMd)
+ {
+ // Per ECMA, the metadata header looks like this:
+ struct MD
+ {
+ ULONG m_ulReserved; // Reserved, must be zero.
+ BYTE m_major; // Version numbers.
+ BYTE m_minor;
+ BYTE m_heaps; // Bits for heap sizes.
+ BYTE m_rid; // log-base-2 of largest rid.
+ unsigned __int64 m_maskvalid; // Bit mask of present table counts.
+ unsigned __int64 m_sorted; // Bit mask of sorted tables. };
+ };
+
+ const MD *pMd;
+ pMd = (const MD *)pbMd;
+
+ VWriteLine("Metadata header: %d.%d, heaps: 0x%02x, rid: 0x%02x, valid: 0x%016I64x, sorted: 0x%016I64x",
+ pMd->m_major, pMd->m_minor, pMd->m_heaps, pMd->m_rid,
+ (ULONGLONG)GET_UNALIGNED_VAL64(&(pMd->m_maskvalid)),
+ (ULONGLONG)GET_UNALIGNED_VAL64(&(pMd->m_sorted)));
+
+ if (m_DumpFilter & dumpMoreHex)
+ {
+ DumpHex(" ", pbMd, sizeof(MD));
+ }
+ }
+ VWriteLine("");
+ }
+
+ m_pTables->GetNumTables(&cTables);
+
+ m_pTables->GetStringHeapSize(&ulSize);
+ VWrite("Strings: %d(%#x)", ulSize, ulSize);
+ m_pTables->GetBlobHeapSize(&ulSize);
+ VWrite(", Blobs: %d(%#x)", ulSize, ulSize);
+ m_pTables->GetGuidHeapSize(&ulSize);
+ VWrite(", Guids: %d(%#x)", ulSize, ulSize);
+ m_pTables->GetUserStringHeapSize(&ulSize);
+ VWriteLine(", User strings: %d(%#x)", ulSize, ulSize);
+
+ for (ULONG ixTbl = 0; ixTbl < cTables; ++ixTbl)
+ {
+ m_pTables->GetTableInfo(ixTbl, &cbRow, &cRows, &cCols, &iKey, &pNameTable);
+
+ if (bRows) // when dumping rows, print a break between row data and schema
+ VWriteLine("=================================================");
+ VWriteLine("%2d(%#x): %-20s cRecs:%5d(%#x), cbRec:%3d(%#x), cbTable:%6d(%#x)",
+ ixTbl, ixTbl, pNameTable, cRows, cRows, cbRow, cbRow, cbRow * cRows, cbRow * cRows);
+
+ if (!bSchema && !bRows)
+ continue;
+
+ // Dump column definitions for the table.
+ ULONG ixCol;
+ for (ixCol=0; ixCol<cCols; ++ixCol)
+ {
+ m_pTables->GetColumnInfo(ixTbl, ixCol, &oCol, &cbCol, &ulType, &pNameColumn);
+
+ VWrite(" col %2x:%c %-12s oCol:%2x, cbCol:%x, %-7s",
+ ixCol, ((ixCol==iKey)?'*':' '), pNameColumn, oCol, cbCol, DumpRawNameOfType(ulType));
+
+ if (bStats)
+ {
+ ulSize = DumpRawColStats(ixTbl, ixCol, cRows);
+ if (ulSize)
+ VWrite("(%d)", ulSize);
+ }
+ VWriteLine("");
+ }
+
+ if (!bRows)
+ continue;
+
+ // Dump the rows.
+ for (ULONG rid = 1; rid <= cRows; ++rid)
+ {
+ if (rid == 1)
+ VWriteLine("-------------------------------------------------");
+ VWrite(" %3x == ", rid);
+ for (ixCol=0; ixCol < cCols; ++ixCol)
+ {
+ if (ixCol) VWrite(", ");
+ VWrite("%d:", ixCol);
+ DumpRawCol(ixTbl, ixCol, rid, bStats);
+ }
+ VWriteLine("");
+ }
+ }
+} // void MDInfo::DumpRaw()
+
+void MDInfo::DumpRawCSV()
+{
+ ULONG cTables; // Tables in the database.
+ ULONG cCols; // Columns in a table.
+ ULONG cRows; // Rows in a table.
+ ULONG cbRow; // Bytes in a row of a table.
+ const char *pNameTable; // Name of a table.
+ ULONG ulSize;
+
+ m_pTables->GetNumTables(&cTables);
+
+ VWriteLine("Name,Size,cRecs,cbRec");
+
+ m_pTables->GetStringHeapSize(&ulSize);
+ VWriteLine("Strings,%d", ulSize);
+
+ m_pTables->GetBlobHeapSize(&ulSize);
+ VWriteLine("Blobs,%d", ulSize);
+
+ m_pTables->GetGuidHeapSize(&ulSize);
+ VWriteLine("Guids,%d", ulSize);
+
+ for (ULONG ixTbl = 0; ixTbl < cTables; ++ixTbl)
+ {
+ m_pTables->GetTableInfo(ixTbl, &cbRow, &cRows, &cCols, NULL, &pNameTable);
+ VWriteLine("%s,%d,%d,%d", pNameTable, cbRow*cRows, cRows, cbRow);
+ }
+
+} // void MDInfo::DumpRawCSV()
+
diff --git a/src/tools/metainfo/mdinfo.h b/src/tools/metainfo/mdinfo.h
new file mode 100644
index 0000000000..077a89da9b
--- /dev/null
+++ b/src/tools/metainfo/mdinfo.h
@@ -0,0 +1,206 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#ifndef _mdinfo_h
+#define _mdinfo_h
+
+#include "winwrap.h"
+#include "cor.h"
+#include "corhlprpriv.h"
+
+#ifdef FEATURE_PAL
+#include <oleauto.h>
+#endif
+
+#define STRING_BUFFER_LEN 4096
+
+typedef void (*strPassBackFn)(const char *str);
+
+class MDInfo {
+public:
+ enum DUMP_FILTER
+ {
+ dumpDefault = 0x00000000, // Dump everything but debugger data.
+ dumpSchema = 0x00000002, // Dump the metadata schema.
+ dumpRaw = 0x00000004, // Dump the metadata in raw table format.
+ dumpHeader = 0x00000008, // Dump just the metadata header info.
+ dumpCSV = 0x00000010, // Dump the metadata header info in CSV format.
+ dumpUnsat = 0x00000020, // Dump unresolved methods or memberref
+ dumpAssem = 0x00000040,
+ dumpStats = 0x00000080, // Dump more statistics about tables.
+ dumpMoreHex = 0x00000100, // Dump more things in hex.
+ dumpValidate = 0x00000200, // Validate MetaData.
+ dumpRawHeaps = 0x00000400, // Also dump the heaps in the raw dump.
+ dumpNoLogo = 0x00000800, // Don't display the logo or MVID
+ dumpNames = 0x00001000, // In a hex dump, display the names, as well as string #'s.
+ };
+
+
+public:
+ MDInfo(IMetaDataImport2* pImport, IMetaDataAssemblyImport* pAssemblyImport, LPCWSTR szScope, strPassBackFn inPBFn, ULONG DumpFilter);
+ MDInfo(IMetaDataDispenserEx *pDispenser, LPCWSTR szScope, strPassBackFn inPBFn, ULONG DumpFilter=dumpDefault);
+ MDInfo(IMetaDataDispenserEx *pDispenser, PBYTE pManifest, DWORD dwSize, strPassBackFn inPBFn, ULONG DumpFilter=dumpDefault);
+ ~MDInfo();
+
+ void DisplayMD(void);
+
+ LPWSTR VariantAsString(VARIANT *pVariant);
+
+ void DisplayVersionInfo(void);
+
+ void DisplayScopeInfo(void);
+
+ void DisplayGlobalFunctions(void);
+ void DisplayGlobalFields(void);
+ void DisplayFieldRVA(mdFieldDef field);
+ void DisplayGlobalMemberRefs(void);
+
+ void DisplayTypeDefs(void);
+ void DisplayTypeDefInfo(mdTypeDef inTypeDef);
+ void DisplayTypeDefProps(mdTypeDef inTypeDef);
+
+ void DisplayModuleRefs(void);
+ void DisplayModuleRefInfo(mdModuleRef inModuleRef);
+
+ void DisplaySignatures(void);
+ void DisplaySignatureInfo(mdSignature inSignature);
+
+ LPCWSTR TokenName(mdToken inToken, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen);
+
+ LPCWSTR TypeDeforRefName(mdToken inToken, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen);
+ LPCWSTR TypeDefName(mdTypeDef inTypeDef, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen);
+ LPCWSTR TypeRefName(mdTypeRef tr, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen);
+
+ LPCWSTR MemberDeforRefName(mdToken inToken, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen);
+ LPCWSTR MemberRefName(mdToken inMemRef, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen);
+ LPCWSTR MemberName(mdToken inMember, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen);
+
+ LPCWSTR MethodName(mdMethodDef inToken, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen);
+ LPCWSTR FieldName(mdFieldDef inToken, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen);
+
+ char *ClassFlags(DWORD flags, __out_ecount(STRING_BUFFER_LEN) char *sFlags);
+
+ void DisplayTypeRefs(void);
+ void DisplayTypeRefInfo(mdTypeRef tr);
+ void DisplayTypeSpecs(void);
+ void DisplayTypeSpecInfo(mdTypeSpec ts, const char *preFix);
+ void DisplayMethodSpecs(void);
+ void DisplayMethodSpecInfo(mdMethodSpec ms, const char *preFix);
+
+ void DisplayCorNativeLink(COR_NATIVE_LINK *pCorNLnk, const char *preFix);
+ void DisplayCustomAttributeInfo(mdCustomAttribute inValue, const char *preFix);
+ void DisplayCustomAttributes(mdToken inToken, const char *preFix);
+
+ void DisplayInterfaceImpls(mdTypeDef inTypeDef);
+ void DisplayInterfaceImplInfo(mdInterfaceImpl inImpl);
+
+ LPWSTR GUIDAsString(GUID inGuid, __out_ecount(bufLen) LPWSTR guidString, ULONG bufLen);
+
+ char *TokenTypeName(mdToken inToken);
+
+ void DisplayMemberInfo(mdToken inMember);
+ void DisplayMethodInfo(mdMethodDef method, DWORD *pflags = 0);
+ void DisplayFieldInfo(mdFieldDef field, DWORD *pflags = 0);
+
+ void DisplayMethods(mdTypeDef inTypeDef);
+ void DisplayFields(mdTypeDef inTypeDef, COR_FIELD_OFFSET *rFieldOffset, ULONG cFieldOffset);
+
+ void DisplaySignature(PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob, const char *preFix);
+ HRESULT GetOneElementType(PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob, ULONG *pcb);
+
+ void DisplayMemberRefs(mdToken tkParent, const char *preFix);
+ void DisplayMemberRefInfo(mdMemberRef inMemRef, const char *preFix);
+
+ void DisplayMethodImpls(mdTypeDef inTypeDef);
+
+ void DisplayParams(mdMethodDef inMthDef);
+ void DisplayParamInfo(mdParamDef inParam);
+
+ void DisplayGenericParams(mdToken tk, const char *prefix);
+ void DisplayGenericParamInfo(mdGenericParam tkparam, const char *prefix);
+
+ void DisplayPropertyInfo(mdProperty inProp);
+ void DisplayProperties(mdTypeDef inTypeDef);
+
+ void DisplayEventInfo(mdEvent inEvent);
+ void DisplayEvents(mdTypeDef inTypeDef);
+
+ void DisplayPermissions(mdToken tk, const char *preFix);
+ void DisplayPermissionInfo(mdPermission inPermission, const char *preFix);
+
+ void DisplayFieldMarshal(mdToken inToken);
+
+ void DisplayPinvokeInfo(mdToken inToken);
+
+ void DisplayAssembly();
+
+ void DisplayAssemblyInfo();
+
+ void DisplayAssemblyRefs();
+ void DisplayAssemblyRefInfo(mdAssemblyRef inAssemblyRef);
+
+ void DisplayFiles();
+ void DisplayFileInfo(mdFile inFile);
+
+ void DisplayExportedTypes();
+ void DisplayExportedTypeInfo(mdExportedType inExportedType);
+
+ void DisplayManifestResources();
+ void DisplayManifestResourceInfo(mdManifestResource inManifestResource);
+
+ void DisplayASSEMBLYMETADATA(ASSEMBLYMETADATA *pMetaData);
+
+ void DisplayUserStrings();
+
+ void DisplayUnsatInfo();
+
+ void DisplayRaw();
+ void DumpRawHeaps();
+ void DumpRaw(int iDump=1, bool bStats=false);
+ void DumpRawCSV();
+ void DumpRawCol(ULONG ixTbl, ULONG ixCol, ULONG rid, bool bStats);
+ ULONG DumpRawColStats(ULONG ixTbl, ULONG ixCol, ULONG cRows);
+ const char *DumpRawNameOfType(ULONG ulType);
+ void SetVEHandlerReporter(__int64 VEHandlerReporterPtr) { m_VEHandlerReporterPtr = VEHandlerReporterPtr; };
+
+ static void Error(const char *szError, HRESULT hr = S_OK);
+private:
+ void Init(strPassBackFn inPBFn, DUMP_FILTER DumpFilter); // Common initialization code.
+
+ int DumpHex(const char *szPrefix, const void *pvData, ULONG cbData, int bText=true, ULONG nLine=16);
+
+ int Write(__in_z __in char *str);
+ int WriteLine(__in_z __in char *str);
+
+ int VWrite(__in_z __in char *str, ...);
+ int VWriteLine(__in_z __in char *str, ...);
+ int VWriteMarker(__in_z __in char *str, va_list marker);
+
+ void InitSigBuffer();
+ HRESULT AddToSigBuffer(__in_z __in char *string);
+
+ IMetaDataImport2 *m_pRegImport;
+ IMetaDataImport2 *m_pImport;
+ IMetaDataAssemblyImport *m_pAssemblyImport;
+ strPassBackFn m_pbFn;
+ __int64 m_VEHandlerReporterPtr;
+ IMetaDataTables *m_pTables;
+ IMetaDataTables2 *m_pTables2;
+
+ CQuickBytes m_output;
+ DUMP_FILTER m_DumpFilter;
+
+ // temporary buffer for TypeDef or TypeRef name. Consume immediately
+ // because other functions may overwrite it.
+ WCHAR m_szTempBuf[STRING_BUFFER_LEN];
+
+ // temporary buffer for formatted string. Consume immediately before any function calls.
+ char m_tempFormatBuffer[STRING_BUFFER_LEN];
+
+ // Signature buffer.
+ CQuickBytes m_sigBuf;
+};
+
+#endif
diff --git a/src/tools/metainfo/mdobj.cpp b/src/tools/metainfo/mdobj.cpp
new file mode 100644
index 0000000000..956d4c6f76
--- /dev/null
+++ b/src/tools/metainfo/mdobj.cpp
@@ -0,0 +1,299 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include <stdio.h>
+#include <ctype.h>
+#include <crtdbg.h>
+#include "mdinfo.h"
+
+#ifndef STRING_BUFFER_LEN
+#define STRING_BUFFER_LEN 4096
+#endif
+
+#define OBJ_EXT ".obj"
+#define OBJ_EXT_W L".obj"
+#define OBJ_EXT_LEN 4
+#define LIB_EXT ".lib"
+#define LIB_EXT_W L".lib"
+#define LIB_EXT_LEN 4
+
+extern IMetaDataDispenserEx *g_pDisp;
+extern DWORD g_ValModuleType;
+
+// This function is copied from peparse.c file. Making this static, so we won't end up with
+// duplicate definitions causing confusion.
+static const char g_szCORMETA[] = ".cormeta";
+static HRESULT FindObjMetaData(PVOID pImage, PVOID *ppMetaData, long *pcbMetaData)
+{
+ IMAGE_FILE_HEADER *pImageHdr; // Header for the .obj file.
+ IMAGE_SECTION_HEADER *pSectionHdr; // Section header.
+ WORD i; // Loop control.
+
+ // Get a pointer to the header and the first section.
+ pImageHdr = (IMAGE_FILE_HEADER *) pImage;
+ pSectionHdr = (IMAGE_SECTION_HEADER *)(pImageHdr + 1);
+
+ // Avoid confusion.
+ *ppMetaData = NULL;
+ *pcbMetaData = 0;
+
+ // Walk each section looking for .cormeta.
+ for (i=0; i<VAL16(pImageHdr->NumberOfSections); i++, pSectionHdr++)
+ {
+ // Simple comparison to section name.
+ if (strcmp((const char *) pSectionHdr->Name, g_szCORMETA) == 0)
+ {
+ *pcbMetaData = VAL32(pSectionHdr->SizeOfRawData);
+ *ppMetaData = (void *) ((UINT_PTR)pImage + VAL32(pSectionHdr->PointerToRawData));
+ break;
+ }
+ }
+
+ // Check for errors.
+ if (*ppMetaData == NULL || *pcbMetaData == 0)
+ return (E_FAIL);
+ return (S_OK);
+}
+
+
+// This function returns the address to the MapView of file and file size.
+void GetMapViewOfFile(__in wchar_t *szFile, PBYTE *ppbMap, DWORD *pdwFileSize)
+{
+ HANDLE hMapFile;
+ DWORD dwHighSize;
+
+ HANDLE hFile = WszCreateFile(szFile,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ MDInfo::Error("CreateFileA failed!");
+
+ *pdwFileSize = GetFileSize(hFile, &dwHighSize);
+
+ if ((*pdwFileSize == 0xFFFFFFFF) && (GetLastError() != NO_ERROR))
+ {
+ CloseHandle(hFile);
+ MDInfo::Error("GetFileSize failed!");
+ }
+ _ASSERTE(dwHighSize == 0);
+
+ hMapFile = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
+ CloseHandle(hFile);
+ if (!hMapFile)
+ MDInfo::Error("CreateFileMappingA failed!");
+
+ *ppbMap = (PBYTE) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
+ CloseHandle(hMapFile);
+
+ if (!*ppbMap)
+ MDInfo::Error("MapViewOfFile failed!");
+} // void GetMapViewOfFile()
+
+// This function skips a member given the pointer to the member header
+// and returns a pointer to the next header.
+PBYTE SkipMember(PBYTE pbMapAddress)
+{
+ PIMAGE_ARCHIVE_MEMBER_HEADER pMemHdr;
+ ULONG ulMemSize;
+ int j;
+
+ pMemHdr = (PIMAGE_ARCHIVE_MEMBER_HEADER)pbMapAddress;
+
+ // Get size of the member.
+ ulMemSize = 0;
+ for (j = 0; j < 10; j++)
+ {
+ if (pMemHdr->Size[j] < '0' || pMemHdr->Size[j] > '9')
+ break;
+ else
+ ulMemSize = ulMemSize * 10 + pMemHdr->Size[j] - '0';
+ }
+
+ // Skip past the header.
+ pbMapAddress += IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR + ulMemSize;
+ // Find the next even address if the current one is not even.
+ if ((ULONG_PTR)pbMapAddress % 2)
+ pbMapAddress++;
+
+ return pbMapAddress;
+} // void SkipMember()
+
+// This function returns the name of the given Obj. If the name fits in the header,
+// szBuf will be filled in and returned from the function. Else an offset into the long
+// names section will be returned.
+char *GetNameOfObj(PBYTE pbLongNames, PIMAGE_ARCHIVE_MEMBER_HEADER pMemHdr, char szBuf[17])
+{
+ if (pMemHdr->Name[0] == '/')
+ {
+ ULONG ulOffset = 0;
+
+ // Long Names section must exist if the .obj file name starts with '/'.
+ _ASSERTE(pbLongNames &&
+ "Corrupt archive file - .obj file name in the header starts with "
+ "'/' but no long names section present in the archive file.");
+
+ // Calculate the offset into the long names section.
+ for (int j = 1; j < 16; j++)
+ {
+ if (pMemHdr->Name[j] < '0' || pMemHdr->Name[j] > '9')
+ break;
+ else
+ ulOffset = ulOffset * 10 + pMemHdr->Name[j] - '0';
+ }
+ return (char *)(pbLongNames + ulOffset);
+ }
+ else
+ {
+ int j;
+ for (j = 0; j < 16; j++)
+ if ((szBuf[j] = pMemHdr->Name[j]) == '/')
+ break;
+ szBuf[j] = '\0';
+ return szBuf;
+ }
+} // char *GetNameOfObj()
+
+// DisplayArchive() function
+//
+// Opens the .LIB file, and displays the metadata in the specified object files.
+
+void DisplayArchive(__in_z __in wchar_t* szFile, ULONG DumpFilter, __in_z __in_opt wchar_t* szObjName, strPassBackFn pDisplayString)
+{
+ PBYTE pbMapAddress;
+ PBYTE pbStartAddress;
+ PBYTE pbLongNameAddress;
+ PIMAGE_ARCHIVE_MEMBER_HEADER pMemHdr;
+ DWORD dwFileSize;
+ PVOID pvMetaData;
+ char *szName;
+ wchar_t wzName[1024];
+ char szBuf[17];
+ long cbMetaData;
+ int i;
+ HRESULT hr;
+ char szString[1024];
+
+ GetMapViewOfFile(szFile, &pbMapAddress, &dwFileSize);
+ pbStartAddress = pbMapAddress;
+
+ // Verify and skip archive signature.
+ if (dwFileSize < IMAGE_ARCHIVE_START_SIZE ||
+ strncmp((char *)pbMapAddress, IMAGE_ARCHIVE_START, IMAGE_ARCHIVE_START_SIZE))
+ {
+ MDInfo::Error("Bad file format - archive signature mis-match!");
+ }
+ pbMapAddress += IMAGE_ARCHIVE_START_SIZE;
+
+ // Skip linker member 1, linker member 2.
+ for (i = 0; i < 2; i++)
+ pbMapAddress = SkipMember(pbMapAddress);
+
+ // Save address of the long name member and skip it if there exists one.
+ pMemHdr = (PIMAGE_ARCHIVE_MEMBER_HEADER)pbMapAddress;
+ if (pMemHdr->Name[0] == '/' && pMemHdr->Name[1] == '/')
+ {
+ pbLongNameAddress = pbMapAddress + IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR;
+ pbMapAddress = SkipMember(pbMapAddress);
+ }
+ else
+ pbLongNameAddress = 0;
+
+ pDisplayString ("\n");
+ // Get the MetaData for each object file and display it.
+ while (DWORD(pbMapAddress - pbStartAddress) < dwFileSize)
+ {
+ if((szName = GetNameOfObj(pbLongNameAddress, (PIMAGE_ARCHIVE_MEMBER_HEADER)pbMapAddress, szBuf))!=NULL)
+ {
+ if (Wsz_mbstowcs(wzName, szName, 1024) == -1)
+ MDInfo::Error("Conversion from Multi-Byte to Wide-Char failed.");
+
+ // Display metadata only for object files.
+ // If szObjName is specified, display metadata only for that one object file.
+ if (!_stricmp(&szName[strlen(szName) - OBJ_EXT_LEN], OBJ_EXT) &&
+ (!szObjName || !_wcsicmp(szObjName, wzName)))
+ {
+ // Try to find the MetaData section in the current object file.
+ hr = FindObjMetaData(pbMapAddress+IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR, &pvMetaData, &cbMetaData);
+ if (SUCCEEDED(hr))
+ {
+ sprintf_s (szString,1024,"MetaData for object file %s:\n", szName);
+ pDisplayString(szString);
+ MDInfo archiveInfo(g_pDisp,
+ (PBYTE)pvMetaData,
+ cbMetaData,
+ pDisplayString,
+ DumpFilter);
+ archiveInfo.DisplayMD();
+ }
+ else
+ {
+ sprintf_s(szString,1024,"MetaData not found for object file %s!\n\n", szName);
+ pDisplayString(szString);
+ }
+ }
+ }
+
+ // Skip past the object file.
+ pbMapAddress = SkipMember(pbMapAddress);
+ }
+
+ UnmapViewOfFile(pbStartAddress);
+} // void DisplayArchive()
+
+// DisplayFile() function
+//
+// Opens the meta data content of a .EXE, .CLB, .CLASS, .TLB, .DLL or .LIB file, and
+// calls RawDisplay()
+
+void DisplayFile(__in_z __in wchar_t* szFile, BOOL isFile, ULONG DumpFilter, __in_z __in_opt wchar_t* szObjName, strPassBackFn pDisplayString)
+{
+ // Open the emit scope
+
+ // We need to make sure this file isn't too long. Checking _MAX_PATH is probably safe, but since we have a much
+ // larger buffer, we might as well use it all.
+ if (wcslen(szFile) > 1000)
+ return;
+
+
+ WCHAR szScope[1024];
+ char szString[1024];
+
+ if (isFile)
+ {
+ wcscpy_s(szScope, 1024, L"file:");
+ wcscat_s(szScope, 1024, szFile);
+ }
+ else
+ wcscpy_s(szScope, 1024, szFile);
+
+ // print bar that separates different files
+ pDisplayString("////////////////////////////////////////////////////////////////\n");
+ wchar_t rcFname[_MAX_FNAME], rcExt[_MAX_EXT];
+
+ _wsplitpath_s(szFile, NULL, 0, NULL, 0, rcFname, _MAX_FNAME, rcExt, _MAX_EXT);
+ sprintf_s(szString,1024,"\nFile %S%S: \n",rcFname, rcExt);
+ pDisplayString(szString);
+
+ if (DumpFilter & MDInfo::dumpValidate)
+ {
+ if (!_wcsicmp(rcExt, OBJ_EXT_W) || !_wcsicmp(rcExt, LIB_EXT_W))
+ g_ValModuleType = ValidatorModuleTypeObj;
+ else
+ g_ValModuleType = ValidatorModuleTypePE;
+ }
+
+ if (!_wcsicmp(rcExt, LIB_EXT_W))
+ DisplayArchive(szFile, DumpFilter, szObjName, pDisplayString);
+ else
+ {
+ MDInfo metaDataInfo(g_pDisp, szScope, pDisplayString, DumpFilter);
+ metaDataInfo.DisplayMD();
+ }
+} // void DisplayFile()
+
diff --git a/src/tools/metainfo/metainfo.cpp b/src/tools/metainfo/metainfo.cpp
new file mode 100644
index 0000000000..0ebca52094
--- /dev/null
+++ b/src/tools/metainfo/metainfo.cpp
@@ -0,0 +1,199 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include <stdio.h>
+#include <ctype.h>
+#include <crtdbg.h>
+#include <utilcode.h>
+#include "mdinfo.h"
+#include <ndpversion.h>
+
+// Provide custom LoadLibrary implementation.
+#define LEGACY_ACTIVATION_SHIM_LOAD_LIBRARY WszLoadLibrary
+#define LEGACY_ACTIVATION_SHIM_DEFINE_CoInitializeEE
+#include "LegacyActivationShim.h"
+
+#ifdef FEATURE_PAL
+#include <palstartupw.h>
+#endif
+
+// Global variables
+bool g_bSchema = false;
+bool g_bRaw = false;
+bool g_bDebug = false;
+bool g_bHeader = false;
+
+// Validator module type.
+DWORD g_ValModuleType = ValidatorModuleTypeInvalid;
+
+IMetaDataImport2 *g_pImport = NULL;
+IMetaDataDispenserEx *g_pDisp = NULL;
+
+void DisplayFile(__in_z __in wchar_t* szFile, BOOL isFile, ULONG DumpFilter, __in_z __in_opt wchar_t* szObjFile, strPassBackFn pDisplayString);
+void DisplayArchive(__in_z __in wchar_t* szFile, ULONG DumpFilter, __in_z __in_opt wchar_t* szObjName, strPassBackFn pDisplayString);
+
+void PrintLogo()
+{
+ printf("Microsoft (R) .Net Frameworks Runtime Meta Data Dump Utility Version %s\n", VER_FILEVERSION_STR);
+ printf("%S", VER_LEGALCOPYRIGHT_LOGO_STR_L);
+ printf("\n");
+}// PrintLogo
+
+void Usage()
+{
+ printf("\n");
+ printf("metainfo [-? | -header | -schema | -raw | -validate] [-nologo] [-obj <obj file name>] [<filname> | <file pattern>]\n");
+ printf(" -? Displays this text.\n");
+ printf(" -hex Prints more things in hex as well as words.\n");
+ printf(" -header Prints MetaData header information and sizes.\n");
+ printf(" -csv Prints the header sizes in Comma Separated format.\n");
+ printf(" -unsat Prints unresolved externals.\n");
+ printf(" -assem Prints only the Assembly information.\n");
+ printf(" -schema Prints the MetaData schema information.\n");
+ printf(" -raw Prints the raw MetaData tables.\n");
+ printf(" -heaps Prints the raw heaps (only if -raw).\n");
+ printf(" -names Prints string columns (only if -raw).\n");
+ printf(" -validate Validate the consistency of the metadata.\n");
+ printf(" -nologo Do not display the logo and MVID.\n");
+ printf(" -obj <objFileName>\n");
+ printf(" Prints the MetaData for the specified obj file in the given \n");
+ printf(" archive(.lib) - e.g metainfo libc.lib -obj wMSILWinCRTStartup.obj\n");
+
+ MDInfo::Error("");
+}
+
+void DisplayString(__in_z __in const char *str)
+{
+ printf("%s", str);
+}
+
+extern "C" int _cdecl wmain(int argc, __in_ecount(argc) WCHAR **argv)
+{
+ wchar_t *pArg = NULL;
+ wchar_t *szObjName = NULL;
+ ULONG DumpFilter = MDInfo::dumpDefault;
+ HRESULT hr = 0;
+ BOOL fWantHelp=FALSE;
+
+#if FEATURE_PAL
+ if (!PAL_RegisterLibrary(L"rotor_palrt") ||
+ !PAL_RegisterLibrary(L"sscoree"))
+ {
+ MDInfo::Error("Unable to register libraries", 1);
+ }
+#endif // FEATURE_PAL
+
+ // Validate incoming arguments
+ for (int i=1; i<argc; i++)
+ {
+ const wchar_t *szArg = argv[i];
+ if (*szArg == L'-' || *szArg == L'/')
+ {
+ if (_wcsicmp(szArg + 1, L"?") == 0)
+ fWantHelp=TRUE;
+
+ else if (_wcsicmp(szArg + 1, L"nologo") == 0)
+ DumpFilter |= MDInfo::dumpNoLogo;
+
+ else if (_wcsicmp(szArg + 1, L"Hex") == 0)
+ DumpFilter |= MDInfo::dumpMoreHex;
+
+ else if (_wcsicmp(szArg + 1, L"header") == 0)
+ DumpFilter |= MDInfo::dumpHeader;
+
+ else if (_wcsicmp(szArg + 1, L"csv") == 0)
+ DumpFilter |= MDInfo::dumpCSV;
+
+ else if (_wcsicmp(szArg + 1, L"raw") == 0)
+ DumpFilter |= MDInfo::dumpRaw;
+
+ else if (_wcsicmp(szArg + 1, L"heaps") == 0)
+ DumpFilter |= MDInfo::dumpRawHeaps;
+
+ else if (_wcsicmp(szArg + 1, L"names") == 0)
+ DumpFilter |= MDInfo::dumpNames;
+
+ else if (_wcsicmp(szArg + 1, L"schema") == 0)
+ DumpFilter |= MDInfo::dumpSchema;
+
+ else if (_wcsicmp(szArg + 1, L"unsat") == 0)
+ DumpFilter |= MDInfo::dumpUnsat;
+
+ else if (_wcsicmp(szArg + 1, L"stats") == 0)
+ DumpFilter |= MDInfo::dumpStats;
+
+ else if (_wcsicmp(szArg + 1, L"assem") == 0)
+ DumpFilter |= MDInfo::dumpAssem;
+
+ else if (_wcsicmp(szArg + 1, L"validate") == 0)
+ DumpFilter |= MDInfo::dumpValidate;
+
+ else if (_wcsicmp(szArg + 1, L"obj") == 0)
+ {
+ if (++i == argc)
+ Usage();
+ else
+ szObjName = argv[i];
+ }
+ }
+ else
+ pArg = argv[i];
+ }
+
+ // Print banner.
+ if (!(DumpFilter & MDInfo::dumpNoLogo))
+ PrintLogo();
+
+
+ if (!pArg || fWantHelp)
+ Usage();
+
+
+#ifndef FEATURE_PAL
+ // Init and run.
+ CoInitialize(0);
+#endif
+
+ LegacyActivationShim::CoInitializeCor(0);
+
+ hr = LegacyActivationShim::ClrCoCreateInstance(
+ CLSID_CorMetaDataDispenser, NULL, CLSCTX_INPROC_SERVER,
+ IID_IMetaDataDispenserEx, (void **) &g_pDisp);
+ if(FAILED(hr)) MDInfo::Error("Unable to CoCreate Meta-data Dispenser", hr);
+
+ // Loop through all files in the file pattern passed
+ WIN32_FIND_DATA fdFiles;
+ HANDLE hFind;
+ wchar_t szSpec[_MAX_PATH];
+ wchar_t szDrive[_MAX_DRIVE];
+ wchar_t szDir[_MAX_DIR];
+
+ hFind = WszFindFirstFile(pArg, &fdFiles);
+
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ DisplayFile(pArg, false, DumpFilter, szObjName, DisplayString);
+ }
+ else
+ {
+ // Convert relative paths to full paths.
+ LPWSTR szFname;
+ WszGetFullPathName(pArg, _MAX_PATH, szSpec, &szFname);
+ SplitPath(szSpec, szDrive, _MAX_DRIVE, szDir, _MAX_DIR, NULL, 0, NULL, 0);
+ do
+ {
+ MakePath(szSpec, szDrive, szDir, fdFiles.cFileName, NULL);
+ // display the meta data of the file
+ DisplayFile(szSpec, true, DumpFilter, szObjName, DisplayString);
+ } while (WszFindNextFile(hFind, &fdFiles)) ;
+ FindClose(hFind);
+ }
+ g_pDisp->Release();
+ LegacyActivationShim::CoUninitializeCor();
+#ifndef FEATURE_PAL
+ CoUninitialize();
+#endif
+ return 0;
+}
diff --git a/src/tools/metainfo/metainfo.nativeproj b/src/tools/metainfo/metainfo.nativeproj
new file mode 100644
index 0000000000..7591a40d63
--- /dev/null
+++ b/src/tools/metainfo/metainfo.nativeproj
@@ -0,0 +1,42 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="dogfood">
+ <!--Import the settings-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.props" />
+ <!--Leaf project Properties-->
+ <PropertyGroup>
+ <OutputName>metainfo</OutputName>
+ <FileToMarkForSigning>$(BinariesDirectory)\metainfo.exe</FileToMarkForSigning>
+ <TargetType>PROGRAM</TargetType>
+ <LinkSubsystem>console</LinkSubsystem>
+ <EntryPoint>wmain</EntryPoint>
+ <ClAdditionalOptions>$(ClAdditionalOptions) -DUNICODE -D_UNICODE</ClAdditionalOptions>
+ <LinkGenerateManifest>true</LinkGenerateManifest>
+ <LinkAdditionalOptions>$(LinkAdditionalOptions) /MANIFEST</LinkAdditionalOptions>
+ </PropertyGroup>
+ <!--Leaf Project Items-->
+ <ItemGroup>
+ <LinkPreCrtLibs Include="$(ClrLibPath)\utilcodenohost.lib">
+ <ProjectReference>$(ClrSrcDirectory)utilcode\dyncrtnohost\dyncrtnohost.nativeproj</ProjectReference>
+ </LinkPreCrtLibs>
+ <LinkPreCrtLibs Include="$(ClrLibPath)\MDHotData.lib" />
+
+ <TargetLib Include="$(ClrLibPath)\corguids.lib" />
+ <TargetLib Include="$(SdkLibPath)\mscoree.lib" />
+ <TargetLib Include="$(SdkLibPath)\ole32.lib" />
+ <TargetLib Include="$(SdkLibPath)\user32.lib" />
+ <TargetLib Include="$(SdkLibPath)\uuid.lib" />
+ <TargetLib Include="$(SdkLibPath)\oleaut32.lib" />
+ <ProjectReference Include="$(ClrSrcDirectory)md\hotdata\full\mdhotdata.nativeproj">
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <RCResourceFile Include="native.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <CppCompile Include="mdinfo.cpp" />
+ <CppCompile Include="mdobj.cpp" />
+ <CppCompile Include="metainfo.cpp" />
+ </ItemGroup>
+ <!--Import the targets-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.targets" />
+</Project>