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 * ; |
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_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 | |
280 | MTokName* rAsmRef = NULL; |
281 | ULONG nAsmRefs = 0; |
282 | |
283 | void 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 | |
415 | DynamicArray<LocalComTypeDescr*> *g_pLocalComType = NULL; |
416 | ULONG g_LocalComTypeNum = 0; |
417 | |
418 | void 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 | |
441 | void 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 | |
506 | void 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 | |
547 | void 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. |
631 | static 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. |
708 | static 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, ¶m) |
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, ¶m) { |
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 | |
778 | void 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 | |
946 | IMetaDataAssemblyImport* 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**) ¶m.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(¶m.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, ¶m) |
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 | |
1045 | static 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 | |
1056 | void 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 | |