Merge pull request #12216 from ellismg/fix-warnings
[platform/upstream/coreclr.git] / src / ildasm / dman.cpp
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.
4
5 //
6 // Assembly and Manifest Disassembler
7 //
8 #include "ildasmpch.h"
9
10 #include "debugmacros.h"
11 #include "corpriv.h"
12 #include "dasmenum.hpp"
13 #include "formattype.h"
14 #include "dis.h"
15
16 #include "ceeload.h"
17 #include "dynamicarray.h"
18 #include "resource.h"
19
20 #include "clrinternal.h"
21
22 #ifndef MAX_LOCALE_NAME
23 #define MAX_LOCALE_NAME (32)
24 #endif
25
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;
36 extern DWORD    g_Mode;
37 extern FILE*    g_pFile;
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;
42 ULONG   nFiles = 0;
43 void DumpFiles(void* GUICookie)
44 {
45     static mdFile      rFileTok[4096];
46     HCORENUM    hEnum=NULL;
47     if(rFile) { VDELETE(rFile); nFiles = 0; }
48     if(SUCCEEDED(g_pAssemblyImport->EnumFiles(&hEnum,rFileTok,4096,&nFiles)))
49     {
50         if(nFiles)
51         {
52             static WCHAR       wzName[1024];
53             ULONG       ulNameLen;
54             const void* pHashValue;
55             ULONG       cbHashValue;
56             DWORD       dwFlags;
57             char*       szptr;
58             rFile = new MTokName[nFiles];
59             for(ULONG ix = 0; ix < nFiles; ix++)
60             {
61                 pHashValue=NULL;
62                 cbHashValue=0;
63                 ulNameLen=0;
64                 if(SUCCEEDED(g_pAssemblyImport->GetFileProps(rFileTok[ix],wzName,1024,&ulNameLen,
65                                                             &pHashValue,&cbHashValue,&dwFlags)))
66                 {
67                     szptr = &szString[0];
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;
72
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 "));
76                     {
77                         int L = ulNameLen*3+3;
78                         char* sz = new char[L];
79                         memset(sz,0,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]));
82                         VDELETE(sz);
83                     }
84                     printLine(GUICookie,szString);
85                     if(VAL32(IMAGE_COR20_HEADER_FIELD(*g_CORHeader, EntryPointToken)) == rFileTok[ix])
86                     {
87                         printLine(GUICookie, KEYWORD("    .entrypoint"));
88                     }
89                     if(pHashValue && cbHashValue)
90                     {
91                         sprintf_s(szString,SZSTRING_SIZE,"    %s = (",KEYWORD(".hash"));
92                         DumpByteArray(szString,(BYTE*)pHashValue,cbHashValue,GUICookie);
93                         printLine(GUICookie,szString);
94                     }
95                     DumpCustomAttributes(rFile[ix].tok, GUICookie);
96                 }
97             }
98         }
99         g_pAssemblyImport->CloseEnum(hEnum);
100     }
101     else nFiles=0;
102 }
103
104 void DumpAssemblyMetaData(ASSEMBLYMETADATA* pmd, void* GUICookie)
105 {
106     if(pmd)
107     {
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)
112         {
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);
116         }
117     }
118 }
119 void DumpScope(void* GUICookie)
120 {
121     mdModule mdm;
122     GUID mvid;
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])
127     {
128         {
129             UINT32 L = (UINT32)wcslen(scopeName)*3+3;
130             char* sz = new char[L];
131             memset(sz,0,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));
134             VDELETE(sz);
135         }
136         printLine(GUICookie,szString);
137         StringFromGUID2(mvid, guidString, 1024);
138         {
139             UINT32 L = (UINT32)wcslen(guidString)*3+3;
140             char* sz = new char[L];
141             memset(sz,0,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);
144             VDELETE(sz);
145         }
146         printLine(GUICookie,szString);
147         if(SUCCEEDED(g_pPubImport->GetModuleFromScope(&mdm)))
148         {
149             DumpCustomAttributes(mdm, GUICookie);
150             DumpPermissions(mdm, GUICookie);
151         }
152     }
153 }
154
155 void DumpModuleRefs(void *GUICookie)
156 {
157     HCORENUM        hEnum=NULL;
158     ULONG           N;
159     static mdToken         tk[4096];
160     char*           szptr;
161     LPCSTR          szName;
162
163     g_pPubImport->EnumModuleRefs(&hEnum,tk,4096,&N);
164     for(ULONG i = 0; i < N; i++)
165     {
166         if(RidFromToken(tk[i]))
167         {
168             if (FAILED(g_pImport->GetModuleRefProps(tk[i],&szName)))
169             {
170                 continue;
171             }
172             if (*szName != 0) // ignore the no-name ModuleRef: it's an IJW artifact
173             {
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);
181             }
182         }
183     }
184     g_pPubImport->CloseEnum(hEnum);
185 }
186
187 void DumpAssembly(void* GUICookie, BOOL fFullDump)
188 {
189     mdAssembly  tkAsm;
190     if(SUCCEEDED(g_pAssemblyImport->GetAssemblyFromScope(&tkAsm))&&(tkAsm != mdAssemblyNil))
191     {
192         const void* pPublicKey;
193         ULONG       cbPublicKey = 0;
194         ULONG       ulHashAlgId;
195         WCHAR       wzName[1024];
196         ULONG       ulNameLen=0;
197         ASSEMBLYMETADATA    md;
198         WCHAR       wzLocale[MAX_LOCALE_NAME];
199         DWORD       dwFlags;
200         char*       szptr;
201
202         md.szLocale = wzLocale;
203         md.cbLocale = MAX_LOCALE_NAME;
204         md.rProcessor = NULL;
205         md.ulProcessor = 0;
206         md.rOS = NULL;
207         md.ulOS = 0;
208
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.
219         {
220             if(ulNameLen >= 1024)
221             {
222                 strcpy_s(szString,SZSTRING_SIZE,RstrUTF(IDS_ASSEMNAMETOOLONG));
223                 printError(GUICookie,szString);
224                 ulNameLen = 1023;
225             }
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);
229
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 "));
237
238
239             wzName[ulNameLen] = 0;
240             {
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));
245                 VDELETE(sz);
246             }
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,"  ");
251             if(fFullDump)
252             {
253                 DumpCustomAttributes(tkAsm, GUICookie);
254                 DumpPermissions(tkAsm, GUICookie);
255             }
256
257             if(fFullDump)
258             {
259                 if(pPublicKey && cbPublicKey)
260                 {
261                     sprintf_s(szString,SZSTRING_SIZE,"%s%s = (",g_szAsmCodeIndent,KEYWORD(".publickey"));
262                     DumpByteArray(szString,(BYTE*)pPublicKey,cbPublicKey,GUICookie);
263                     printLine(GUICookie,szString);
264                 }
265                 if(ulHashAlgId)
266                 {
267                     sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%08X",g_szAsmCodeIndent,KEYWORD(".hash algorithm"),ulHashAlgId);
268                     printLine(GUICookie,szString);
269                 }
270             }
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))
277 }
278
279 MTokName*   rAsmRef = NULL;
280 ULONG   nAsmRefs = 0;
281
282 void DumpAssemblyRefs(void* GUICookie)
283 {
284     static mdAssemblyRef       rAsmRefTok[4096];
285     HCORENUM    hEnum=NULL;
286     ULONG ix = 0;
287     if(rAsmRef) { VDELETE(rAsmRef); nAsmRefs = 0; }
288     if(rAsmRefName)
289     {
290         for(ix=0; ix < ulNumAsmRefs; ix++)
291         {
292             if(rAsmRefName[ix]) VDELETE(rAsmRefName[ix]);
293         }
294         VDELETE(rAsmRefName);
295         rAsmRefName = NULL;
296         ulNumAsmRefs = 0;
297     }
298     if(SUCCEEDED(g_pAssemblyImport->EnumAssemblyRefs(&hEnum,rAsmRefTok,4096,&nAsmRefs)))
299     {
300         if(nAsmRefs)
301         {
302             const void* pPublicKeyOrToken;
303             ULONG       cbPublicKeyOrToken = 0;
304             const void* pHashValue;
305             ULONG       cbHashValue;
306             static WCHAR       wzName[1024];
307             ULONG       ulNameLen=0;
308             ASSEMBLYMETADATA    md;
309             WCHAR       wzLocale[MAX_LOCALE_NAME];
310             DWORD       dwFlags;
311
312             rAsmRef = new MTokName[nAsmRefs];
313             rAsmRefName = new LPCSTR[nAsmRefs];
314             ulNumAsmRefs = nAsmRefs;
315
316             for(ix = 0; ix < nAsmRefs; ix++)
317             {
318                 md.szLocale = wzLocale;
319                 md.cbLocale = MAX_LOCALE_NAME;
320                 md.rProcessor = NULL;
321                 md.ulProcessor = 0;
322                 md.rOS = NULL;
323                 md.ulOS = 0;
324
325                 ulNameLen=cbHashValue=0;
326                 pHashValue = NULL;
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.
338                 {
339                     ULONG ixx;
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)
345                     {
346                         strcpy_s(szString,SZSTRING_SIZE,RstrUTF(IDS_ASMREFNAMETOOLONG));
347                         printError(GUICookie,szString);
348                         wzName[1023] = 0;
349                     }
350
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]);
353                     
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 "));
360
361                     {
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++)
367                         {
368                             if(!wcscmp(rAsmRef[ixx].name,rAsmRef[ix].name)) break;
369                         }
370                         if(ixx < ix)
371                         {
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]));
376                         }
377                         else
378                             strcat_s(szString,SZSTRING_SIZE, ANCHORPT(ProperName(sz),rAsmRefTok[ix]));
379                         rAsmRefName[ix] = sz;
380                     }
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)
387                     {
388                         if (IsAfPublicKey(dwFlags))
389                             sprintf_s(szString,SZSTRING_SIZE,"%s%s = (",g_szAsmCodeIndent,KEYWORD(".publickey"));
390                         else
391                             sprintf_s(szString,SZSTRING_SIZE,"%s%s = (",g_szAsmCodeIndent,KEYWORD(".publickeytoken"));
392                         DumpByteArray(szString,(BYTE*)pPublicKeyOrToken,cbPublicKeyOrToken,GUICookie);
393                         printLine(GUICookie,szString);
394                     }
395                     if(pHashValue && cbHashValue)
396                     {
397                         sprintf_s(szString,SZSTRING_SIZE,"%s%s = (",g_szAsmCodeIndent,KEYWORD(".hash"));
398                         DumpByteArray(szString,(BYTE*)pHashValue,cbHashValue,GUICookie);
399                         printLine(GUICookie,szString);
400                     }
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)
407         }//end if(nAsmRefs
408         g_pAssemblyImport->CloseEnum(hEnum);
409     }//end if OK(EnumAssemblyRefs)
410     else nAsmRefs=0;
411 }
412
413 DynamicArray<LocalComTypeDescr*>    *g_pLocalComType = NULL;
414 ULONG   g_LocalComTypeNum = 0;
415
416 void DumpComTypeFQN(
417     LocalComTypeDescr*              pCTD,
418     __inout __nullterminated char*  szName)
419 {
420     if(TypeFromToken(pCTD->tkImplementation) == mdtExportedType)
421     {
422         ULONG i;
423         for(i = 0; (i < g_LocalComTypeNum) && ((*g_pLocalComType)[i]->tkComTypeTok != pCTD->tkImplementation); i++);
424         if(i < g_LocalComTypeNum)
425         {
426             DumpComTypeFQN((*g_pLocalComType)[i], szName);
427             strcat_s(szName, SZSTRING_SIZE, "/");
428         }
429     }
430
431     UINT32 L = (UINT32)wcslen(pCTD->wzName)*3+3;
432     char* sz = new char[L];
433     memset(sz,0,L);
434     WszWideCharToMultiByte(CP_UTF8,0,pCTD->wzName,-1,sz,L,NULL,NULL);
435     strcat_s(szName, SZSTRING_SIZE, JUMPPT(ProperName(sz), pCTD->tkComTypeTok));
436     VDELETE(sz);
437 }
438
439 void DumpImplementation(mdToken tkImplementation, 
440                         DWORD dwOffset, 
441                         __inout __nullterminated char* szString, 
442                         void* GUICookie)
443 {
444     ULONG i;
445     char* pc;
446     if(RidFromToken(tkImplementation))
447     {
448         if(TypeFromToken(tkImplementation) == mdtFile)
449         {
450             for(i=0; (i < nFiles)&&(rFile[i].tok != tkImplementation); i++);
451             if(i < nFiles)
452             {
453                 {
454                     UINT32 L = (UINT32)wcslen(rFile[i].name)*3+3;
455                     char* sz = new char[L];
456                     memset(sz,0,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));
460                     VDELETE(sz);
461                 }
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);
466             }
467         }
468         else if(TypeFromToken(tkImplementation) == mdtAssemblyRef)
469         {
470             for(i=0; (i < nAsmRefs)&&(rAsmRef[i].tok != tkImplementation); i++);
471             if(i < nAsmRefs)
472             {
473                 {
474                     UINT32 L = (UINT32)wcslen(rAsmRef[i].name)*3+3;
475                     char* sz = new char[L];
476                     memset(sz,0,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));
480                     VDELETE(sz);
481                 }
482                 pc=&szString[strlen(szString)];
483                 if(g_fDumpTokens) sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc),COMMENT(" /*%08X*/ "),tkImplementation);
484                 printLine(GUICookie,szString);
485             }
486         }
487         else if(TypeFromToken(tkImplementation) == mdtExportedType)
488         {
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)
492             {
493                 sprintf_s(szString,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".class extern"));
494                 DumpComTypeFQN((*g_pLocalComType)[i], szString);
495
496                 pc=&szString[strlen(szString)];
497                 if(g_fDumpTokens) sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc),COMMENT(" /*%08X*/ "),tkImplementation);
498                 printLine(GUICookie,szString);
499             }
500         }
501     }
502 }
503
504 void DumpComType(LocalComTypeDescr* pCTD, 
505                  __inout __nullterminated char* szString, 
506                  void* GUICookie)
507 {
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 "));
517
518     char* pc=&szString[strlen(szString)];
519     {
520         UINT32 L = (UINT32)wcslen(pCTD->wzName)*3+3;
521         char* sz = new char[L];
522         memset(sz,0,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));
525         VDELETE(sz);
526     }
527     printLine(GUICookie,szString);
528
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))
535     {
536         sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%08X",g_szAsmCodeIndent,KEYWORD(".class"),pCTD->tkTypeDef);
537         printLine(GUICookie,szString);
538     }
539     g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
540     sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
541     printLine(GUICookie,szString);
542 }
543
544
545 void DumpComTypes(void* GUICookie)
546 {
547     static mdExportedType  rComTypeTok[4096];
548     ULONG           nComTypes;
549     HCORENUM    hEnum=NULL;
550
551     g_LocalComTypeNum = 0;
552     if(SUCCEEDED(g_pAssemblyImport->EnumExportedTypes(&hEnum,rComTypeTok,4096,&nComTypes)))
553     {
554         if(nComTypes)
555         {
556             static WCHAR       wzName[1024];
557             ULONG       ulNameLen=0;
558             DWORD       dwFlags;
559             mdToken     tkImplementation;
560             mdTypeDef   tkTypeDef;
561
562             ULONG ix;
563             for(ix = 0; ix < nComTypes; ix++)
564             {
565                 ulNameLen=0;
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.
574                 {
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;
584
585                     if (g_pLocalComType == NULL)
586                     {
587                         g_pLocalComType = new DynamicArray<LocalComTypeDescr*>;
588                     }
589
590                     (*g_pLocalComType)[g_LocalComTypeNum] = pCTD;
591                     g_LocalComTypeNum++;
592                 } //end if(OK(GetComTypeProps))
593             }//end for(all com types)
594
595             // now, print all "external" com types
596             for(ix = 0; ix < nComTypes; ix++)
597             {
598                 tkImplementation = (*g_pLocalComType)[ix]->tkImplementation;
599                 // ComType of a nested class has its nester's ComType as implementation
600                 while(TypeFromToken(tkImplementation)==mdtExportedType)
601                 {
602                     unsigned k;
603                     for(k=0; k<g_LocalComTypeNum; k++)
604                     {
605                         if((*g_pLocalComType)[k]->tkComTypeTok == tkImplementation)
606                         {
607                             tkImplementation = (*g_pLocalComType)[k]->tkImplementation;
608                             break;
609                         }
610                     }
611                     if(k==g_LocalComTypeNum) break;
612                 }
613                 // At this moment, tkImplementation is impl.of top nester
614                 if(RidFromToken(tkImplementation))
615                 {
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;
619                 }
620             }
621         }//end if(nComTypes)
622         g_pAssemblyImport->CloseEnum(hEnum);
623     }//end if OK(EnumComTypes)
624     else nComTypes=0;
625 }
626
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)
630 {
631     BOOL fAlias = FALSE;
632     
633     // neutralize reserved names
634     static const WCHAR * const rwzReserved[] =
635     {
636         W("COM"), W("LPT"), // '1' - '9' must follow after these
637         W("CON"), W("PRN"), W("AUX"), W("NUL")
638     };
639
640     for (size_t i = 0; i < (sizeof(rwzReserved) / sizeof(WCHAR *)); i++)
641     {
642         _ASSERTE(wcslen(rwzReserved[i]) == 3);
643         if (_wcsnicmp(wzName, rwzReserved[i], 3) == 0)
644         {
645             LPWSTR pwc = wzName + 3;
646
647             if (i <= 1) // COM, LPT
648             {
649                 if (*pwc >= L'1' && *pwc <= L'9')
650                 {
651                     // skip the digit
652                     pwc++;
653                 }
654                 else continue;
655             }
656
657             // check for . or end of string
658             if (*pwc == L'.' || *pwc == 0)
659             {
660                 *wzName = L'_';
661                 fAlias = TRUE;
662                 break;
663             }
664         }
665     }
666
667     // replace invalid characters
668     for (;; wzName++)
669     {
670         WCHAR wch = *wzName;
671         
672         if (wch > 0 && wch < 32)
673         {
674             *wzName = '~';
675             fAlias = TRUE;
676         }
677         else
678         {
679             switch (wch)
680             {
681 #define REPLACE_CH(oldCh, newCh) \
682     case oldCh: *wzName = newCh; \
683                 fAlias = TRUE;   \
684                 break;
685
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
697
698                 case 0: return fAlias;
699 #undef REPLACE_CH
700             }
701         }
702     }
703 }
704
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)
708 {
709     struct Param
710     {
711         BYTE *pRes;
712         DWORD dwOffset;
713         LPCUTF8 sz;
714         void *GUICookie;
715         const WCHAR *wzFileName;
716     } param;
717     param.pRes = pRes;
718     param.dwOffset = dwOffset;
719     param.sz = sz;
720     param.GUICookie = GUICookie;
721     param.wzFileName = wzFileName;
722
723     PAL_TRY(Param *, pParam, &param)
724     {
725        DWORD L;
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
730         {
731             FILE *pF = NULL;
732             _wfopen_s(&pF, pParam->wzFileName, W("wb"));
733             if (pF)
734             {
735                 struct Param
736                 {
737                     BYTE *pRes;
738                     DWORD dwOffset;
739                     DWORD L;
740                     FILE *pF;
741                     LPCUTF8 sz;
742                     void *GUICookie;
743                 } param;
744                 param.pRes = pParam->pRes;
745                 param.dwOffset = pParam->dwOffset;
746                 param.L = L;
747                 param.pF = pF;
748                 param.sz = pParam->sz;
749                 param.GUICookie = pParam->GUICookie;
750
751                 PAL_TRY(Param *, pParam, &param) {
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));
755                 }
756                 PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
757                 {
758                     sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_READINGMRES),g_szAsmCodeIndent,ProperName(pParam->sz),pParam->dwOffset);
759                     printError(pParam->GUICookie,szString);
760                 }
761                 PAL_ENDTRY
762                 fclose(pF);
763             }
764         }
765     }
766     PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
767     {
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);
772     }
773     PAL_ENDTRY
774 }
775
776 void DumpManifestResources(void* GUICookie)
777 {
778     static mdManifestResource      rManResTok[4096];
779     ULONG           nManRes = 0;
780     HCORENUM    hEnum=NULL;
781     BYTE*       pRes = NULL;
782     if(SUCCEEDED(g_pAssemblyImport->EnumManifestResources(&hEnum,rManResTok,4096,&nManRes)))
783     {
784         if(nManRes)
785         {
786             WCHAR*      wzName = NULL;
787             ULONG       ulNameLen=0;
788             DWORD       dwFlags;
789             static char        sz[4096];
790             mdToken     tkImplementation;
791             DWORD       dwOffset;
792
793             static WCHAR wzFileName[2048];
794
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;
799             else wzName++;
800
801             // remember the file names created so far to avoid duplicates
802             CQuickArray<CQuickWSTRBase> qbNameArray;
803             if (!qbNameArray.AllocNoThrow(nManRes + 2))
804             {
805                 sprintf_s(szString, SZSTRING_SIZE,
806                           "ERROR retrieving/saving embedded managed resource '%s'", UnicodeToUtf(wzName)); 
807                 printError(GUICookie, szString);
808                 return;
809             }
810
811 #define NAME_ARRAY_ADD(index, str)                                                    \
812             {                                                                         \
813                 size_t __dwBufLen = wcslen(str) + 1;                                  \
814                                                                                       \
815                 qbNameArray[index].Init();                                            \
816                 WCHAR *__wpc = (WCHAR *)qbNameArray[index].AllocNoThrow(__dwBufLen);  \
817                 if (__wpc) wcscpy_s(__wpc, __dwBufLen, str);                          \
818             }
819
820             // add the output file name to avoid conflict between the IL file and a resource file
821             NAME_ARRAY_ADD(0, wzName);
822
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"));
827
828             NAME_ARRAY_ADD(1, wzName);
829
830             for(ULONG ix = 0; ix < nManRes; ix++)
831             {
832                 ulNameLen=0;
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.
841                 {
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 "));
846
847                     char* pc = szString + strlen(szString);
848                     wzName[ulNameLen]=0;
849
850                     WszWideCharToMultiByte(CP_UTF8,0,wzName,-1,sz,sizeof(sz),NULL,NULL);
851                     strcpy_s(pc,SZSTRING_REMAINING_SIZE(pc),ProperName(sz));
852
853                     // get rid of invalid characters and reserved names
854                     BOOL fAlias = ConvertToLegalFileNameInPlace(wzName);
855
856                     // check for duplicate file name
857                     WCHAR *wpc = wzName + wcslen(wzName);
858                     for (int iIndex = 1;; iIndex++)
859                     {
860                         BOOL fConflict = FALSE;
861                         if (*wzName == 0)
862                     {
863                             // resource with an empty name
864                             fConflict = TRUE;
865                     }
866                         else
867                     {
868                             for (ULONG i = 0; i < (ix + 2); i++)
869                             {
870                                 WCHAR *wzPreviousName = (WCHAR *)qbNameArray[i].Ptr();
871                                 if (wzPreviousName && _wcsicmp(wzName, wzPreviousName) == 0)
872                                 {
873                                     // resource with the same name as another resource
874                                     // or with the same name as the output IL/RES file
875                                     fConflict = TRUE;
876                                     break;
877                     }
878                             }
879                     }
880
881                         // if we have a conflict, add a number suffix to the file name
882                         if (!fConflict ||
883                             swprintf_s(wpc, 2048 - (wpc - wzFileName), W("%d"), iIndex) <= 0)
884                     {
885                             // no conflict or unable to add index
886                             break;
887                     }
888
889                         // try again with this new number suffix
890                         fAlias = TRUE;
891                     }
892
893                     // add this unique file name to the list
894                     NAME_ARRAY_ADD(ix + 2, wzName);
895
896                     if(fAlias)
897                     {
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)
900                         {
901                             sz[sizeof(sz) - 1] = 0;
902                         }
903
904                         pc=&szString[strlen(szString)];
905                         sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc)," %s %s",KEYWORD("as"),ProperName(sz));
906                     }
907
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);
913
914                     if(tkImplementation == mdFileNil) // embedded resource -- dump as .resources file
915                     {
916                         if(pRes == NULL)
917                         {
918                             // get the resource VA
919                             if (g_pPELoader->getVAforRVA((DWORD) VAL32(g_CORHeader->Resources.VirtualAddress), (void **) &pRes) == FALSE)
920                             {
921                                 printError(GUICookie,RstrUTF(IDS_E_IMPORTDATA));
922                             }
923                         }
924                         if(pRes)
925                         {
926                             DumpResourceFile(GUICookie, pRes, dwOffset, wzName, wzFileName, sz);
927                         }
928                     }
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)
935
936 #undef NAME_ARRAY_ADD
937
938         }//end if(nManRes)
939         g_pAssemblyImport->CloseEnum(hEnum);
940     }//end if OK(EnumManifestResources)
941     else nManRes=0;
942 }
943
944 IMetaDataAssemblyImport* GetAssemblyImport(void* GUICookie)
945 {
946     struct Param
947     {
948         void*                    GUICookie;
949         IMetaDataAssemblyImport* pAssemblyImport;
950         IMDInternalImport*       pImport;
951     mdToken                 tkManifest;
952     } param;
953     param.GUICookie = GUICookie;
954     param.pAssemblyImport = NULL;
955     param.pImport = NULL;
956
957     HRESULT                 hr;
958
959     hr=g_pPubImport->QueryInterface(IID_IMetaDataAssemblyImport, (void**) &param.pAssemblyImport);
960     if(SUCCEEDED(hr))
961     {
962         static mdAssemblyRef       rAsmRefTok[4096];
963         HCORENUM    hEnum=NULL;
964         ULONG   nAsmRefs = 0;
965         if(SUCCEEDED(param.pAssemblyImport->GetAssemblyFromScope(&param.tkManifest))) return param.pAssemblyImport;
966         if(SUCCEEDED(param.pAssemblyImport->EnumAssemblyRefs(&hEnum,rAsmRefTok,4096,&nAsmRefs)))
967         {
968             param.pAssemblyImport->CloseEnum(hEnum);
969             if(nAsmRefs) return param.pAssemblyImport;
970         }
971         param.pAssemblyImport->Release();
972     }
973     else
974     {
975         sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_MDAIMPORT),hr);
976         printLine(GUICookie,COMMENT(szString));
977     }
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, &param)
981     {
982         if(g_CORHeader->Resources.Size)
983         {
984             DWORD*  pdwSize = NULL;
985             BYTE*   pbManifest = NULL;
986             HRESULT hr;
987
988             pbManifest = (BYTE*)(g_pPELoader->base() + (DWORD)VAL32(g_CORHeader->Resources.VirtualAddress));
989             pdwSize = (DWORD*)pbManifest;
990             if(pdwSize && *pdwSize)
991             {
992                 pbManifest += sizeof(DWORD);
993                 if (SUCCEEDED(hr = getMetaDataInternalInterface(
994                     pbManifest,
995                     VAL32(*pdwSize),
996                     ofRead,
997                     IID_IMDInternalImport,
998                     (LPVOID *)&pParam->pImport)))
999                 {
1000                     if (FAILED(hr = getMetaDataPublicInterfaceFromInternal(
1001                         pParam->pImport,
1002                         IID_IMetaDataAssemblyImport,
1003                         (LPVOID *)&pParam->pAssemblyImport)))
1004                     {
1005                         sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_MDAFROMMDI),hr);
1006                         printLine(pParam->GUICookie,COMMENT(szString));
1007                         pParam->pAssemblyImport = NULL;
1008                     }
1009                     else
1010                     {
1011                         mdAssemblyRef       rAsmRefTok[4096];
1012                         HCORENUM    hEnum=NULL;
1013                         ULONG   nAsmRefs = 0;
1014                         if(FAILED(pParam->pAssemblyImport->GetAssemblyFromScope(&pParam->tkManifest))
1015                             && (FAILED(pParam->pAssemblyImport->EnumAssemblyRefs(&hEnum,rAsmRefTok,4096,&nAsmRefs))
1016                                 || (nAsmRefs ==0)))
1017                         {
1018                             pParam->pAssemblyImport->CloseEnum(hEnum);
1019                             pParam->pAssemblyImport->Release();
1020                             pParam->pAssemblyImport = NULL;
1021                         }
1022                     }
1023                     pParam->pImport->Release();
1024                 }
1025                 else
1026                 {
1027                     sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_MDIIMPORT),hr);
1028                     printLine(pParam->GUICookie,COMMENT(szString));
1029                 }
1030             }
1031         }
1032     } // end try
1033     PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1034     {
1035         if(param.pAssemblyImport) param.pAssemblyImport->Release();
1036         param.pAssemblyImport = NULL;
1037         if(param.pImport) param.pImport->Release();
1038     }
1039     PAL_ENDTRY
1040     return param.pAssemblyImport;
1041 }
1042
1043 static void DumpMetadataVersion(void* GUICookie)
1044 {
1045     LPCSTR pVersionStr;
1046     if (g_pImport == NULL || FAILED(g_pImport->GetVersionString(&pVersionStr)))
1047     {
1048         pVersionStr = "**Unavailable**";
1049     }
1050     sprintf_s(szString,SZSTRING_SIZE,"// Metadata version: %s",pVersionStr);
1051     printLine(GUICookie,szString);
1052 }
1053
1054 void DumpManifest(void* GUICookie)
1055 {
1056     DumpMetadataVersion(GUICookie);
1057     DumpModuleRefs(GUICookie);
1058     if(g_pAssemblyImport==NULL) g_pAssemblyImport = GetAssemblyImport(GUICookie);
1059     if(g_pAssemblyImport)
1060     {
1061         DumpAssemblyRefs(GUICookie);
1062         DumpAssembly(GUICookie,TRUE);
1063         DumpFiles(GUICookie);
1064         DumpComTypes(GUICookie);
1065         DumpManifestResources(GUICookie);
1066     }
1067     else printLine(GUICookie,COMMENT(RstrUTF(IDS_E_NOMANIFEST)));
1068     DumpScope(GUICookie);
1069     DumpVtable(GUICookie);
1070
1071 }