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
26extern IMAGE_COR20_HEADER * g_CORHeader;
27extern IMDInternalImport* g_pImport;
28extern PELoader * g_pPELoader;
29extern IMetaDataImport2* g_pPubImport;
30extern void * g_pMetaData;
31IMetaDataAssemblyImport* g_pAssemblyImport=NULL;
32extern BOOL g_fDumpAsmCode;
33extern char g_szAsmCodeIndent[];
34extern char g_szOutputFile[];
35extern BOOL g_fDumpTokens;
36extern DWORD g_Mode;
37extern FILE* g_pFile;
38extern LPCSTR* rAsmRefName; // decl. in formatType.cpp -- for AsmRef aliases
39extern ULONG ulNumAsmRefs; // decl. in formatType.cpp -- for AsmRef aliases
40extern unsigned g_uConsoleCP;
41MTokName* rFile = NULL;
42ULONG nFiles = 0;
43void 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
104void 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}
119void 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
155void 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
187void 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_AMD64(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("amd64 "));
236 if(IsAfPA_ARM(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("arm "));
237 if(IsAfPA_ARM64(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("arm64 "));
238
239
240 wzName[ulNameLen] = 0;
241 {
242 char* sz = new char[3*ulNameLen+3];
243 memset(sz,0,3*ulNameLen+3);
244 WszWideCharToMultiByte(CP_UTF8,0,wzName,-1,sz,3*ulNameLen+3,NULL,NULL);
245 strcat_s(szString,SZSTRING_SIZE,ANCHORPT(ProperName(sz),tkAsm));
246 VDELETE(sz);
247 }
248 printLine(GUICookie,szString);
249 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
250 printLine(GUICookie,szString);
251 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
252 if(fFullDump)
253 {
254 DumpCustomAttributes(tkAsm, GUICookie);
255 DumpPermissions(tkAsm, GUICookie);
256 }
257
258 if(fFullDump)
259 {
260 if(pPublicKey && cbPublicKey)
261 {
262 sprintf_s(szString,SZSTRING_SIZE,"%s%s = (",g_szAsmCodeIndent,KEYWORD(".publickey"));
263 DumpByteArray(szString,(BYTE*)pPublicKey,cbPublicKey,GUICookie);
264 printLine(GUICookie,szString);
265 }
266 if(ulHashAlgId)
267 {
268 sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%08X",g_szAsmCodeIndent,KEYWORD(".hash algorithm"),ulHashAlgId);
269 printLine(GUICookie,szString);
270 }
271 }
272 DumpAssemblyMetaData(&md,GUICookie);
273 g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
274 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
275 printLine(GUICookie,szString);
276 } //end if(OK(GetAssemblyProps))
277 } //end if(OK(GetAssemblyFromScope))
278}
279
280MTokName* rAsmRef = NULL;
281ULONG nAsmRefs = 0;
282
283void DumpAssemblyRefs(void* GUICookie)
284{
285 static mdAssemblyRef rAsmRefTok[4096];
286 HCORENUM hEnum=NULL;
287 ULONG ix = 0;
288 if(rAsmRef) { VDELETE(rAsmRef); nAsmRefs = 0; }
289 if(rAsmRefName)
290 {
291 for(ix=0; ix < ulNumAsmRefs; ix++)
292 {
293 if(rAsmRefName[ix]) VDELETE(rAsmRefName[ix]);
294 }
295 VDELETE(rAsmRefName);
296 rAsmRefName = NULL;
297 ulNumAsmRefs = 0;
298 }
299 if(SUCCEEDED(g_pAssemblyImport->EnumAssemblyRefs(&hEnum,rAsmRefTok,4096,&nAsmRefs)))
300 {
301 if(nAsmRefs)
302 {
303 const void* pPublicKeyOrToken;
304 ULONG cbPublicKeyOrToken = 0;
305 const void* pHashValue;
306 ULONG cbHashValue;
307 static WCHAR wzName[1024];
308 ULONG ulNameLen=0;
309 ASSEMBLYMETADATA md;
310 WCHAR wzLocale[MAX_LOCALE_NAME];
311 DWORD dwFlags;
312
313 rAsmRef = new MTokName[nAsmRefs];
314 rAsmRefName = new LPCSTR[nAsmRefs];
315 ulNumAsmRefs = nAsmRefs;
316
317 for(ix = 0; ix < nAsmRefs; ix++)
318 {
319 md.szLocale = wzLocale;
320 md.cbLocale = MAX_LOCALE_NAME;
321 md.rProcessor = NULL;
322 md.ulProcessor = 0;
323 md.rOS = NULL;
324 md.ulOS = 0;
325
326 ulNameLen=cbHashValue=0;
327 pHashValue = NULL;
328 if(SUCCEEDED(g_pAssemblyImport->GetAssemblyRefProps( // S_OK or error.
329 rAsmRefTok[ix], // [IN] The Assembly for which to get the properties.
330 &pPublicKeyOrToken, // [OUT] Pointer to the public key or token.
331 &cbPublicKeyOrToken,// [OUT] Count of bytes in the public key or token.
332 wzName, // [OUT] Buffer to fill with name.
333 1024, // [IN] Size of buffer in wide chars.
334 &ulNameLen, // [OUT] Actual # of wide chars in name.
335 &md, // [OUT] Assembly MetaData.
336 &pHashValue, // [OUT] Hash blob.
337 &cbHashValue,// [OUT] Count of bytes in the hash blob.
338 &dwFlags))) // [OUT] Flags.
339 {
340 ULONG ixx;
341 rAsmRef[ix].tok = rAsmRefTok[ix];
342 rAsmRef[ix].name = new WCHAR[ulNameLen+16];
343 memcpy(rAsmRef[ix].name,wzName,ulNameLen*sizeof(WCHAR));
344 rAsmRef[ix].name[ulNameLen] = 0;
345 if(ulNameLen >= 1024)
346 {
347 strcpy_s(szString,SZSTRING_SIZE,RstrUTF(IDS_ASMREFNAMETOOLONG));
348 printError(GUICookie,szString);
349 wzName[1023] = 0;
350 }
351
352 sprintf_s(szString,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".assembly extern"));
353 if(g_fDumpTokens) sprintf_s(&szString[strlen(szString)],SZSTRING_SIZE-strlen(szString),COMMENT("/*%08X*/ "),rAsmRefTok[ix]);
354
355 if(IsAfRetargetable(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("retargetable "));
356 if(IsAfContentType_WindowsRuntime(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("windowsruntime "));
357 if(IsAfPA_MSIL(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("cil "));
358 if(IsAfPA_x86(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("x86 "));
359 if(IsAfPA_AMD64(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("amd64 "));
360 if(IsAfPA_ARM(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("arm "));
361 if(IsAfPA_ARM64(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("arm64 "));
362
363 {
364 char* sz = new char[3*ulNameLen+32];
365 memset(sz,0,3*ulNameLen+3);
366 WszWideCharToMultiByte(CP_UTF8,0,rAsmRef[ix].name,-1,sz,3*ulNameLen+3,NULL,NULL);
367 // check for name duplication and introduce alias if needed
368 for(ixx = 0; ixx < ix; ixx++)
369 {
370 if(!wcscmp(rAsmRef[ixx].name,rAsmRef[ix].name)) break;
371 }
372 if(ixx < ix)
373 {
374 strcat_s(szString,SZSTRING_SIZE, ProperName(sz));
375 char* pc=&szString[strlen(szString)];
376 sprintf_s(&sz[strlen(sz)],3*ulNameLen+32-strlen(sz),"_%d",ix);
377 sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc)," %s %s", KEYWORD("as"),ANCHORPT(ProperName(sz),rAsmRefTok[ix]));
378 }
379 else
380 strcat_s(szString,SZSTRING_SIZE, ANCHORPT(ProperName(sz),rAsmRefTok[ix]));
381 rAsmRefName[ix] = sz;
382 }
383 printLine(GUICookie,szString);
384 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
385 printLine(GUICookie,szString);
386 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
387 DumpCustomAttributes(rAsmRefTok[ix], GUICookie);
388 if(pPublicKeyOrToken && cbPublicKeyOrToken)
389 {
390 if (IsAfPublicKey(dwFlags))
391 sprintf_s(szString,SZSTRING_SIZE,"%s%s = (",g_szAsmCodeIndent,KEYWORD(".publickey"));
392 else
393 sprintf_s(szString,SZSTRING_SIZE,"%s%s = (",g_szAsmCodeIndent,KEYWORD(".publickeytoken"));
394 DumpByteArray(szString,(BYTE*)pPublicKeyOrToken,cbPublicKeyOrToken,GUICookie);
395 printLine(GUICookie,szString);
396 }
397 if(pHashValue && cbHashValue)
398 {
399 sprintf_s(szString,SZSTRING_SIZE,"%s%s = (",g_szAsmCodeIndent,KEYWORD(".hash"));
400 DumpByteArray(szString,(BYTE*)pHashValue,cbHashValue,GUICookie);
401 printLine(GUICookie,szString);
402 }
403 DumpAssemblyMetaData(&md,GUICookie);
404 g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
405 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
406 printLine(GUICookie,szString);
407 } //end if(OK(GetAssemblyRefProps))
408 }//end for(all assembly refs)
409 }//end if(nAsmRefs
410 g_pAssemblyImport->CloseEnum(hEnum);
411 }//end if OK(EnumAssemblyRefs)
412 else nAsmRefs=0;
413}
414
415DynamicArray<LocalComTypeDescr*> *g_pLocalComType = NULL;
416ULONG g_LocalComTypeNum = 0;
417
418void DumpComTypeFQN(
419 LocalComTypeDescr* pCTD,
420 __inout __nullterminated char* szName)
421{
422 if(TypeFromToken(pCTD->tkImplementation) == mdtExportedType)
423 {
424 ULONG i;
425 for(i = 0; (i < g_LocalComTypeNum) && ((*g_pLocalComType)[i]->tkComTypeTok != pCTD->tkImplementation); i++);
426 if(i < g_LocalComTypeNum)
427 {
428 DumpComTypeFQN((*g_pLocalComType)[i], szName);
429 strcat_s(szName, SZSTRING_SIZE, "/");
430 }
431 }
432
433 UINT32 L = (UINT32)wcslen(pCTD->wzName)*3+3;
434 char* sz = new char[L];
435 memset(sz,0,L);
436 WszWideCharToMultiByte(CP_UTF8,0,pCTD->wzName,-1,sz,L,NULL,NULL);
437 strcat_s(szName, SZSTRING_SIZE, JUMPPT(ProperName(sz), pCTD->tkComTypeTok));
438 VDELETE(sz);
439}
440
441void DumpImplementation(mdToken tkImplementation,
442 DWORD dwOffset,
443 __inout __nullterminated char* szString,
444 void* GUICookie)
445{
446 ULONG i;
447 char* pc;
448 if(RidFromToken(tkImplementation))
449 {
450 if(TypeFromToken(tkImplementation) == mdtFile)
451 {
452 for(i=0; (i < nFiles)&&(rFile[i].tok != tkImplementation); i++);
453 if(i < nFiles)
454 {
455 {
456 UINT32 L = (UINT32)wcslen(rFile[i].name)*3+3;
457 char* sz = new char[L];
458 memset(sz,0,L);
459 WszWideCharToMultiByte(CP_UTF8,0,rFile[i].name,-1,sz,L,NULL,NULL);
460 sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,KEYWORD(".file"),
461 JUMPPT(ProperName(sz),tkImplementation));
462 VDELETE(sz);
463 }
464 pc=&szString[strlen(szString)];
465 if(g_fDumpTokens) pc+=sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc),COMMENT("/*%08X*/ "),tkImplementation);
466 if(dwOffset != 0xFFFFFFFF) sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc)," %s 0x%08X",KEYWORD("at"),dwOffset);
467 printLine(GUICookie,szString);
468 }
469 }
470 else if(TypeFromToken(tkImplementation) == mdtAssemblyRef)
471 {
472 for(i=0; (i < nAsmRefs)&&(rAsmRef[i].tok != tkImplementation); i++);
473 if(i < nAsmRefs)
474 {
475 {
476 UINT32 L = (UINT32)wcslen(rAsmRef[i].name)*3+3;
477 char* sz = new char[L];
478 memset(sz,0,L);
479 WszWideCharToMultiByte(CP_UTF8,0,rAsmRef[i].name,-1,sz,L,NULL,NULL);
480 sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,KEYWORD(".assembly extern"),
481 JUMPPT(ProperName(sz),tkImplementation));
482 VDELETE(sz);
483 }
484 pc=&szString[strlen(szString)];
485 if(g_fDumpTokens) sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc),COMMENT(" /*%08X*/ "),tkImplementation);
486 printLine(GUICookie,szString);
487 }
488 }
489 else if(TypeFromToken(tkImplementation) == mdtExportedType)
490 {
491 // Find the type structure corresponding to this token
492 for(i=0; (i < g_LocalComTypeNum)&&((*g_pLocalComType)[i]->tkComTypeTok != tkImplementation); i++);
493 if(i < g_LocalComTypeNum)
494 {
495 sprintf_s(szString,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".class extern"));
496 DumpComTypeFQN((*g_pLocalComType)[i], szString);
497
498 pc=&szString[strlen(szString)];
499 if(g_fDumpTokens) sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc),COMMENT(" /*%08X*/ "),tkImplementation);
500 printLine(GUICookie,szString);
501 }
502 }
503 }
504}
505
506void DumpComType(LocalComTypeDescr* pCTD,
507 __inout __nullterminated char* szString,
508 void* GUICookie)
509{
510 if(g_fDumpTokens) sprintf_s(&szString[strlen(szString)],SZSTRING_SIZE-strlen(szString),COMMENT("/*%08X*/ "),pCTD->tkComTypeTok);
511 if (IsTdPublic(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("public "));
512 if (IsTdForwarder(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("forwarder "));
513 if (IsTdNestedPublic(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("nested public "));
514 if (IsTdNestedPrivate(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("nested private "));
515 if (IsTdNestedFamily(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("nested family "));
516 if (IsTdNestedAssembly(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("nested assembly "));
517 if (IsTdNestedFamANDAssem(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("nested famandassem "));
518 if (IsTdNestedFamORAssem(pCTD->dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("nested famorassem "));
519
520 char* pc=&szString[strlen(szString)];
521 {
522 UINT32 L = (UINT32)wcslen(pCTD->wzName)*3+3;
523 char* sz = new char[L];
524 memset(sz,0,L);
525 WszWideCharToMultiByte(CP_UTF8,0,pCTD->wzName,-1,sz,L,NULL,NULL);
526 strcpy_s(pc,SZSTRING_REMAINING_SIZE(pc),ANCHORPT(ProperName(sz),pCTD->tkComTypeTok));
527 VDELETE(sz);
528 }
529 printLine(GUICookie,szString);
530
531 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
532 printLine(GUICookie,szString);
533 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
534 DumpCustomAttributes(pCTD->tkComTypeTok, GUICookie);
535 DumpImplementation(pCTD->tkImplementation,0xFFFFFFFF,szString,GUICookie);
536 if(RidFromToken(pCTD->tkTypeDef))
537 {
538 sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%08X",g_szAsmCodeIndent,KEYWORD(".class"),pCTD->tkTypeDef);
539 printLine(GUICookie,szString);
540 }
541 g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
542 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
543 printLine(GUICookie,szString);
544}
545
546
547void DumpComTypes(void* GUICookie)
548{
549 static mdExportedType rComTypeTok[4096];
550 ULONG nComTypes;
551 HCORENUM hEnum=NULL;
552
553 g_LocalComTypeNum = 0;
554 if(SUCCEEDED(g_pAssemblyImport->EnumExportedTypes(&hEnum,rComTypeTok,4096,&nComTypes)))
555 {
556 if(nComTypes)
557 {
558 static WCHAR wzName[1024];
559 ULONG ulNameLen=0;
560 DWORD dwFlags;
561 mdToken tkImplementation;
562 mdTypeDef tkTypeDef;
563
564 ULONG ix;
565 for(ix = 0; ix < nComTypes; ix++)
566 {
567 ulNameLen=0;
568 if(SUCCEEDED(g_pAssemblyImport->GetExportedTypeProps( // S_OK or error.
569 rComTypeTok[ix], // [IN] The ComType for which to get the properties.
570 wzName, // [OUT] Buffer to fill with name.
571 1024, // [IN] Size of buffer in wide chars.
572 &ulNameLen, // [OUT] Actual # of wide chars in name.
573 &tkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ComType.
574 &tkTypeDef, // [OUT] TypeDef token within the file.
575 &dwFlags))) // [OUT] Flags.
576 {
577 LocalComTypeDescr* pCTD = new LocalComTypeDescr;
578 memset(pCTD,0,sizeof(LocalComTypeDescr));
579 pCTD->tkComTypeTok = rComTypeTok[ix];
580 pCTD->tkTypeDef = tkTypeDef;
581 pCTD->tkImplementation = tkImplementation;
582 pCTD->wzName = new WCHAR[ulNameLen+1];
583 memcpy(pCTD->wzName,wzName,ulNameLen*sizeof(WCHAR));
584 pCTD->wzName[ulNameLen] = 0;
585 pCTD->dwFlags = dwFlags;
586
587 if (g_pLocalComType == NULL)
588 {
589 g_pLocalComType = new DynamicArray<LocalComTypeDescr*>;
590 }
591
592 (*g_pLocalComType)[g_LocalComTypeNum] = pCTD;
593 g_LocalComTypeNum++;
594 } //end if(OK(GetComTypeProps))
595 }//end for(all com types)
596
597 // now, print all "external" com types
598 for(ix = 0; ix < nComTypes; ix++)
599 {
600 tkImplementation = (*g_pLocalComType)[ix]->tkImplementation;
601 // ComType of a nested class has its nester's ComType as implementation
602 while(TypeFromToken(tkImplementation)==mdtExportedType)
603 {
604 unsigned k;
605 for(k=0; k<g_LocalComTypeNum; k++)
606 {
607 if((*g_pLocalComType)[k]->tkComTypeTok == tkImplementation)
608 {
609 tkImplementation = (*g_pLocalComType)[k]->tkImplementation;
610 break;
611 }
612 }
613 if(k==g_LocalComTypeNum) break;
614 }
615 // At this moment, tkImplementation is impl.of top nester
616 if(RidFromToken(tkImplementation))
617 {
618 sprintf_s(szString,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".class extern"));
619 DumpComType((*g_pLocalComType)[ix],szString,GUICookie);
620 (*g_pLocalComType)[ix]->tkTypeDef = 0;
621 }
622 }
623 }//end if(nComTypes)
624 g_pAssemblyImport->CloseEnum(hEnum);
625 }//end if OK(EnumComTypes)
626 else nComTypes=0;
627}
628
629// Replaces invalid characters and neutralizes reserved file names.
630// Returns TRUE if the string was modified, FALSE otherwise.
631static BOOL ConvertToLegalFileNameInPlace(__inout LPWSTR wzName)
632{
633 BOOL fAlias = FALSE;
634
635 // neutralize reserved names
636 static const WCHAR * const rwzReserved[] =
637 {
638 W("COM"), W("LPT"), // '1' - '9' must follow after these
639 W("CON"), W("PRN"), W("AUX"), W("NUL")
640 };
641
642 for (size_t i = 0; i < (sizeof(rwzReserved) / sizeof(WCHAR *)); i++)
643 {
644 _ASSERTE(wcslen(rwzReserved[i]) == 3);
645 if (_wcsnicmp(wzName, rwzReserved[i], 3) == 0)
646 {
647 LPWSTR pwc = wzName + 3;
648
649 if (i <= 1) // COM, LPT
650 {
651 if (*pwc >= L'1' && *pwc <= L'9')
652 {
653 // skip the digit
654 pwc++;
655 }
656 else continue;
657 }
658
659 // check for . or end of string
660 if (*pwc == L'.' || *pwc == 0)
661 {
662 *wzName = L'_';
663 fAlias = TRUE;
664 break;
665 }
666 }
667 }
668
669 // replace invalid characters
670 for (;; wzName++)
671 {
672 WCHAR wch = *wzName;
673
674 if (wch > 0 && wch < 32)
675 {
676 *wzName = '~';
677 fAlias = TRUE;
678 }
679 else
680 {
681 switch (wch)
682 {
683#define REPLACE_CH(oldCh, newCh) \
684 case oldCh: *wzName = newCh; \
685 fAlias = TRUE; \
686 break;
687
688 REPLACE_CH(L':', L'!')
689 REPLACE_CH(L'\\', L'$')
690 REPLACE_CH(L',', L'&') // not necessary but keeping for back compat
691 REPLACE_CH(L';', L'@') // not necessary but keeping for back compat
692 REPLACE_CH(L'<', L'(')
693 REPLACE_CH(L'>', L')')
694 REPLACE_CH(L'"', L'`')
695 REPLACE_CH(L'/', L'_')
696 REPLACE_CH(L'|', L'-')
697 REPLACE_CH(L'*', L'+') // disallowed wildcard
698 REPLACE_CH(L'?', L'=') // disallowed wildcard
699
700 case 0: return fAlias;
701#undef REPLACE_CH
702 }
703 }
704 }
705}
706
707// Dumps managed resource at pRes + dwOffset to a file.
708static void DumpResourceFile(void *GUICookie, BYTE *pRes, DWORD dwOffset, LPCWSTR wzName,
709 LPCWSTR wzFileName, LPCUTF8 sz)
710{
711 struct Param
712 {
713 BYTE *pRes;
714 DWORD dwOffset;
715 LPCUTF8 sz;
716 void *GUICookie;
717 const WCHAR *wzFileName;
718 } param;
719 param.pRes = pRes;
720 param.dwOffset = dwOffset;
721 param.sz = sz;
722 param.GUICookie = GUICookie;
723 param.wzFileName = wzFileName;
724
725 PAL_TRY(Param *, pParam, &param)
726 {
727 DWORD L;
728 memcpy(&L,pParam->pRes+pParam->dwOffset,sizeof(DWORD));
729 sprintf_s(szString,SZSTRING_SIZE,COMMENT("%s// Offset: 0x%8.8X Length: 0x%8.8X"), g_szAsmCodeIndent,pParam->dwOffset,L);
730 printLine(pParam->GUICookie,szString);
731 if (g_pFile != NULL) // embedded resource -- dump as .resources file
732 {
733 FILE *pF = NULL;
734 _wfopen_s(&pF, pParam->wzFileName, W("wb"));
735 if (pF)
736 {
737 struct Param
738 {
739 BYTE *pRes;
740 DWORD dwOffset;
741 DWORD L;
742 FILE *pF;
743 LPCUTF8 sz;
744 void *GUICookie;
745 } param;
746 param.pRes = pParam->pRes;
747 param.dwOffset = pParam->dwOffset;
748 param.L = L;
749 param.pF = pF;
750 param.sz = pParam->sz;
751 param.GUICookie = pParam->GUICookie;
752
753 PAL_TRY(Param *, pParam, &param) {
754 fwrite((pParam->pRes+pParam->dwOffset+sizeof(DWORD)),pParam->L,1,pParam->pF);
755 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_W_CREATEDMRES),g_szAsmCodeIndent,ProperName(pParam->sz));
756 printLine(pParam->GUICookie,COMMENT(szString));
757 }
758 PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
759 {
760 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_READINGMRES),g_szAsmCodeIndent,ProperName(pParam->sz),pParam->dwOffset);
761 printError(pParam->GUICookie,szString);
762 }
763 PAL_ENDTRY
764 fclose(pF);
765 }
766 }
767 }
768 PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
769 {
770 sprintf_s(szString, SZSTRING_SIZE,
771 "ERROR retrieving/saving embedded managed resource '%s' at offset 0x%8.8X",
772 UnicodeToUtf(wzName), dwOffset);
773 printError(GUICookie, szString);
774 }
775 PAL_ENDTRY
776}
777
778void DumpManifestResources(void* GUICookie)
779{
780 static mdManifestResource rManResTok[4096];
781 ULONG nManRes = 0;
782 HCORENUM hEnum=NULL;
783 BYTE* pRes = NULL;
784 if(SUCCEEDED(g_pAssemblyImport->EnumManifestResources(&hEnum,rManResTok,4096,&nManRes)))
785 {
786 if(nManRes)
787 {
788 WCHAR* wzName = NULL;
789 ULONG ulNameLen=0;
790 DWORD dwFlags;
791 static char sz[4096];
792 mdToken tkImplementation;
793 DWORD dwOffset;
794
795 static WCHAR wzFileName[2048];
796
797 WszMultiByteToWideChar(CP_UTF8,0,g_szOutputFile,-1,wzFileName,2048);
798 wzName = wcsrchr(wzFileName,'\\');
799 if(wzName == NULL) wzName = wcsrchr(wzFileName,':');
800 if (wzName == NULL) wzName = wzFileName;
801 else wzName++;
802
803 // remember the file names created so far to avoid duplicates
804 CQuickArray<CQuickWSTRBase> qbNameArray;
805 if (!qbNameArray.AllocNoThrow(nManRes + 2))
806 {
807 sprintf_s(szString, SZSTRING_SIZE,
808 "ERROR retrieving/saving embedded managed resource '%s'", UnicodeToUtf(wzName));
809 printError(GUICookie, szString);
810 return;
811 }
812
813#define NAME_ARRAY_ADD(index, str) \
814 { \
815 size_t __dwBufLen = wcslen(str) + 1; \
816 \
817 qbNameArray[index].Init(); \
818 WCHAR *__wpc = (WCHAR *)qbNameArray[index].AllocNoThrow(__dwBufLen); \
819 if (__wpc) wcscpy_s(__wpc, __dwBufLen, str); \
820 }
821
822 // add the output file name to avoid conflict between the IL file and a resource file
823 NAME_ARRAY_ADD(0, wzName);
824
825 // add the Win32 resource file name to avoid conflict between the native and a managed resource file
826 WCHAR *pwc = wcsrchr(wzName, L'.');
827 if (pwc == NULL) pwc = &wzName[wcslen(wzName)];
828 wcscpy_s(pwc, 2048 - (pwc - wzFileName), W(".res"));
829
830 NAME_ARRAY_ADD(1, wzName);
831
832 for(ULONG ix = 0; ix < nManRes; ix++)
833 {
834 ulNameLen=0;
835 if(SUCCEEDED(g_pAssemblyImport->GetManifestResourceProps( // S_OK or error.
836 rManResTok[ix], // [IN] The ManifestResource for which to get the properties.
837 wzName, // [OUT] Buffer to fill with name.
838 1024, // [IN] Size of buffer in wide chars.
839 &ulNameLen, // [OUT] Actual # of wide chars in name.
840 &tkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ComType.
841 &dwOffset, // [OUT] Offset to the beginning of the resource within the file.
842 &dwFlags))) // [OUT] Flags.
843 {
844 sprintf_s(szString,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".mresource"));
845 if(g_fDumpTokens) sprintf_s(&szString[strlen(szString)],SZSTRING_SIZE-strlen(szString),COMMENT("/*%08X*/ "),rManResTok[ix]);
846 if(IsMrPublic(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("public "));
847 if(IsMrPrivate(dwFlags)) strcat_s(szString,SZSTRING_SIZE,KEYWORD("private "));
848
849 char* pc = szString + strlen(szString);
850 wzName[ulNameLen]=0;
851
852 WszWideCharToMultiByte(CP_UTF8,0,wzName,-1,sz,sizeof(sz),NULL,NULL);
853 strcpy_s(pc,SZSTRING_REMAINING_SIZE(pc),ProperName(sz));
854
855 // get rid of invalid characters and reserved names
856 BOOL fAlias = ConvertToLegalFileNameInPlace(wzName);
857
858 // check for duplicate file name
859 WCHAR *wpc = wzName + wcslen(wzName);
860 for (int iIndex = 1;; iIndex++)
861 {
862 BOOL fConflict = FALSE;
863 if (*wzName == 0)
864 {
865 // resource with an empty name
866 fConflict = TRUE;
867 }
868 else
869 {
870 for (ULONG i = 0; i < (ix + 2); i++)
871 {
872 WCHAR *wzPreviousName = (WCHAR *)qbNameArray[i].Ptr();
873 if (wzPreviousName && _wcsicmp(wzName, wzPreviousName) == 0)
874 {
875 // resource with the same name as another resource
876 // or with the same name as the output IL/RES file
877 fConflict = TRUE;
878 break;
879 }
880 }
881 }
882
883 // if we have a conflict, add a number suffix to the file name
884 if (!fConflict ||
885 swprintf_s(wpc, 2048 - (wpc - wzFileName), W("%d"), iIndex) <= 0)
886 {
887 // no conflict or unable to add index
888 break;
889 }
890
891 // try again with this new number suffix
892 fAlias = TRUE;
893 }
894
895 // add this unique file name to the list
896 NAME_ARRAY_ADD(ix + 2, wzName);
897
898 if(fAlias)
899 {
900 // update sz with the aliased name and print the 'as' keyword
901 if (WszWideCharToMultiByte(CP_UTF8, 0, wzName, -1, sz, sizeof(sz), NULL, NULL) == 0)
902 {
903 sz[sizeof(sz) - 1] = 0;
904 }
905
906 pc=&szString[strlen(szString)];
907 sprintf_s(pc,SZSTRING_REMAINING_SIZE(pc)," %s %s",KEYWORD("as"),ProperName(sz));
908 }
909
910 printLine(GUICookie,szString);
911 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
912 printLine(GUICookie,szString);
913 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
914 DumpCustomAttributes(rManResTok[ix], GUICookie);
915
916 if(tkImplementation == mdFileNil) // embedded resource -- dump as .resources file
917 {
918 if(pRes == NULL)
919 {
920 // get the resource VA
921 if (g_pPELoader->getVAforRVA((DWORD) VAL32(g_CORHeader->Resources.VirtualAddress), (void **) &pRes) == FALSE)
922 {
923 printError(GUICookie,RstrUTF(IDS_E_IMPORTDATA));
924 }
925 }
926 if(pRes)
927 {
928 DumpResourceFile(GUICookie, pRes, dwOffset, wzName, wzFileName, sz);
929 }
930 }
931 else DumpImplementation(tkImplementation,dwOffset,szString,GUICookie);
932 g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
933 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
934 printLine(GUICookie,szString);
935 } //end if(OK(GetManifestResourceProps))
936 }//end for(all manifest resources)
937
938#undef NAME_ARRAY_ADD
939
940 }//end if(nManRes)
941 g_pAssemblyImport->CloseEnum(hEnum);
942 }//end if OK(EnumManifestResources)
943 else nManRes=0;
944}
945
946IMetaDataAssemblyImport* GetAssemblyImport(void* GUICookie)
947{
948 struct Param
949 {
950 void* GUICookie;
951 IMetaDataAssemblyImport* pAssemblyImport;
952 IMDInternalImport* pImport;
953 mdToken tkManifest;
954 } param;
955 param.GUICookie = GUICookie;
956 param.pAssemblyImport = NULL;
957 param.pImport = NULL;
958
959 HRESULT hr;
960
961 hr=g_pPubImport->QueryInterface(IID_IMetaDataAssemblyImport, (void**) &param.pAssemblyImport);
962 if(SUCCEEDED(hr))
963 {
964 static mdAssemblyRef rAsmRefTok[4096];
965 HCORENUM hEnum=NULL;
966 ULONG nAsmRefs = 0;
967 if(SUCCEEDED(param.pAssemblyImport->GetAssemblyFromScope(&param.tkManifest))) return param.pAssemblyImport;
968 if(SUCCEEDED(param.pAssemblyImport->EnumAssemblyRefs(&hEnum,rAsmRefTok,4096,&nAsmRefs)))
969 {
970 param.pAssemblyImport->CloseEnum(hEnum);
971 if(nAsmRefs) return param.pAssemblyImport;
972 }
973 param.pAssemblyImport->Release();
974 }
975 else
976 {
977 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_MDAIMPORT),hr);
978 printLine(GUICookie,COMMENT(szString));
979 }
980 param.pAssemblyImport = NULL;
981 // OK, let's do it hard way: check if the manifest is hidden somewhere else
982 PAL_TRY(Param *, pParam, &param)
983 {
984 if(g_CORHeader->Resources.Size)
985 {
986 DWORD* pdwSize = NULL;
987 BYTE* pbManifest = NULL;
988 HRESULT hr;
989
990 pbManifest = (BYTE*)(g_pPELoader->base() + (DWORD)VAL32(g_CORHeader->Resources.VirtualAddress));
991 pdwSize = (DWORD*)pbManifest;
992 if(pdwSize && *pdwSize)
993 {
994 pbManifest += sizeof(DWORD);
995 if (SUCCEEDED(hr = getMetaDataInternalInterface(
996 pbManifest,
997 VAL32(*pdwSize),
998 ofRead,
999 IID_IMDInternalImport,
1000 (LPVOID *)&pParam->pImport)))
1001 {
1002 if (FAILED(hr = getMetaDataPublicInterfaceFromInternal(
1003 pParam->pImport,
1004 IID_IMetaDataAssemblyImport,
1005 (LPVOID *)&pParam->pAssemblyImport)))
1006 {
1007 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_MDAFROMMDI),hr);
1008 printLine(pParam->GUICookie,COMMENT(szString));
1009 pParam->pAssemblyImport = NULL;
1010 }
1011 else
1012 {
1013 mdAssemblyRef rAsmRefTok[4096];
1014 HCORENUM hEnum=NULL;
1015 ULONG nAsmRefs = 0;
1016 if(FAILED(pParam->pAssemblyImport->GetAssemblyFromScope(&pParam->tkManifest))
1017 && (FAILED(pParam->pAssemblyImport->EnumAssemblyRefs(&hEnum,rAsmRefTok,4096,&nAsmRefs))
1018 || (nAsmRefs ==0)))
1019 {
1020 pParam->pAssemblyImport->CloseEnum(hEnum);
1021 pParam->pAssemblyImport->Release();
1022 pParam->pAssemblyImport = NULL;
1023 }
1024 }
1025 pParam->pImport->Release();
1026 }
1027 else
1028 {
1029 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_MDIIMPORT),hr);
1030 printLine(pParam->GUICookie,COMMENT(szString));
1031 }
1032 }
1033 }
1034 } // end try
1035 PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1036 {
1037 if(param.pAssemblyImport) param.pAssemblyImport->Release();
1038 param.pAssemblyImport = NULL;
1039 if(param.pImport) param.pImport->Release();
1040 }
1041 PAL_ENDTRY
1042 return param.pAssemblyImport;
1043}
1044
1045static void DumpMetadataVersion(void* GUICookie)
1046{
1047 LPCSTR pVersionStr;
1048 if (g_pImport == NULL || FAILED(g_pImport->GetVersionString(&pVersionStr)))
1049 {
1050 pVersionStr = "**Unavailable**";
1051 }
1052 sprintf_s(szString,SZSTRING_SIZE,"// Metadata version: %s",pVersionStr);
1053 printLine(GUICookie,szString);
1054}
1055
1056void DumpManifest(void* GUICookie)
1057{
1058 DumpMetadataVersion(GUICookie);
1059 DumpModuleRefs(GUICookie);
1060 if(g_pAssemblyImport==NULL) g_pAssemblyImport = GetAssemblyImport(GUICookie);
1061 if(g_pAssemblyImport)
1062 {
1063 DumpAssemblyRefs(GUICookie);
1064 DumpAssembly(GUICookie,TRUE);
1065 DumpFiles(GUICookie);
1066 DumpComTypes(GUICookie);
1067 DumpManifestResources(GUICookie);
1068 }
1069 else printLine(GUICookie,COMMENT(RstrUTF(IDS_E_NOMANIFEST)));
1070 DumpScope(GUICookie);
1071 DumpVtable(GUICookie);
1072
1073}
1074