1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
6 // Assembly and Manifest Disassembler
10 #include "debugmacros.h"
12 #include "dasmenum.hpp"
13 #include "formattype.h"
17 #include "dynamicarray.h"
20 #include "clrinternal.h"
22 #ifndef MAX_LOCALE_NAME
23 #define MAX_LOCALE_NAME (32)
26 extern IMAGE_COR20_HEADER * g_CORHeader;
27 extern IMDInternalImport* g_pImport;
28 extern PELoader * g_pPELoader;
29 extern IMetaDataImport2* g_pPubImport;
30 extern void * g_pMetaData;
31 IMetaDataAssemblyImport* g_pAssemblyImport=NULL;
32 extern BOOL g_fDumpAsmCode;
33 extern char g_szAsmCodeIndent[];
34 extern char g_szOutputFile[];
35 extern BOOL g_fDumpTokens;
38 extern LPCSTR* rAsmRefName; // decl. in formatType.cpp -- for AsmRef aliases
39 extern ULONG ulNumAsmRefs; // decl. in formatType.cpp -- for AsmRef aliases
40 extern unsigned g_uConsoleCP;
41 MTokName* rFile = NULL;
43 void DumpFiles(void* GUICookie)
45 static mdFile rFileTok[4096];
47 if(rFile) { VDELETE(rFile); nFiles = 0; }
48 if(SUCCEEDED(g_pAssemblyImport->EnumFiles(&hEnum,rFileTok,4096,&nFiles)))
52 static WCHAR wzName[1024];
54 const void* pHashValue;
58 rFile = new MTokName[nFiles];
59 for(ULONG ix = 0; ix < nFiles; ix++)
64 if(SUCCEEDED(g_pAssemblyImport->GetFileProps(rFileTok[ix],wzName,1024,&ulNameLen,
65 &pHashValue,&cbHashValue,&dwFlags)))
68 rFile[ix].tok = rFileTok[ix];
69 rFile[ix].name = new WCHAR[ulNameLen+1];
70 memcpy(rFile[ix].name,wzName,ulNameLen*sizeof(WCHAR));
71 rFile[ix].name[ulNameLen] = 0;
73 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s%s ",g_szAsmCodeIndent,KEYWORD(".file"));
74 if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),rFileTok[ix]);
75 if(IsFfContainsNoMetaData(dwFlags)) szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("nometadata "));
77 int L = ulNameLen*3+3;
78 char* sz = new char[L];
80 WszWideCharToMultiByte(CP_UTF8,0,rFile[ix].name,-1,sz,L,NULL,NULL);
81 strcpy_s(szptr,SZSTRING_REMAINING_SIZE(szptr), ANCHORPT(ProperName(sz),rFileTok[ix]));
84 printLine(GUICookie,szString);
85 if(VAL32(IMAGE_COR20_HEADER_FIELD(*g_CORHeader, EntryPointToken)) == rFileTok[ix])
87 printLine(GUICookie, KEYWORD(" .entrypoint"));
89 if(pHashValue && cbHashValue)
91 sprintf_s(szString,SZSTRING_SIZE," %s = (",KEYWORD(".hash"));
92 DumpByteArray(szString,(BYTE*)pHashValue,cbHashValue,GUICookie);
93 printLine(GUICookie,szString);
95 DumpCustomAttributes(rFile[ix].tok, GUICookie);
99 g_pAssemblyImport->CloseEnum(hEnum);
104 void DumpAssemblyMetaData(ASSEMBLYMETADATA* pmd, void* GUICookie)
108 sprintf_s(szString,SZSTRING_SIZE,"%s%s %d:%d:%d:%d",g_szAsmCodeIndent,KEYWORD(".ver"),pmd->usMajorVersion,
109 pmd->usMinorVersion,pmd->usBuildNumber,pmd->usRevisionNumber);
110 printLine(GUICookie,szString);
111 if(pmd->szLocale && pmd->cbLocale)
113 sprintf_s(szString,SZSTRING_SIZE,"%s%s = (",g_szAsmCodeIndent,KEYWORD(".locale"));
114 DumpByteArray(szString,(BYTE*)(pmd->szLocale),pmd->cbLocale*sizeof(WCHAR),GUICookie);
115 printLine(GUICookie,szString);
119 void DumpScope(void* GUICookie)
123 WCHAR scopeName[1024];
124 WCHAR guidString[1024];
125 memset(scopeName,0,1024*sizeof(WCHAR));
126 if(SUCCEEDED(g_pPubImport->GetScopeProps( scopeName, 1024, NULL, &mvid))&& scopeName[0])
129 UINT32 L = (UINT32)wcslen(scopeName)*3+3;
130 char* sz = new char[L];
132 WszWideCharToMultiByte(CP_UTF8,0,scopeName,-1,sz,L,NULL,NULL);
133 sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,KEYWORD(".module"),ProperName(sz));
136 printLine(GUICookie,szString);
137 StringFromGUID2(mvid, guidString, 1024);
139 UINT32 L = (UINT32)wcslen(guidString)*3+3;
140 char* sz = new char[L];
142 WszWideCharToMultiByte(CP_UTF8,0,guidString,-1,sz,L,NULL,NULL);
143 sprintf_s(szString,SZSTRING_SIZE,COMMENT("%s// MVID: %s"),g_szAsmCodeIndent,sz);
146 printLine(GUICookie,szString);
147 if(SUCCEEDED(g_pPubImport->GetModuleFromScope(&mdm)))
149 DumpCustomAttributes(mdm, GUICookie);
150 DumpPermissions(mdm, GUICookie);
155 void DumpModuleRefs(void *GUICookie)
159 static mdToken tk[4096];
163 g_pPubImport->EnumModuleRefs(&hEnum,tk,4096,&N);
164 for(ULONG i = 0; i < N; i++)
166 if(RidFromToken(tk[i]))
168 if (FAILED(g_pImport->GetModuleRefProps(tk[i],&szName)))
172 if (*szName != 0) // ignore the no-name ModuleRef: it's an IJW artifact
174 szptr = &szString[0];
175 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,KEYWORD(".module extern"),
176 ANCHORPT(ProperName((char*)szName),tk[i]));
177 if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT(" /*%08X*/"),tk[i]);
178 printLine(GUICookie,szString);
179 DumpCustomAttributes(tk[i], GUICookie);
180 DumpPermissions(tk[i], GUICookie);
184 g_pPubImport->CloseEnum(hEnum);
187 void DumpAssembly(void* GUICookie, BOOL fFullDump)
190 if(SUCCEEDED(g_pAssemblyImport->GetAssemblyFromScope(&tkAsm))&&(tkAsm != mdAssemblyNil))
192 const void* pPublicKey;
193 ULONG cbPublicKey = 0;
198 WCHAR wzLocale[MAX_LOCALE_NAME];
202 md.szLocale = wzLocale;
203 md.cbLocale = MAX_LOCALE_NAME;
204 md.rProcessor = NULL;
209 if(SUCCEEDED(g_pAssemblyImport->GetAssemblyProps( // S_OK or error.
210 tkAsm, // [IN] The Assembly for which to get the properties.
211 &pPublicKey, // [OUT] Pointer to the public key.
212 &cbPublicKey,// [OUT] Count of bytes in the public key.
213 &ulHashAlgId,// [OUT] Hash Algorithm.
214 wzName, // [OUT] Buffer to fill with name.
215 1024, // [IN] Size of buffer in wide chars.
216 &ulNameLen, // [OUT] Actual # of wide chars in name.
217 &md, // [OUT] Assembly MetaData.
218 &dwFlags))) // [OUT] Flags.
220 if(ulNameLen >= 1024)
222 strcpy_s(szString,SZSTRING_SIZE,RstrUTF(IDS_ASSEMNAMETOOLONG));
223 printError(GUICookie,szString);
226 szptr = &szString[0];
227 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".assembly"));
228 if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),tkAsm);
230 if(IsAfRetargetable(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("retargetable "));
231 if(IsAfContentType_WindowsRuntime(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("windowsruntime "));
232 if(IsAfPA_NoPlatform(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("noplatform "));
233 if(IsAfPA_MSIL(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("cil "));
234 if(IsAfPA_x86(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("x86 "));
235 if(IsAfPA_IA64(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("ia64 "));
236 if(IsAfPA_AMD64(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("amd64 "));
239 wzName[ulNameLen] = 0;
241 char* sz = new char[3*ulNameLen+3];
242 memset(sz,0,3*ulNameLen+3);
243 WszWideCharToMultiByte(CP_UTF8,0,wzName,-1,sz,3*ulNameLen+3,NULL,NULL);
244 strcat_s(szString,SZSTRING_SIZE,ANCHORPT(ProperName(sz),tkAsm));
247 printLine(GUICookie,szString);
248 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
249 printLine(GUICookie,szString);
250 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
253 DumpCustomAttributes(tkAsm, GUICookie);
254 DumpPermissions(tkAsm, GUICookie);
259 if(pPublicKey && cbPublicKey)
261 sprintf_s(szString,SZSTRING_SIZE,"%s%s = (",g_szAsmCodeIndent,KEYWORD(".publickey"));
262 DumpByteArray(szString,(BYTE*)pPublicKey,cbPublicKey,GUICookie);
263 printLine(GUICookie,szString);
267 sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%08X",g_szAsmCodeIndent,KEYWORD(".hash algorithm"),ulHashAlgId);
268 printLine(GUICookie,szString);
271 DumpAssemblyMetaData(&md,GUICookie);
272 g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
273 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
274 printLine(GUICookie,szString);
275 } //end if(OK(GetAssemblyProps))
276 } //end if(OK(GetAssemblyFromScope))
279 MTokName* rAsmRef = NULL;
282 void DumpAssemblyRefs(void* GUICookie)
284 static mdAssemblyRef rAsmRefTok[4096];
287 if(rAsmRef) { VDELETE(rAsmRef); nAsmRefs = 0; }
290 for(ix=0; ix < ulNumAsmRefs; ix++)
292 if(rAsmRefName[ix]) VDELETE(rAsmRefName[ix]);
294 VDELETE(rAsmRefName);
298 if(SUCCEEDED(g_pAssemblyImport->EnumAssemblyRefs(&hEnum,rAsmRefTok,4096,&nAsmRefs)))
302 const void* pPublicKeyOrToken;
303 ULONG cbPublicKeyOrToken = 0;
304 const void* pHashValue;
306 static WCHAR wzName[1024];
309 WCHAR wzLocale[MAX_LOCALE_NAME];
312 rAsmRef = new MTokName[nAsmRefs];
313 rAsmRefName = new LPCSTR[nAsmRefs];
314 ulNumAsmRefs = nAsmRefs;
316 for(ix = 0; ix < nAsmRefs; ix++)
318 md.szLocale = wzLocale;
319 md.cbLocale = MAX_LOCALE_NAME;
320 md.rProcessor = NULL;
325 ulNameLen=cbHashValue=0;
327 if(SUCCEEDED(g_pAssemblyImport->GetAssemblyRefProps( // S_OK or error.
328 rAsmRefTok[ix], // [IN] The Assembly for which to get the properties.
329 &pPublicKeyOrToken, // [OUT] Pointer to the public key or token.
330 &cbPublicKeyOrToken,// [OUT] Count of bytes in the public key or token.
331 wzName, // [OUT] Buffer to fill with name.
332 1024, // [IN] Size of buffer in wide chars.
333 &ulNameLen, // [OUT] Actual # of wide chars in name.
334 &md, // [OUT] Assembly MetaData.
335 &pHashValue, // [OUT] Hash blob.
336 &cbHashValue,// [OUT] Count of bytes in the hash blob.
337 &dwFlags))) // [OUT] Flags.
340 rAsmRef[ix].tok = rAsmRefTok[ix];
341 rAsmRef[ix].name = new WCHAR[ulNameLen+16];
342 memcpy(rAsmRef[ix].name,wzName,ulNameLen*sizeof(WCHAR));
343 rAsmRef[ix].name[ulNameLen] = 0;
344 if(ulNameLen >= 1024)
346 strcpy_s(szString,SZSTRING_SIZE,RstrUTF(IDS_ASMREFNAMETOOLONG));
347 printError(GUICookie,szString);
351 sprintf_s(szString,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".assembly extern"));
352 if(g_fDumpTokens) sprintf_s(&szString[strlen(szString)],SZSTRING_SIZE-strlen(szString),COMMENT("/*%08X*/ "),rAsmRefTok[ix]);
354 if(IsAfRetargetable(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("retargetable "));
355 if(IsAfContentType_WindowsRuntime(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("windowsruntime "));
356 if(IsAfPA_MSIL(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("cil "));
357 if(IsAfPA_x86(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("x86 "));
358 if(IsAfPA_IA64(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("ia64 "));
359 if(IsAfPA_AMD64(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("amd64 "));
362 char* sz = new char[3*ulNameLen+32];
363 memset(sz,0,3*ulNameLen+3);
364 WszWideCharToMultiByte(CP_UTF8,0,rAsmRef[ix].name,-1,sz,3*ulNameLen+3,NULL,NULL);
365 // check for name duplication and introduce alias if needed
366 for(ixx = 0; ixx < ix; ixx++)
368 if(!wcscmp(rAsmRef[ixx].name,rAsmRef[ix].name)) break;
372 strcat_s(szString,SZSTRING_SIZE, ProperName(sz));
373 char* pc=&szString[strlen(szString)];
374 sprintf_s(&sz[strlen(sz)],3*ulNameLen+32-strlen(sz),"_%d",ix);
375 sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc)," %s %s", KEYWORD("as"),ANCHORPT(ProperName(sz),rAsmRefTok[ix]));
378 strcat_s(szString,SZSTRING_SIZE, ANCHORPT(ProperName(sz),rAsmRefTok[ix]));
379 rAsmRefName[ix] = sz;
381 printLine(GUICookie,szString);
382 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
383 printLine(GUICookie,szString);
384 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
385 DumpCustomAttributes(rAsmRefTok[ix], GUICookie);
386 if(pPublicKeyOrToken && cbPublicKeyOrToken)
388 if (IsAfPublicKey(dwFlags))
389 sprintf_s(szString,SZSTRING_SIZE,"%s%s = (",g_szAsmCodeIndent,KEYWORD(".publickey"));
391 sprintf_s(szString,SZSTRING_SIZE,"%s%s = (",g_szAsmCodeIndent,KEYWORD(".publickeytoken"));
392 DumpByteArray(szString,(BYTE*)pPublicKeyOrToken,cbPublicKeyOrToken,GUICookie);
393 printLine(GUICookie,szString);
395 if(pHashValue && cbHashValue)
397 sprintf_s(szString,SZSTRING_SIZE,"%s%s = (",g_szAsmCodeIndent,KEYWORD(".hash"));
398 DumpByteArray(szString,(BYTE*)pHashValue,cbHashValue,GUICookie);
399 printLine(GUICookie,szString);
401 DumpAssemblyMetaData(&md,GUICookie);
402 g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
403 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
404 printLine(GUICookie,szString);
405 } //end if(OK(GetAssemblyRefProps))
406 }//end for(all assembly refs)
408 g_pAssemblyImport->CloseEnum(hEnum);
409 }//end if OK(EnumAssemblyRefs)
413 DynamicArray<LocalComTypeDescr*> *g_pLocalComType = NULL;
414 ULONG g_LocalComTypeNum = 0;
417 LocalComTypeDescr* pCTD,
418 __inout __nullterminated char* szName)
420 if(TypeFromToken(pCTD->tkImplementation) == mdtExportedType)
423 for(i = 0; (i < g_LocalComTypeNum) && ((*g_pLocalComType)[i]->tkComTypeTok != pCTD->tkImplementation); i++);
424 if(i < g_LocalComTypeNum)
426 DumpComTypeFQN((*g_pLocalComType)[i], szName);
427 strcat_s(szName, SZSTRING_SIZE, "/");
431 UINT32 L = (UINT32)wcslen(pCTD->wzName)*3+3;
432 char* sz = new char[L];
434 WszWideCharToMultiByte(CP_UTF8,0,pCTD->wzName,-1,sz,L,NULL,NULL);
435 strcat_s(szName, SZSTRING_SIZE, JUMPPT(ProperName(sz), pCTD->tkComTypeTok));
439 void DumpImplementation(mdToken tkImplementation,
441 __inout __nullterminated char* szString,
446 if(RidFromToken(tkImplementation))
448 if(TypeFromToken(tkImplementation) == mdtFile)
450 for(i=0; (i < nFiles)&&(rFile[i].tok != tkImplementation); i++);
454 UINT32 L = (UINT32)wcslen(rFile[i].name)*3+3;
455 char* sz = new char[L];
457 WszWideCharToMultiByte(CP_UTF8,0,rFile[i].name,-1,sz,L,NULL,NULL);
458 sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,KEYWORD(".file"),
459 JUMPPT(ProperName(sz),tkImplementation));
462 pc=&szString[strlen(szString)];
463 if(g_fDumpTokens) pc+=sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc),COMMENT("/*%08X*/ "),tkImplementation);
464 if(dwOffset != 0xFFFFFFFF) sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc)," %s 0x%08X",KEYWORD("at"),dwOffset);
465 printLine(GUICookie,szString);
468 else if(TypeFromToken(tkImplementation) == mdtAssemblyRef)
470 for(i=0; (i < nAsmRefs)&&(rAsmRef[i].tok != tkImplementation); i++);
474 UINT32 L = (UINT32)wcslen(rAsmRef[i].name)*3+3;
475 char* sz = new char[L];
477 WszWideCharToMultiByte(CP_UTF8,0,rAsmRef[i].name,-1,sz,L,NULL,NULL);
478 sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,KEYWORD(".assembly extern"),
479 JUMPPT(ProperName(sz),tkImplementation));
482 pc=&szString[strlen(szString)];
483 if(g_fDumpTokens) sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc),COMMENT(" /*%08X*/ "),tkImplementation);
484 printLine(GUICookie,szString);
487 else if(TypeFromToken(tkImplementation) == mdtExportedType)
489 // Find the type structure corresponding to this token
490 for(i=0; (i < g_LocalComTypeNum)&&((*g_pLocalComType)[i]->tkComTypeTok != tkImplementation); i++);
491 if(i < g_LocalComTypeNum)
493 sprintf_s(szString,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".class extern"));
494 DumpComTypeFQN((*g_pLocalComType)[i], szString);
496 pc=&szString[strlen(szString)];
497 if(g_fDumpTokens) sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc),COMMENT(" /*%08X*/ "),tkImplementation);
498 printLine(GUICookie,szString);
504 void DumpComType(LocalComTypeDescr* pCTD,
505 __inout __nullterminated char* szString,
508 if(g_fDumpTokens) sprintf_s(&szString[strlen(szString)],SZSTRING_SIZE-strlen(szString),COMMENT("/*%08X*/ "),pCTD->tkComTypeTok);
509 if (IsTdPublic(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("public "));
510 if (IsTdForwarder(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("forwarder "));
511 if (IsTdNestedPublic(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("nested public "));
512 if (IsTdNestedPrivate(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("nested private "));
513 if (IsTdNestedFamily(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("nested family "));
514 if (IsTdNestedAssembly(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("nested assembly "));
515 if (IsTdNestedFamANDAssem(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("nested famandassem "));
516 if (IsTdNestedFamORAssem(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("nested famorassem "));
518 char* pc=&szString[strlen(szString)];
520 UINT32 L = (UINT32)wcslen(pCTD->wzName)*3+3;
521 char* sz = new char[L];
523 WszWideCharToMultiByte(CP_UTF8,0,pCTD->wzName,-1,sz,L,NULL,NULL);
524 strcpy_s(pc,SZSTRING_REMAINING_SIZE(pc),ANCHORPT(ProperName(sz),pCTD->tkComTypeTok));
527 printLine(GUICookie,szString);
529 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
530 printLine(GUICookie,szString);
531 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
532 DumpCustomAttributes(pCTD->tkComTypeTok, GUICookie);
533 DumpImplementation(pCTD->tkImplementation,0xFFFFFFFF,szString,GUICookie);
534 if(RidFromToken(pCTD->tkTypeDef))
536 sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%08X",g_szAsmCodeIndent,KEYWORD(".class"),pCTD->tkTypeDef);
537 printLine(GUICookie,szString);
539 g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
540 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
541 printLine(GUICookie,szString);
545 void DumpComTypes(void* GUICookie)
547 static mdExportedType rComTypeTok[4096];
551 g_LocalComTypeNum = 0;
552 if(SUCCEEDED(g_pAssemblyImport->EnumExportedTypes(&hEnum,rComTypeTok,4096,&nComTypes)))
556 static WCHAR wzName[1024];
559 mdToken tkImplementation;
563 for(ix = 0; ix < nComTypes; ix++)
566 if(SUCCEEDED(g_pAssemblyImport->GetExportedTypeProps( // S_OK or error.
567 rComTypeTok[ix], // [IN] The ComType for which to get the properties.
568 wzName, // [OUT] Buffer to fill with name.
569 1024, // [IN] Size of buffer in wide chars.
570 &ulNameLen, // [OUT] Actual # of wide chars in name.
571 &tkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ComType.
572 &tkTypeDef, // [OUT] TypeDef token within the file.
573 &dwFlags))) // [OUT] Flags.
575 LocalComTypeDescr* pCTD = new LocalComTypeDescr;
576 memset(pCTD,0,sizeof(LocalComTypeDescr));
577 pCTD->tkComTypeTok = rComTypeTok[ix];
578 pCTD->tkTypeDef = tkTypeDef;
579 pCTD->tkImplementation = tkImplementation;
580 pCTD->wzName = new WCHAR[ulNameLen+1];
581 memcpy(pCTD->wzName,wzName,ulNameLen*sizeof(WCHAR));
582 pCTD->wzName[ulNameLen] = 0;
583 pCTD->dwFlags = dwFlags;
585 if (g_pLocalComType == NULL)
587 g_pLocalComType = new DynamicArray<LocalComTypeDescr*>;
590 (*g_pLocalComType)[g_LocalComTypeNum] = pCTD;
592 } //end if(OK(GetComTypeProps))
593 }//end for(all com types)
595 // now, print all "external" com types
596 for(ix = 0; ix < nComTypes; ix++)
598 tkImplementation = (*g_pLocalComType)[ix]->tkImplementation;
599 // ComType of a nested class has its nester's ComType as implementation
600 while(TypeFromToken(tkImplementation)==mdtExportedType)
603 for(k=0; k<g_LocalComTypeNum; k++)
605 if((*g_pLocalComType)[k]->tkComTypeTok == tkImplementation)
607 tkImplementation = (*g_pLocalComType)[k]->tkImplementation;
611 if(k==g_LocalComTypeNum) break;
613 // At this moment, tkImplementation is impl.of top nester
614 if(RidFromToken(tkImplementation))
616 sprintf_s(szString,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".class extern"));
617 DumpComType((*g_pLocalComType)[ix],szString,GUICookie);
618 (*g_pLocalComType)[ix]->tkTypeDef = 0;
622 g_pAssemblyImport->CloseEnum(hEnum);
623 }//end if OK(EnumComTypes)
627 // Replaces invalid characters and neutralizes reserved file names.
628 // Returns TRUE if the string was modified, FALSE otherwise.
629 static BOOL ConvertToLegalFileNameInPlace(__inout LPWSTR wzName)
633 // neutralize reserved names
634 static const WCHAR * const rwzReserved[] =
636 W("COM"), W("LPT"), // '1' - '9' must follow after these
637 W("CON"), W("PRN"), W("AUX"), W("NUL")
640 for (size_t i = 0; i < (sizeof(rwzReserved) / sizeof(WCHAR *)); i++)
642 _ASSERTE(wcslen(rwzReserved[i]) == 3);
643 if (_wcsnicmp(wzName, rwzReserved[i], 3) == 0)
645 LPWSTR pwc = wzName + 3;
647 if (i <= 1) // COM, LPT
649 if (*pwc >= L'1' && *pwc <= L'9')
657 // check for . or end of string
658 if (*pwc == L'.' || *pwc == 0)
667 // replace invalid characters
672 if (wch > 0 && wch < 32)
681 #define REPLACE_CH(oldCh, newCh) \
682 case oldCh: *wzName = newCh; \
686 REPLACE_CH(L':', L'!')
687 REPLACE_CH(L'\\', L'$')
688 REPLACE_CH(L',', L'&') // not necessary but keeping for back compat
689 REPLACE_CH(L';', L'@') // not necessary but keeping for back compat
690 REPLACE_CH(L'<', L'(')
691 REPLACE_CH(L'>', L')')
692 REPLACE_CH(L'"', L'`')
693 REPLACE_CH(L'/', L'_')
694 REPLACE_CH(L'|', L'-')
695 REPLACE_CH(L'*', L'+') // disallowed wildcard
696 REPLACE_CH(L'?', L'=') // disallowed wildcard
698 case 0: return fAlias;
705 // Dumps managed resource at pRes + dwOffset to a file.
706 static void DumpResourceFile(void *GUICookie, BYTE *pRes, DWORD dwOffset, LPCWSTR wzName,
707 LPCWSTR wzFileName, LPCUTF8 sz)
715 const WCHAR *wzFileName;
718 param.dwOffset = dwOffset;
720 param.GUICookie = GUICookie;
721 param.wzFileName = wzFileName;
723 PAL_TRY(Param *, pParam, ¶m)
726 memcpy(&L,pParam->pRes+pParam->dwOffset,sizeof(DWORD));
727 sprintf_s(szString,SZSTRING_SIZE,COMMENT("%s// Offset: 0x%8.8X Length: 0x%8.8X"), g_szAsmCodeIndent,pParam->dwOffset,L);
728 printLine(pParam->GUICookie,szString);
729 if (g_pFile != NULL) // embedded resource -- dump as .resources file
732 _wfopen_s(&pF, pParam->wzFileName, W("wb"));
744 param.pRes = pParam->pRes;
745 param.dwOffset = pParam->dwOffset;
748 param.sz = pParam->sz;
749 param.GUICookie = pParam->GUICookie;
751 PAL_TRY(Param *, pParam, ¶m) {
752 fwrite((pParam->pRes+pParam->dwOffset+sizeof(DWORD)),pParam->L,1,pParam->pF);
753 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_W_CREATEDMRES),g_szAsmCodeIndent,ProperName(pParam->sz));
754 printLine(pParam->GUICookie,COMMENT(szString));
756 PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
758 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_READINGMRES),g_szAsmCodeIndent,ProperName(pParam->sz),pParam->dwOffset);
759 printError(pParam->GUICookie,szString);
766 PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
768 sprintf_s(szString, SZSTRING_SIZE,
769 "ERROR retrieving/saving embedded managed resource '%s' at offset 0x%8.8X",
770 UnicodeToUtf(wzName), dwOffset);
771 printError(GUICookie, szString);
776 void DumpManifestResources(void* GUICookie)
778 static mdManifestResource rManResTok[4096];
782 if(SUCCEEDED(g_pAssemblyImport->EnumManifestResources(&hEnum,rManResTok,4096,&nManRes)))
786 WCHAR* wzName = NULL;
789 static char sz[4096];
790 mdToken tkImplementation;
793 static WCHAR wzFileName[2048];
795 WszMultiByteToWideChar(CP_UTF8,0,g_szOutputFile,-1,wzFileName,2048);
796 wzName = wcsrchr(wzFileName,'\\');
797 if(wzName == NULL) wzName = wcsrchr(wzFileName,':');
798 if (wzName == NULL) wzName = wzFileName;
801 // remember the file names created so far to avoid duplicates
802 CQuickArray<CQuickWSTRBase> qbNameArray;
803 if (!qbNameArray.AllocNoThrow(nManRes + 2))
805 sprintf_s(szString, SZSTRING_SIZE,
806 "ERROR retrieving/saving embedded managed resource '%s'", UnicodeToUtf(wzName));
807 printError(GUICookie, szString);
811 #define NAME_ARRAY_ADD(index, str) \
813 size_t __dwBufLen = wcslen(str) + 1; \
815 qbNameArray[index].Init(); \
816 WCHAR *__wpc = (WCHAR *)qbNameArray[index].AllocNoThrow(__dwBufLen); \
817 if (__wpc) wcscpy_s(__wpc, __dwBufLen, str); \
820 // add the output file name to avoid conflict between the IL file and a resource file
821 NAME_ARRAY_ADD(0, wzName);
823 // add the Win32 resource file name to avoid conflict between the native and a managed resource file
824 WCHAR *pwc = wcsrchr(wzName, L'.');
825 if (pwc == NULL) pwc = &wzName[wcslen(wzName)];
826 wcscpy_s(pwc, 2048 - (pwc - wzFileName), W(".res"));
828 NAME_ARRAY_ADD(1, wzName);
830 for(ULONG ix = 0; ix < nManRes; ix++)
833 if(SUCCEEDED(g_pAssemblyImport->GetManifestResourceProps( // S_OK or error.
834 rManResTok[ix], // [IN] The ManifestResource for which to get the properties.
835 wzName, // [OUT] Buffer to fill with name.
836 1024, // [IN] Size of buffer in wide chars.
837 &ulNameLen, // [OUT] Actual # of wide chars in name.
838 &tkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ComType.
839 &dwOffset, // [OUT] Offset to the beginning of the resource within the file.
840 &dwFlags))) // [OUT] Flags.
842 sprintf_s(szString,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".mresource"));
843 if(g_fDumpTokens) sprintf_s(&szString[strlen(szString)],SZSTRING_SIZE-strlen(szString),COMMENT("/*%08X*/ "),rManResTok[ix]);
844 if(IsMrPublic(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("public "));
845 if(IsMrPrivate(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("private "));
847 char* pc = szString + strlen(szString);
850 WszWideCharToMultiByte(CP_UTF8,0,wzName,-1,sz,sizeof(sz),NULL,NULL);
851 strcpy_s(pc,SZSTRING_REMAINING_SIZE(pc),ProperName(sz));
853 // get rid of invalid characters and reserved names
854 BOOL fAlias = ConvertToLegalFileNameInPlace(wzName);
856 // check for duplicate file name
857 WCHAR *wpc = wzName + wcslen(wzName);
858 for (int iIndex = 1;; iIndex++)
860 BOOL fConflict = FALSE;
863 // resource with an empty name
868 for (ULONG i = 0; i < (ix + 2); i++)
870 WCHAR *wzPreviousName = (WCHAR *)qbNameArray[i].Ptr();
871 if (wzPreviousName && _wcsicmp(wzName, wzPreviousName) == 0)
873 // resource with the same name as another resource
874 // or with the same name as the output IL/RES file
881 // if we have a conflict, add a number suffix to the file name
883 swprintf_s(wpc, 2048 - (wpc - wzFileName), W("%d"), iIndex) <= 0)
885 // no conflict or unable to add index
889 // try again with this new number suffix
893 // add this unique file name to the list
894 NAME_ARRAY_ADD(ix + 2, wzName);
898 // update sz with the aliased name and print the 'as' keyword
899 if (WszWideCharToMultiByte(CP_UTF8, 0, wzName, -1, sz, sizeof(sz), NULL, NULL) == 0)
901 sz[sizeof(sz) - 1] = 0;
904 pc=&szString[strlen(szString)];
905 sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc)," %s %s",KEYWORD("as"),ProperName(sz));
908 printLine(GUICookie,szString);
909 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
910 printLine(GUICookie,szString);
911 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
912 DumpCustomAttributes(rManResTok[ix], GUICookie);
914 if(tkImplementation == mdFileNil) // embedded resource -- dump as .resources file
918 // get the resource VA
919 if (g_pPELoader->getVAforRVA((DWORD) VAL32(g_CORHeader->Resources.VirtualAddress), (void **) &pRes) == FALSE)
921 printError(GUICookie,RstrUTF(IDS_E_IMPORTDATA));
926 DumpResourceFile(GUICookie, pRes, dwOffset, wzName, wzFileName, sz);
929 else DumpImplementation(tkImplementation,dwOffset,szString,GUICookie);
930 g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
931 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
932 printLine(GUICookie,szString);
933 } //end if(OK(GetManifestResourceProps))
934 }//end for(all manifest resources)
936 #undef NAME_ARRAY_ADD
939 g_pAssemblyImport->CloseEnum(hEnum);
940 }//end if OK(EnumManifestResources)
944 IMetaDataAssemblyImport* GetAssemblyImport(void* GUICookie)
949 IMetaDataAssemblyImport* pAssemblyImport;
950 IMDInternalImport* pImport;
953 param.GUICookie = GUICookie;
954 param.pAssemblyImport = NULL;
955 param.pImport = NULL;
959 hr=g_pPubImport->QueryInterface(IID_IMetaDataAssemblyImport, (void**) ¶m.pAssemblyImport);
962 static mdAssemblyRef rAsmRefTok[4096];
965 if(SUCCEEDED(param.pAssemblyImport->GetAssemblyFromScope(¶m.tkManifest))) return param.pAssemblyImport;
966 if(SUCCEEDED(param.pAssemblyImport->EnumAssemblyRefs(&hEnum,rAsmRefTok,4096,&nAsmRefs)))
968 param.pAssemblyImport->CloseEnum(hEnum);
969 if(nAsmRefs) return param.pAssemblyImport;
971 param.pAssemblyImport->Release();
975 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_MDAIMPORT),hr);
976 printLine(GUICookie,COMMENT(szString));
978 param.pAssemblyImport = NULL;
979 // OK, let's do it hard way: check if the manifest is hidden somewhere else
980 PAL_TRY(Param *, pParam, ¶m)
982 if(g_CORHeader->Resources.Size)
984 DWORD* pdwSize = NULL;
985 BYTE* pbManifest = NULL;
988 pbManifest = (BYTE*)(g_pPELoader->base() + (DWORD)VAL32(g_CORHeader->Resources.VirtualAddress));
989 pdwSize = (DWORD*)pbManifest;
990 if(pdwSize && *pdwSize)
992 pbManifest += sizeof(DWORD);
993 if (SUCCEEDED(hr = getMetaDataInternalInterface(
997 IID_IMDInternalImport,
998 (LPVOID *)&pParam->pImport)))
1000 if (FAILED(hr = getMetaDataPublicInterfaceFromInternal(
1002 IID_IMetaDataAssemblyImport,
1003 (LPVOID *)&pParam->pAssemblyImport)))
1005 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_MDAFROMMDI),hr);
1006 printLine(pParam->GUICookie,COMMENT(szString));
1007 pParam->pAssemblyImport = NULL;
1011 mdAssemblyRef rAsmRefTok[4096];
1012 HCORENUM hEnum=NULL;
1014 if(FAILED(pParam->pAssemblyImport->GetAssemblyFromScope(&pParam->tkManifest))
1015 && (FAILED(pParam->pAssemblyImport->EnumAssemblyRefs(&hEnum,rAsmRefTok,4096,&nAsmRefs))
1018 pParam->pAssemblyImport->CloseEnum(hEnum);
1019 pParam->pAssemblyImport->Release();
1020 pParam->pAssemblyImport = NULL;
1023 pParam->pImport->Release();
1027 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_MDIIMPORT),hr);
1028 printLine(pParam->GUICookie,COMMENT(szString));
1033 PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1035 if(param.pAssemblyImport) param.pAssemblyImport->Release();
1036 param.pAssemblyImport = NULL;
1037 if(param.pImport) param.pImport->Release();
1040 return param.pAssemblyImport;
1043 static void DumpMetadataVersion(void* GUICookie)
1046 if (g_pImport == NULL || FAILED(g_pImport->GetVersionString(&pVersionStr)))
1048 pVersionStr = "**Unavailable**";
1050 sprintf_s(szString,SZSTRING_SIZE,"// Metadata version: %s",pVersionStr);
1051 printLine(GUICookie,szString);
1054 void DumpManifest(void* GUICookie)
1056 DumpMetadataVersion(GUICookie);
1057 DumpModuleRefs(GUICookie);
1058 if(g_pAssemblyImport==NULL) g_pAssemblyImport = GetAssemblyImport(GUICookie);
1059 if(g_pAssemblyImport)
1061 DumpAssemblyRefs(GUICookie);
1062 DumpAssembly(GUICookie,TRUE);
1063 DumpFiles(GUICookie);
1064 DumpComTypes(GUICookie);
1065 DumpManifestResources(GUICookie);
1067 else printLine(GUICookie,COMMENT(RstrUTF(IDS_E_NOMANIFEST)));
1068 DumpScope(GUICookie);
1069 DumpVtable(GUICookie);