diff options
Diffstat (limited to 'src/ildasm/dman.cpp')
-rw-r--r-- | src/ildasm/dman.cpp | 1091 |
1 files changed, 1091 insertions, 0 deletions
diff --git a/src/ildasm/dman.cpp b/src/ildasm/dman.cpp new file mode 100644 index 0000000000..d0b525556b --- /dev/null +++ b/src/ildasm/dman.cpp @@ -0,0 +1,1091 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// 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 "ceeload.h" +#include "dynamicarray.h" +#include "resource.h" + +#include "clrinternal.h" + +#ifndef MAX_LOCALE_NAME +#define MAX_LOCALE_NAME (32) +#endif + +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[] = + { + W("COM"), W("LPT"), // '1' - '9' must follow after these + W("CON"), W("PRN"), W("AUX"), W("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, ¶m) + { + 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, W("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, ¶m) { + 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), W(".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), W("%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; +} + +#ifndef FEATURE_CORECLR +// CLR internal hosting API +extern ICLRRuntimeHostInternal *g_pCLRRuntimeHostInternal; +#endif + +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**) ¶m.pAssemblyImport); + if(SUCCEEDED(hr)) + { + static mdAssemblyRef rAsmRefTok[4096]; + HCORENUM hEnum=NULL; + ULONG nAsmRefs = 0; + if(SUCCEEDED(param.pAssemblyImport->GetAssemblyFromScope(¶m.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, ¶m) + { + 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); +#ifdef FEATURE_CORECLR + if (SUCCEEDED(hr = getMetaDataInternalInterface( + pbManifest, + VAL32(*pdwSize), + ofRead, + IID_IMDInternalImport, + (LPVOID *)&pParam->pImport))) + { + if (FAILED(hr = getMetaDataPublicInterfaceFromInternal( + pParam->pImport, + IID_IMetaDataAssemblyImport, + (LPVOID *)&pParam->pAssemblyImport))) +#else + 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))) +#endif + { + 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); + +} |