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#include <stdio.h>
6#include <windows.h>
7#include <objbase.h>
8#include <crtdbg.h>
9#include <assert.h>
10
11#include <corpriv.h>
12#include <cor.h>
13#include "assert.h"
14#include "corerror.h"
15#include <winwrap.h>
16#include <prettyprintsig.h>
17
18#include <cahlpr.h>
19#include <limits.h>
20
21#include "mdinfo.h"
22
23#define LEGACY_ACTIVATION_SHIM_LOAD_LIBRARY WszLoadLibrary
24#define LEGACY_ACTIVATION_SHIM_DEFINE_CoInitializeEE
25
26#define ENUM_BUFFER_SIZE 10
27#define TAB_SIZE 8
28
29#define NumItems(s) (sizeof(s) / sizeof(s[0]))
30
31#define ISFLAG(p,x) if (Is##p##x(flags)) strcat_s(sFlags,STRING_BUFFER_LEN, "["#x "] ");
32
33extern HRESULT _FillVariant(
34 BYTE bCPlusTypeFlag,
35 void const *pValue,
36 ULONG cbValue,
37 VARIANT *pvar);
38
39// Validator declarations.
40extern DWORD g_ValModuleType;
41
42// Tables for mapping element type to text
43const char *g_szMapElementType[] =
44{
45 "End", // 0x0
46 "Void", // 0x1
47 "Boolean",
48 "Char",
49 "I1",
50 "UI1",
51 "I2", // 0x6
52 "UI2",
53 "I4",
54 "UI4",
55 "I8",
56 "UI8",
57 "R4",
58 "R8",
59 "String",
60 "Ptr", // 0xf
61 "ByRef", // 0x10
62 "ValueClass",
63 "Class",
64 "Var",
65 "MDArray", // 0x14
66 "GenericInst",
67 "TypedByRef",
68 "VALUEARRAY",
69 "I",
70 "U",
71 "R", // 0x1a
72 "FNPTR",
73 "Object",
74 "SZArray",
75 "MVar",
76 "CMOD_REQD",
77 "CMOD_OPT",
78 "INTERNAL",
79};
80
81const char *g_szMapUndecorateType[] =
82{
83 "", // 0x0
84 "void",
85 "boolean",
86 "Char",
87 "byte",
88 "unsigned byte",
89 "short",
90 "unsigned short",
91 "int",
92 "unsigned int",
93 "long",
94 "unsigned long",
95 "float",
96 "double",
97 "String",
98 "*", // 0xf
99 "ByRef",
100 "",
101 "",
102 "",
103 "",
104 "",
105 "",
106 "",
107 "",
108 "",
109 "",
110 "Function Pointer",
111 "Object",
112 "",
113 "",
114 "CMOD_REQD",
115 "CMOD_OPT",
116 "INTERNAL",
117};
118
119// Provide enough entries for IMAGE_CEE_CS_CALLCONV_MASK (defined in CorHdr.h)
120const char *g_strCalling[] =
121{
122 "[DEFAULT]",
123 "[C]",
124 "[STDCALL]",
125 "[THISCALL]",
126 "[FASTCALL]",
127 "[VARARG]",
128 "[FIELD]",
129 "[LOCALSIG]",
130 "[PROPERTY]",
131 "[UNMANAGED]",
132 "[GENERICINST]",
133 "[NATIVEVARARG]",
134 "[INVALID]",
135 "[INVALID]",
136 "[INVALID]",
137 "[INVALID]"
138};
139
140const char *g_szNativeType[] =
141{
142 "NATIVE_TYPE_END(DEPRECATED!)", // = 0x0, //DEPRECATED
143 "NATIVE_TYPE_VOID(DEPRECATED!)", // = 0x1, //DEPRECATED
144 "NATIVE_TYPE_BOOLEAN", // = 0x2, // (4 byte boolean value: TRUE = non-zero, FALSE = 0)
145 "NATIVE_TYPE_I1", // = 0x3,
146 "NATIVE_TYPE_U1", // = 0x4,
147 "NATIVE_TYPE_I2", // = 0x5,
148 "NATIVE_TYPE_U2", // = 0x6,
149 "NATIVE_TYPE_I4", // = 0x7,
150 "NATIVE_TYPE_U4", // = 0x8,
151 "NATIVE_TYPE_I8", // = 0x9,
152 "NATIVE_TYPE_U8", // = 0xa,
153 "NATIVE_TYPE_R4", // = 0xb,
154 "NATIVE_TYPE_R8", // = 0xc,
155 "NATIVE_TYPE_SYSCHAR(DEPRECATED!)", // = 0xd, //DEPRECATED
156 "NATIVE_TYPE_VARIANT(DEPRECATED!)", // = 0xe, //DEPRECATED
157 "NATIVE_TYPE_CURRENCY", // = 0xf,
158 "NATIVE_TYPE_PTR(DEPRECATED!)", // = 0x10, //DEPRECATED
159
160 "NATIVE_TYPE_DECIMAL(DEPRECATED!)", // = 0x11, //DEPRECATED
161 "NATIVE_TYPE_DATE(DEPRECATED!)", // = 0x12, //DEPRECATED
162 "NATIVE_TYPE_BSTR", // = 0x13,
163 "NATIVE_TYPE_LPSTR", // = 0x14,
164 "NATIVE_TYPE_LPWSTR", // = 0x15,
165 "NATIVE_TYPE_LPTSTR", // = 0x16,
166 "NATIVE_TYPE_FIXEDSYSSTRING", // = 0x17,
167 "NATIVE_TYPE_OBJECTREF(DEPRECATED!)", // = 0x18, //DEPRECATED
168 "NATIVE_TYPE_IUNKNOWN", // = 0x19,
169 "NATIVE_TYPE_IDISPATCH", // = 0x1a,
170 "NATIVE_TYPE_STRUCT", // = 0x1b,
171 "NATIVE_TYPE_INTF", // = 0x1c,
172 "NATIVE_TYPE_SAFEARRAY", // = 0x1d,
173 "NATIVE_TYPE_FIXEDARRAY", // = 0x1e,
174 "NATIVE_TYPE_INT", // = 0x1f,
175 "NATIVE_TYPE_UINT", // = 0x20,
176
177 "NATIVE_TYPE_NESTEDSTRUCT(DEPRECATED!)", // = 0x21, //DEPRECATED (use "NATIVE_TYPE_STRUCT)
178
179 "NATIVE_TYPE_BYVALSTR", // = 0x22,
180
181 "NATIVE_TYPE_ANSIBSTR", // = 0x23,
182
183 "NATIVE_TYPE_TBSTR", // = 0x24, // select BSTR or ANSIBSTR depending on platform
184
185
186 "NATIVE_TYPE_VARIANTBOOL", // = 0x25, // (2-byte boolean value: TRUE = -1, FALSE = 0)
187 "NATIVE_TYPE_FUNC", // = 0x26,
188 "NATIVE_TYPE_LPVOID", // = 0x27, // blind pointer (no deep marshaling)
189
190 "NATIVE_TYPE_ASANY", // = 0x28,
191 "<UNDEFINED NATIVE TYPE 0x29>",
192 "NATIVE_TYPE_ARRAY", // = 0x2a,
193 "NATIVE_TYPE_LPSTRUCT", // = 0x2b,
194 "NATIVE_TYPE_CUSTOMMARSHALER", // = 0x2c, // Custom marshaler.
195 "NATIVE_TYPE_ERROR", // = 0x2d, // VT_HRESULT when exporting to a typelib.
196};
197
198
199size_t g_cbCoffNames = 0;
200
201mdMethodDef g_tkEntryPoint = 0; // integration with ILDASM
202
203
204
205// helper to init signature buffer
206void MDInfo::InitSigBuffer()
207{
208 strcpy_s((LPSTR)m_sigBuf.Ptr(), 1, "");
209} // void MDInfo::InitSigBuffer()
210
211// helper to append a string into the signature buffer. If size of signature buffer is not big enough,
212// we will grow it.
213HRESULT MDInfo::AddToSigBuffer(__in_z __in const char *string)
214{
215 HRESULT hr;
216 size_t LL = strlen((LPSTR)m_sigBuf.Ptr()) + strlen(string) + 1;
217 IfFailRet( m_sigBuf.ReSizeNoThrow(LL) );
218 strcat_s((LPSTR)m_sigBuf.Ptr(), LL, string);
219 return NOERROR;
220} // HRESULT MDInfo::AddToSigBuffer()
221
222MDInfo::MDInfo(IMetaDataImport2 *pImport, IMetaDataAssemblyImport *pAssemblyImport, LPCWSTR szScope, strPassBackFn inPBFn, ULONG DumpFilter)
223{ // This constructor is specific to ILDASM/MetaInfo integration
224
225 _ASSERTE(pImport != NULL);
226 _ASSERTE(NumItems(g_szMapElementType) == NumItems(g_szMapUndecorateType));
227 _ASSERTE(NumItems(g_szMapElementType) == ELEMENT_TYPE_MAX);
228
229 Init(inPBFn, (DUMP_FILTER)DumpFilter);
230
231 m_pImport = pImport;
232 m_pImport->AddRef();
233 if ((m_pAssemblyImport = pAssemblyImport))
234 m_pAssemblyImport->AddRef();
235 else
236 {
237 HRESULT hr = m_pImport->QueryInterface(IID_IMetaDataAssemblyImport, (void**) &m_pAssemblyImport);
238 if (FAILED(hr))
239 Error("QueryInterface failed for IID_IMetaDataAssemblyImport.", hr);
240 }
241
242} // MDInfo::MDInfo()
243
244MDInfo::MDInfo(IMetaDataDispenserEx *pDispenser, LPCWSTR szScope, strPassBackFn inPBFn, ULONG DumpFilter)
245{
246 HRESULT hr = S_OK;
247 VARIANT value;
248
249 _ASSERTE(pDispenser != NULL && inPBFn != NULL);
250 _ASSERTE(NumItems(g_szMapElementType) == NumItems(g_szMapUndecorateType));
251 _ASSERTE(NumItems(g_szMapElementType) == ELEMENT_TYPE_MAX);
252
253 Init(inPBFn, (DUMP_FILTER)DumpFilter);
254
255 // Attempt to open scope on given file
256 V_VT(&value) = VT_UI4;
257 V_UI4(&value) = MDImportOptionAll;
258 if (FAILED(hr = pDispenser->SetOption(MetaDataImportOption, &value)))
259 Error("SetOption failed.", hr);
260
261 hr = pDispenser->OpenScope(szScope, ofNoTransform, IID_IMetaDataImport2, (IUnknown**)&m_pImport);
262 if (hr == CLDB_E_BADUPDATEMODE)
263 {
264 V_VT(&value) = VT_UI4;
265 V_UI4(&value) = MDUpdateIncremental;
266 if (FAILED(hr = pDispenser->SetOption(MetaDataSetUpdate, &value)))
267 Error("SetOption failed.", hr);
268 hr = pDispenser->OpenScope(szScope, ofNoTransform, IID_IMetaDataImport2, (IUnknown**)&m_pImport);
269 }
270 if (FAILED(hr))
271 Error("OpenScope failed", hr);
272
273 // Query for the IMetaDataAssemblyImport interface.
274 hr = m_pImport->QueryInterface(IID_IMetaDataAssemblyImport, (void**) &m_pAssemblyImport);
275 if (FAILED(hr))
276 Error("QueryInterface failed for IID_IMetaDataAssemblyImport.", hr);
277
278} // MDInfo::MDInfo()
279
280
281MDInfo::MDInfo(IMetaDataDispenserEx *pDispenser, PBYTE pbMetaData, DWORD dwSize, strPassBackFn inPBFn, ULONG DumpFilter)
282{
283 _ASSERTE(pDispenser != NULL && inPBFn != NULL);
284 _ASSERTE(NumItems(g_szMapElementType) == NumItems(g_szMapUndecorateType));
285 _ASSERTE(NumItems(g_szMapElementType) == ELEMENT_TYPE_MAX);
286
287 Init(inPBFn, (DUMP_FILTER)DumpFilter);
288
289 // Attempt to open scope on manifest. It's valid for this to fail, because
290 // the blob we open may just be the assembly resources (the space is
291 // overloaded until we remove LM -a assemblies, at which point this
292 // constructor should probably be removed too).
293 HRESULT hr;
294 VARIANT value;
295 V_VT(&value) = VT_UI4;
296 V_UI4(&value) = MDImportOptionAll;
297 if (FAILED(hr = pDispenser->SetOption(MetaDataImportOption, &value)))
298 Error("SetOption failed.", hr);
299 if (SUCCEEDED(hr = pDispenser->OpenScopeOnMemory(pbMetaData, dwSize, ofNoTransform,
300 IID_IMetaDataImport2, (IUnknown**)&m_pImport)))
301 {
302 // Query for the IMetaDataAssemblyImport interface.
303 hr = m_pImport->QueryInterface(IID_IMetaDataAssemblyImport, (void**) &m_pAssemblyImport);
304 if (FAILED(hr))
305 Error("QueryInterface failed for IID_IMetaDataAssemblyImport.", hr);
306 }
307
308} // MDInfo::MDInfo()
309
310void MDInfo::Init(
311 strPassBackFn inPBFn, // Callback to write text.
312 DUMP_FILTER DumpFilter) // Flags to control the dump.
313{
314 m_pbFn = inPBFn;
315 m_DumpFilter = DumpFilter;
316 m_pTables = NULL;
317 m_pTables2 = NULL;
318 m_pImport = NULL;
319 m_pAssemblyImport = NULL;
320} // void MDInfo::Init()
321
322// Destructor
323MDInfo::~MDInfo()
324{
325 if (m_pImport)
326 m_pImport->Release();
327 if (m_pAssemblyImport)
328 m_pAssemblyImport->Release();
329 if (m_pTables)
330 m_pTables->Release();
331 if (m_pTables2)
332 m_pTables2->Release();
333} // MDInfo::~MDInfo()
334
335//=====================================================================================================================
336// DisplayMD() function
337//
338// Displays the meta data content of a file
339
340void MDInfo::DisplayMD()
341{
342 if ((m_DumpFilter & dumpAssem) && m_pAssemblyImport)
343 DisplayAssemblyInfo();
344 WriteLine("===========================================================");
345 // Metadata itself: Raw or normal view
346 if (m_DumpFilter & (dumpSchema | dumpHeader | dumpCSV | dumpRaw | dumpStats | dumpRawHeaps))
347 DisplayRaw();
348 else
349 {
350 DisplayVersionInfo();
351 DisplayScopeInfo();
352 WriteLine("===========================================================");
353 DisplayGlobalFunctions();
354 DisplayGlobalFields();
355 DisplayGlobalMemberRefs();
356 DisplayTypeDefs();
357 DisplayTypeRefs();
358 DisplayTypeSpecs();
359 DisplayMethodSpecs();
360 DisplayModuleRefs();
361 DisplaySignatures();
362 DisplayAssembly();
363 DisplayUserStrings();
364
365 // WriteLine("============================================================");
366 // WriteLine("Unresolved MemberRefs");
367 // DisplayMemberRefs(0x00000001, "\t");
368
369 VWrite("\n\nCoff symbol name overhead: %d\n", g_cbCoffNames);
370 }
371 WriteLine("===========================================================");
372 if (m_DumpFilter & dumpUnsat)
373 DisplayUnsatInfo();
374 WriteLine("===========================================================");
375} // MDVEHandlerClass()
376
377int MDInfo::WriteLine(__in_z __in const char *str)
378{
379 ULONG32 count = (ULONG32) strlen(str);
380
381 m_pbFn(str);
382 m_pbFn("\n");
383 return count;
384} // int MDInfo::WriteLine()
385
386int MDInfo::Write(__in_z __in const char *str)
387{
388 ULONG32 count = (ULONG32) strlen(str);
389
390 m_pbFn(str);
391 return count;
392} // int MDInfo::Write()
393
394int MDInfo::VWriteLine(__in_z __in const char *str, ...)
395{
396 va_list marker;
397 int count;
398
399 va_start(marker, str);
400 count = VWriteMarker(str, marker);
401 m_pbFn("\n");
402 va_end(marker);
403 return count;
404} // int MDInfo::VWriteLine()
405
406int MDInfo::VWrite(__in_z __in const char *str, ...)
407{
408 va_list marker;
409 int count;
410
411 va_start(marker, str);
412 count = VWriteMarker(str, marker);
413 va_end(marker);
414 return count;
415} // int MDInfo::VWrite()
416
417int MDInfo::VWriteMarker(__in_z __in const char *str, va_list marker)
418{
419 HRESULT hr;
420 int count = -1;
421 // Used to allocate 1K, then if not enough, 2K, then 4K.
422 // Faster to allocate 32K right away and be done with it,
423 // we're not running on Commodore 64
424 if (FAILED(hr = m_output.ReSizeNoThrow(STRING_BUFFER_LEN * 8)))
425 Error("ReSize failed.", hr);
426 else
427 {
428 count = vsprintf_s((char *)m_output.Ptr(), STRING_BUFFER_LEN * 8, str, marker);
429 m_pbFn((char *)m_output.Ptr());
430 }
431 return count;
432} // int MDInfo::VWriteToBuffer()
433
434// Error() function -- prints an error and returns
435void MDInfo::Error(const char* szError, HRESULT hr)
436{
437 printf("\n%s\n",szError);
438 if (hr != S_OK)
439 {
440 printf("Failed return code: 0x%08x\n", hr);
441
442 IErrorInfo *pIErr = NULL; // Error interface.
443 BSTR bstrDesc = NULL; // Description text.
444#ifdef FEATURE_COMINTEROP
445 // Try to get an error info object and display the message.
446 if (GetErrorInfo(0, &pIErr) == S_OK &&
447 pIErr->GetDescription(&bstrDesc) == S_OK)
448 {
449 printf("%ls ", bstrDesc);
450 SysFreeString(bstrDesc);
451 }
452#endif
453 // Free the error interface.
454 if (pIErr)
455 pIErr->Release();
456
457 }
458 exit(hr);
459} // void MDInfo::Error()
460
461// Print out the optional version info included in the MetaData.
462
463void MDInfo::DisplayVersionInfo()
464{
465 if (!(m_DumpFilter & MDInfo::dumpNoLogo))
466 {
467 LPCUTF8 pVersionStr;
468 HRESULT hr = S_OK;
469
470 if (m_pTables == 0)
471 {
472 if (m_pImport)
473 hr = m_pImport->QueryInterface(IID_IMetaDataTables, (void**)&m_pTables);
474 else if (m_pAssemblyImport)
475 hr = m_pAssemblyImport->QueryInterface(IID_IMetaDataTables, (void**)&m_pTables);
476 else
477 return;
478 if (FAILED(hr))
479 Error("QueryInterface failed for IID_IMetaDataTables.", hr);
480 }
481
482 hr = m_pTables->GetString(1, &pVersionStr);
483 if (FAILED(hr))
484 Error("GetString() failed.", hr);
485 if (strstr(pVersionStr, "Version of runtime against which the binary is built : ")
486 == pVersionStr)
487 {
488 WriteLine(const_cast<char *>(pVersionStr));
489 }
490 }
491} // void MDInfo::DisplayVersionInfo()
492
493// Prints out information about the scope
494
495void MDInfo::DisplayScopeInfo()
496{
497 HRESULT hr;
498 mdModule mdm;
499 GUID mvid;
500 WCHAR scopeName[STRING_BUFFER_LEN];
501 WCHAR guidString[STRING_BUFFER_LEN];
502
503 hr = m_pImport->GetScopeProps( scopeName, STRING_BUFFER_LEN, 0, &mvid);
504 if (FAILED(hr)) Error("GetScopeProps failed.", hr);
505
506 VWriteLine("ScopeName : %ls",scopeName);
507
508 if (!(m_DumpFilter & MDInfo::dumpNoLogo))
509 VWriteLine("MVID : %ls",GUIDAsString(mvid, guidString, STRING_BUFFER_LEN));
510
511 hr = m_pImport->GetModuleFromScope(&mdm);
512 if (FAILED(hr)) Error("GetModuleFromScope failed.", hr);
513 DisplayPermissions(mdm, "");
514 DisplayCustomAttributes(mdm, "\t");
515} // void MDInfo::DisplayScopeInfo()
516
517void MDInfo::DisplayRaw()
518{
519 int iDump; // Level of info to dump.
520
521 if (m_pTables == 0)
522 m_pImport->QueryInterface(IID_IMetaDataTables, (void**)&m_pTables);
523 if (m_pTables == 0)
524 Error("Can't get table info.");
525 if (m_pTables2 == 0)
526 m_pImport->QueryInterface(IID_IMetaDataTables2, (void**)&m_pTables2);
527
528 if (m_DumpFilter & dumpCSV)
529 DumpRawCSV();
530 if (m_DumpFilter & (dumpSchema | dumpHeader | dumpRaw | dumpStats))
531 {
532 if (m_DumpFilter & dumpRaw)
533 iDump = 3;
534 else
535 if (m_DumpFilter & dumpSchema)
536 iDump = 2;
537 else
538 iDump = 1;
539
540 DumpRaw(iDump, (m_DumpFilter & dumpStats) != 0);
541 }
542 if (m_DumpFilter & dumpRawHeaps)
543 DumpRawHeaps();
544} // void MDInfo::DisplayRaw()
545
546// return the name of the type of token passed in
547
548const char *MDInfo::TokenTypeName(mdToken inToken)
549{
550 switch(TypeFromToken(inToken))
551 {
552 case mdtTypeDef: return "TypeDef";
553 case mdtInterfaceImpl: return "InterfaceImpl";
554 case mdtMethodDef: return "MethodDef";
555 case mdtFieldDef: return "FieldDef";
556 case mdtTypeRef: return "TypeRef";
557 case mdtMemberRef: return "MemberRef";
558 case mdtCustomAttribute:return "CustomAttribute";
559 case mdtParamDef: return "ParamDef";
560 case mdtProperty: return "Property";
561 case mdtEvent: return "Event";
562 case mdtTypeSpec: return "TypeSpec";
563 default: return "[UnknownTokenType]";
564 }
565} // char *MDInfo::TokenTypeName()
566
567// Prints out name of the given memberref
568//
569
570LPCWSTR MDInfo::MemberRefName(mdMemberRef inMemRef, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen)
571{
572 HRESULT hr;
573
574
575 hr = m_pImport->GetMemberRefProps( inMemRef, NULL, buffer, bufLen,
576 NULL, NULL, NULL);
577 if (FAILED(hr)) Error("GetMemberRefProps failed.", hr);
578
579 return buffer;
580} // LPCWSTR MDInfo::MemberRefName()
581
582
583// Prints out information about the given memberref
584//
585
586void MDInfo::DisplayMemberRefInfo(mdMemberRef inMemRef, const char *preFix)
587{
588 HRESULT hr;
589 WCHAR memRefName[STRING_BUFFER_LEN];
590 ULONG nameLen;
591 mdToken token;
592 PCCOR_SIGNATURE pbSigBlob;
593 ULONG ulSigBlob;
594 char newPreFix[STRING_BUFFER_LEN];
595
596
597 hr = m_pImport->GetMemberRefProps( inMemRef, &token, memRefName, STRING_BUFFER_LEN,
598 &nameLen, &pbSigBlob, &ulSigBlob);
599 if (FAILED(hr)) Error("GetMemberRefProps failed.", hr);
600
601 VWriteLine("%s\t\tMember: (%8.8x) %ls: ", preFix, inMemRef, memRefName);
602
603 if (ulSigBlob)
604 DisplaySignature(pbSigBlob, ulSigBlob, preFix);
605 else
606 VWriteLine("%s\t\tERROR: no valid signature ", preFix);
607
608 sprintf_s (newPreFix, STRING_BUFFER_LEN, "\t\t%s", preFix);
609 DisplayCustomAttributes(inMemRef, newPreFix);
610} // void MDInfo::DisplayMemberRefInfo()
611
612// Prints out information about all memberrefs of the given typeref
613//
614
615void MDInfo::DisplayMemberRefs(mdToken tkParent, const char *preFix)
616{
617 HCORENUM memRefEnum = NULL;
618 HRESULT hr;
619 mdMemberRef memRefs[ENUM_BUFFER_SIZE];
620 ULONG count, totalCount = 1;
621
622
623 while (SUCCEEDED(hr = m_pImport->EnumMemberRefs( &memRefEnum, tkParent,
624 memRefs, NumItems(memRefs), &count)) &&
625 count > 0)
626 {
627 for (ULONG i = 0; i < count; i++, totalCount++)
628 {
629 VWriteLine("%s\tMemberRef #%d (%08x)", preFix, totalCount, memRefs[i]);
630 VWriteLine("%s\t-------------------------------------------------------", preFix);
631 DisplayMemberRefInfo(memRefs[i], preFix);
632 }
633 }
634 m_pImport->CloseEnum( memRefEnum);
635} // void MDInfo::DisplayMemberRefs()
636
637// Prints out information about all resources in the com object
638//
639
640// Iterates through each typeref and prints out the information of each
641//
642
643void MDInfo::DisplayTypeRefs()
644{
645 HCORENUM typeRefEnum = NULL;
646 mdTypeRef typeRefs[ENUM_BUFFER_SIZE];
647 ULONG count, totalCount=1;
648 HRESULT hr;
649
650 while (SUCCEEDED(hr = m_pImport->EnumTypeRefs( &typeRefEnum,
651 typeRefs, NumItems(typeRefs), &count)) &&
652 count > 0)
653 {
654 for (ULONG i = 0; i < count; i++, totalCount++)
655 {
656 VWriteLine("TypeRef #%d (%08x)", totalCount, typeRefs[i]);
657 WriteLine("-------------------------------------------------------");
658 DisplayTypeRefInfo(typeRefs[i]);
659 DisplayMemberRefs(typeRefs[i], "");
660 WriteLine("");
661 }
662 }
663 m_pImport->CloseEnum( typeRefEnum);
664} // void MDInfo::DisplayTypeRefs()
665
666void MDInfo::DisplayTypeSpecs()
667{
668 HCORENUM typespecEnum = NULL;
669 mdTypeSpec typespecs[ENUM_BUFFER_SIZE];
670 ULONG count, totalCount=1;
671 HRESULT hr;
672
673 while (SUCCEEDED(hr = m_pImport->EnumTypeSpecs( &typespecEnum,
674 typespecs, NumItems(typespecs), &count)) &&
675 count > 0)
676 {
677 for (ULONG i = 0; i < count; i++, totalCount++)
678 {
679 VWriteLine("TypeSpec #%d (%08x)", totalCount, typespecs[i]);
680 WriteLine("-------------------------------------------------------");
681 DisplayTypeSpecInfo(typespecs[i], "");
682 DisplayMemberRefs(typespecs[i], "");
683 WriteLine("");
684 }
685 }
686 m_pImport->CloseEnum( typespecEnum);
687} // void MDInfo::DisplayTypeSpecs()
688
689void MDInfo::DisplayMethodSpecs()
690{
691 HCORENUM MethodSpecEnum = NULL;
692 mdMethodSpec MethodSpecs[ENUM_BUFFER_SIZE];
693 ULONG count, totalCount=1;
694///// HRESULT hr;
695
696
697///// HACK until I implement EnumMethodSpecs!
698///// while (SUCCEEDED(hr = m_pImport->EnumMethodSpecs( &MethodSpecEnum,
699///// MethodSpecs, NumItems(MethodSpecs), &count)) &&
700///// count > 0)
701 for (ULONG rid=1; m_pImport->IsValidToken(TokenFromRid(rid, mdtMethodSpec)); ++rid)
702 {
703// More hackery
704count = 1;
705MethodSpecs[0] = TokenFromRid(rid, mdtMethodSpec);
706// More hackery
707 for (ULONG i = 0; i < count; i++, totalCount++)
708 {
709 VWriteLine("MethodSpec #%d (%08x)", totalCount, MethodSpecs[i]);
710 DisplayMethodSpecInfo(MethodSpecs[i], "");
711 WriteLine("");
712 }
713 }
714 m_pImport->CloseEnum( MethodSpecEnum);
715} // void MDInfo::DisplayMethodSpecs()
716
717
718
719// Called to display the information about all typedefs in the object.
720//
721
722void MDInfo::DisplayTypeDefs()
723{
724 HCORENUM typeDefEnum = NULL;
725 mdTypeDef typeDefs[ENUM_BUFFER_SIZE];
726 ULONG count, totalCount = 1;
727 HRESULT hr;
728
729 while (SUCCEEDED(hr = m_pImport->EnumTypeDefs( &typeDefEnum,
730 typeDefs, NumItems(typeDefs), &count)) &&
731 count > 0)
732 {
733 for (ULONG i = 0; i < count; i++, totalCount++)
734 {
735 VWriteLine("TypeDef #%d (%08x)", totalCount, typeDefs[i]);
736 WriteLine("-------------------------------------------------------");
737 DisplayTypeDefInfo(typeDefs[i]);
738 WriteLine("");
739 }
740 }
741 m_pImport->CloseEnum( typeDefEnum);
742} // void MDInfo::DisplayTypeDefs()
743
744// Called to display the information about all modulerefs in the object.
745//
746
747void MDInfo::DisplayModuleRefs()
748{
749 HCORENUM moduleRefEnum = NULL;
750 mdModuleRef moduleRefs[ENUM_BUFFER_SIZE];
751 ULONG count, totalCount = 1;
752 HRESULT hr;
753
754 while (SUCCEEDED(hr = m_pImport->EnumModuleRefs( &moduleRefEnum,
755 moduleRefs, NumItems(moduleRefs), &count)) &&
756 count > 0)
757 {
758 for (ULONG i = 0; i < count; i++, totalCount++)
759 {
760 VWriteLine("ModuleRef #%d (%08x)", totalCount, moduleRefs[i]);
761 WriteLine("-------------------------------------------------------");
762 DisplayModuleRefInfo(moduleRefs[i]);
763 DisplayMemberRefs(moduleRefs[i], "");
764 WriteLine("");
765 }
766 }
767 m_pImport->CloseEnum( moduleRefEnum);
768} // void MDInfo::DisplayModuleRefs()
769
770// Prints out information about the given moduleref
771//
772
773void MDInfo::DisplayModuleRefInfo(mdModuleRef inModuleRef)
774{
775 HRESULT hr;
776 WCHAR moduleRefName[STRING_BUFFER_LEN];
777 ULONG nameLen;
778
779
780 hr = m_pImport->GetModuleRefProps( inModuleRef, moduleRefName, STRING_BUFFER_LEN,
781 &nameLen);
782 if (FAILED(hr)) Error("GetModuleRefProps failed.", hr);
783
784 VWriteLine("\t\tModuleRef: (%8.8x) %ls: ", inModuleRef, moduleRefName);
785 DisplayCustomAttributes(inModuleRef, "\t\t");
786} // void MDInfo::DisplayModuleRefInfo()
787
788
789// Called to display the information about all signatures in the object.
790//
791
792void MDInfo::DisplaySignatures()
793{
794 HCORENUM signatureEnum = NULL;
795 mdSignature signatures[ENUM_BUFFER_SIZE];
796 ULONG count, totalCount = 1;
797 HRESULT hr;
798
799 while (SUCCEEDED(hr = m_pImport->EnumSignatures( &signatureEnum,
800 signatures, NumItems(signatures), &count)) &&
801 count > 0)
802 {
803 for (ULONG i = 0; i < count; i++, totalCount++)
804 {
805 VWriteLine("Signature #%d (%#08x)", totalCount, signatures[i]);
806 WriteLine("-------------------------------------------------------");
807 DisplaySignatureInfo(signatures[i]);
808 WriteLine("");
809 }
810 }
811 m_pImport->CloseEnum( signatureEnum);
812} // void MDInfo::DisplaySignatures()
813
814
815// Prints out information about the given signature
816//
817
818void MDInfo::DisplaySignatureInfo(mdSignature inSignature)
819{
820 HRESULT hr;
821 PCCOR_SIGNATURE pbSigBlob;
822 ULONG ulSigBlob;
823
824
825 hr = m_pImport->GetSigFromToken( inSignature, &pbSigBlob, &ulSigBlob );
826 if (FAILED(hr)) Error("GetSigFromToken failed.", hr);
827 if(ulSigBlob)
828 DisplaySignature(pbSigBlob, ulSigBlob, "");
829 else
830 VWriteLine("\t\tERROR: no valid signature ");
831} // void MDInfo::DisplaySignatureInfo()
832
833
834// returns the passed-in buffer which is filled with the name of the given
835// member in wide characters
836//
837
838LPCWSTR MDInfo::MemberName(mdToken inToken, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen)
839{
840 HRESULT hr;
841
842
843 hr = m_pImport->GetMemberProps( inToken, NULL, buffer, bufLen,
844 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
845 if (FAILED(hr)) Error("GetMemberProps failed.", hr);
846
847 return (buffer);
848} // LPCWSTR MDInfo::MemberName()
849
850
851// displays information for the given method
852//
853
854void MDInfo::DisplayMethodInfo(mdMethodDef inMethod, DWORD *pflags)
855{
856 HRESULT hr;
857 mdTypeDef memTypeDef;
858 WCHAR memberName[STRING_BUFFER_LEN];
859 ULONG nameLen;
860 DWORD flags;
861 PCCOR_SIGNATURE pbSigBlob;
862 ULONG ulSigBlob;
863 ULONG ulCodeRVA;
864 ULONG ulImplFlags;
865
866
867 hr = m_pImport->GetMethodProps( inMethod, &memTypeDef, memberName, STRING_BUFFER_LEN,
868 &nameLen, &flags, &pbSigBlob, &ulSigBlob, &ulCodeRVA, &ulImplFlags);
869 if (FAILED(hr)) Error("GetMethodProps failed.", hr);
870 if (pflags)
871 *pflags = flags;
872
873 VWriteLine("\t\tMethodName: %ls (%8.8X)", memberName, inMethod);
874
875 char sFlags[STRING_BUFFER_LEN];
876
877 sFlags[0] = 0;
878 ISFLAG(Md, Public);
879 ISFLAG(Md, Private);
880 ISFLAG(Md, Family);
881 ISFLAG(Md, Assem);
882 ISFLAG(Md, FamANDAssem);
883 ISFLAG(Md, FamORAssem);
884 ISFLAG(Md, PrivateScope);
885 ISFLAG(Md, Static);
886 ISFLAG(Md, Final);
887 ISFLAG(Md, Virtual);
888 ISFLAG(Md, HideBySig);
889 ISFLAG(Md, ReuseSlot);
890 ISFLAG(Md, NewSlot);
891 ISFLAG(Md, Abstract);
892 ISFLAG(Md, SpecialName);
893 ISFLAG(Md, RTSpecialName);
894 ISFLAG(Md, PinvokeImpl);
895 ISFLAG(Md, UnmanagedExport);
896 if (!*sFlags)
897 strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
898
899 bool result = (((flags) & mdRTSpecialName) && !wcscmp((memberName), W(".ctor")));
900 if (result) strcat_s(sFlags, STRING_BUFFER_LEN, "[.ctor] ");
901 result = (((flags) & mdRTSpecialName) && !wcscmp((memberName), W(".cctor")));
902 if (result) strcat_s(sFlags,STRING_BUFFER_LEN, "[.cctor] ");
903 // "Reserved" flags
904 ISFLAG(Md, HasSecurity);
905 ISFLAG(Md, RequireSecObject);
906
907 VWriteLine("\t\tFlags : %s (%08x)", sFlags, flags);
908 VWriteLine("\t\tRVA : 0x%08x", ulCodeRVA);
909
910 flags = ulImplFlags;
911 sFlags[0] = 0;
912 ISFLAG(Mi, Native);
913 ISFLAG(Mi, IL);
914 ISFLAG(Mi, OPTIL);
915 ISFLAG(Mi, Runtime);
916 ISFLAG(Mi, Unmanaged);
917 ISFLAG(Mi, Managed);
918 ISFLAG(Mi, ForwardRef);
919 ISFLAG(Mi, PreserveSig);
920 ISFLAG(Mi, InternalCall);
921 ISFLAG(Mi, Synchronized);
922 ISFLAG(Mi, NoInlining);
923 if (!*sFlags)
924 strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
925
926 VWriteLine("\t\tImplFlags : %s (%08x)", sFlags, flags);
927
928 if (ulSigBlob)
929 DisplaySignature(pbSigBlob, ulSigBlob, "");
930 else
931 VWriteLine("\t\tERROR: no valid signature ");
932
933 DisplayGenericParams(inMethod, "\t\t");
934
935} // void MDInfo::DisplayMethodInfo()
936
937// displays the member information for the given field
938//
939
940void MDInfo::DisplayFieldInfo(mdFieldDef inField, DWORD *pdwFlags)
941{
942 HRESULT hr;
943 mdTypeDef memTypeDef;
944 WCHAR memberName[STRING_BUFFER_LEN];
945 ULONG nameLen;
946 DWORD flags;
947 PCCOR_SIGNATURE pbSigBlob;
948 ULONG ulSigBlob;
949 DWORD dwCPlusTypeFlag;
950 void const *pValue;
951 ULONG cbValue;
952#ifdef FEATURE_COMINTEROP
953 VARIANT defaultValue;
954
955 ::VariantInit(&defaultValue);
956#endif
957 hr = m_pImport->GetFieldProps( inField, &memTypeDef, memberName, STRING_BUFFER_LEN,
958 &nameLen, &flags, &pbSigBlob, &ulSigBlob, &dwCPlusTypeFlag,
959 &pValue, &cbValue);
960 if (FAILED(hr)) Error("GetFieldProps failed.", hr);
961
962 if (pdwFlags)
963 *pdwFlags = flags;
964
965#ifdef FEATURE_COMINTEROP
966 _FillVariant((BYTE)dwCPlusTypeFlag, pValue, cbValue, &defaultValue);
967#endif
968
969 char sFlags[STRING_BUFFER_LEN];
970
971 sFlags[0] = 0;
972 ISFLAG(Fd, Public);
973 ISFLAG(Fd, Private);
974 ISFLAG(Fd, Family);
975 ISFLAG(Fd, Assembly);
976 ISFLAG(Fd, FamANDAssem);
977 ISFLAG(Fd, FamORAssem);
978 ISFLAG(Fd, PrivateScope);
979 ISFLAG(Fd, Static);
980 ISFLAG(Fd, InitOnly);
981 ISFLAG(Fd, Literal);
982 ISFLAG(Fd, NotSerialized);
983 ISFLAG(Fd, SpecialName);
984 ISFLAG(Fd, RTSpecialName);
985 ISFLAG(Fd, PinvokeImpl);
986 // "Reserved" flags
987 ISFLAG(Fd, HasDefault);
988 if (!*sFlags)
989 strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
990
991 VWriteLine("\t\tField Name: %ls (%8.8X)", memberName, inField);
992 VWriteLine("\t\tFlags : %s (%08x)", sFlags, flags);
993#ifdef FEATURE_COMINTEROP
994 if (IsFdHasDefault(flags))
995 VWriteLine("\tDefltValue: (%s) %ls", g_szMapElementType[dwCPlusTypeFlag], VariantAsString(&defaultValue));
996#endif
997 if (!ulSigBlob) // Signature size should be non-zero for fields
998 VWriteLine("\t\tERROR: no valid signature ");
999 else
1000 DisplaySignature(pbSigBlob, ulSigBlob, "");
1001#ifdef FEATURE_COMINTEROP
1002 ::VariantClear(&defaultValue);
1003#endif
1004} // void MDInfo::DisplayFieldInfo()
1005
1006// displays the RVA for the given global field.
1007void MDInfo::DisplayFieldRVA(mdFieldDef inFieldDef)
1008{
1009 HRESULT hr;
1010 ULONG ulRVA;
1011
1012 hr = m_pImport->GetRVA(inFieldDef, &ulRVA, 0);
1013 if (FAILED(hr) && hr != CLDB_E_RECORD_NOTFOUND) Error("GetRVA failed.", hr);
1014
1015 VWriteLine("\t\tRVA : 0x%08x", ulRVA);
1016} // void MDInfo::DisplayFieldRVA()
1017
1018// displays information about every global function.
1019void MDInfo::DisplayGlobalFunctions()
1020{
1021 WriteLine("Global functions");
1022 WriteLine("-------------------------------------------------------");
1023 DisplayMethods(mdTokenNil);
1024 WriteLine("");
1025} // void MDInfo::DisplayGlobalFunctions()
1026
1027// displays information about every global field.
1028void MDInfo::DisplayGlobalFields()
1029{
1030 WriteLine("Global fields");
1031 WriteLine("-------------------------------------------------------");
1032 DisplayFields(mdTokenNil, NULL, 0);
1033 WriteLine("");
1034} // void MDInfo::DisplayGlobalFields()
1035
1036// displays information about every global memberref.
1037void MDInfo::DisplayGlobalMemberRefs()
1038{
1039 WriteLine("Global MemberRefs");
1040 WriteLine("-------------------------------------------------------");
1041 DisplayMemberRefs(mdTokenNil, "");
1042 WriteLine("");
1043} // void MDInfo::DisplayGlobalMemberRefs()
1044
1045// displays information about every method in a given typedef
1046//
1047
1048void MDInfo::DisplayMethods(mdTypeDef inTypeDef)
1049{
1050 HCORENUM methodEnum = NULL;
1051 mdToken methods[ENUM_BUFFER_SIZE];
1052 DWORD flags;
1053 ULONG count, totalCount = 1;
1054 HRESULT hr;
1055
1056
1057 while (SUCCEEDED(hr = m_pImport->EnumMethods( &methodEnum, inTypeDef,
1058 methods, NumItems(methods), &count)) &&
1059 count > 0)
1060 {
1061 for (ULONG i = 0; i < count; i++, totalCount++)
1062 {
1063 VWriteLine("\tMethod #%d (%08x) %s", totalCount, methods[i], (methods[i] == g_tkEntryPoint) ? "[ENTRYPOINT]" : "");
1064 WriteLine("\t-------------------------------------------------------");
1065 DisplayMethodInfo(methods[i], &flags);
1066 DisplayParams(methods[i]);
1067 DisplayCustomAttributes(methods[i], "\t\t");
1068 DisplayPermissions(methods[i], "\t");
1069 DisplayMemberRefs(methods[i], "\t");
1070
1071 // P-invoke data if present.
1072 if (IsMdPinvokeImpl(flags))
1073 DisplayPinvokeInfo(methods[i]);
1074
1075 WriteLine("");
1076 }
1077 }
1078 m_pImport->CloseEnum( methodEnum);
1079} // void MDInfo::DisplayMethods()
1080
1081
1082// displays information about every field in a given typedef
1083//
1084
1085void MDInfo::DisplayFields(mdTypeDef inTypeDef, COR_FIELD_OFFSET *rFieldOffset, ULONG cFieldOffset)
1086{
1087 HCORENUM fieldEnum = NULL;
1088 mdToken fields[ENUM_BUFFER_SIZE];
1089 ULONG count, totalCount = 1;
1090 DWORD flags;
1091 HRESULT hr;
1092
1093
1094 while (SUCCEEDED(hr = m_pImport->EnumFields( &fieldEnum, inTypeDef,
1095 fields, NumItems(fields), &count)) &&
1096 count > 0)
1097 {
1098 for (ULONG i = 0; i < count; i++, totalCount++)
1099 {
1100 VWriteLine("\tField #%d (%08x)",totalCount, fields[i]);
1101 WriteLine("\t-------------------------------------------------------");
1102 DisplayFieldInfo(fields[i], &flags);
1103 DisplayCustomAttributes(fields[i], "\t\t");
1104 DisplayPermissions(fields[i], "\t");
1105 DisplayFieldMarshal(fields[i]);
1106
1107 // RVA if its a global field.
1108 if (inTypeDef == mdTokenNil)
1109 DisplayFieldRVA(fields[i]);
1110
1111 // P-invoke data if present.
1112 if (IsFdPinvokeImpl(flags))
1113 DisplayPinvokeInfo(fields[i]);
1114
1115 // Display offset if present.
1116 if (cFieldOffset)
1117 {
1118 bool found = false;
1119 for (ULONG iLayout = 0; iLayout < cFieldOffset; ++iLayout)
1120 {
1121 if (RidFromToken(rFieldOffset[iLayout].ridOfField) == RidFromToken(fields[i]))
1122 {
1123 found = true;
1124 VWriteLine("\t\tOffset : 0x%08x", rFieldOffset[iLayout].ulOffset);
1125 break;
1126 }
1127 }
1128 _ASSERTE(found);
1129 }
1130 WriteLine("");
1131 }
1132 }
1133 m_pImport->CloseEnum( fieldEnum);
1134} // void MDInfo::DisplayFields()
1135
1136
1137// displays information about every methodImpl in a given typedef
1138//
1139
1140void MDInfo::DisplayMethodImpls(mdTypeDef inTypeDef)
1141{
1142 HCORENUM methodImplEnum = NULL;
1143 mdMethodDef rtkMethodBody[ENUM_BUFFER_SIZE];
1144 mdMethodDef rtkMethodDecl[ENUM_BUFFER_SIZE];
1145
1146 ULONG count, totalCount=1;
1147 HRESULT hr;
1148
1149
1150 while (SUCCEEDED(hr = m_pImport->EnumMethodImpls( &methodImplEnum, inTypeDef,
1151 rtkMethodBody, rtkMethodDecl, NumItems(rtkMethodBody), &count)) &&
1152 count > 0)
1153 {
1154 for (ULONG i = 0; i < count; i++, totalCount++)
1155 {
1156 VWriteLine("\n\tMethodImpl #%d (%08x)", totalCount, totalCount);
1157 WriteLine("\t-------------------------------------------------------");
1158 VWriteLine("\t\tMethod Body Token : 0x%08x", rtkMethodBody[i]);
1159 VWriteLine("\t\tMethod Declaration Token : 0x%08x", rtkMethodDecl[i]);
1160 WriteLine("");
1161 }
1162 }
1163 m_pImport->CloseEnum( methodImplEnum);
1164} // void MDInfo::DisplayMethodImpls()
1165
1166// displays information about the given parameter
1167//
1168
1169void MDInfo::DisplayParamInfo(mdParamDef inParamDef)
1170{
1171 mdMethodDef md;
1172 ULONG num;
1173 WCHAR paramName[STRING_BUFFER_LEN];
1174 ULONG nameLen;
1175 DWORD flags;
1176 VARIANT defValue;
1177 DWORD dwCPlusFlags;
1178 void const *pValue;
1179 ULONG cbValue;
1180
1181#ifdef FEATURE_COMINTEROP
1182 ::VariantInit(&defValue);
1183#endif
1184 HRESULT hr = m_pImport->GetParamProps( inParamDef, &md, &num, paramName, NumItems(paramName),
1185 &nameLen, &flags, &dwCPlusFlags, &pValue, &cbValue);
1186 if (FAILED(hr)) Error("GetParamProps failed.", hr);
1187
1188 _FillVariant((BYTE)dwCPlusFlags, pValue, cbValue, &defValue);
1189
1190 char sFlags[STRING_BUFFER_LEN];
1191 sFlags[0] = 0;
1192 ISFLAG(Pd, In);
1193 ISFLAG(Pd, Out);
1194 ISFLAG(Pd, Optional);
1195 // "Reserved" flags.
1196 ISFLAG(Pd, HasDefault);
1197 ISFLAG(Pd, HasFieldMarshal);
1198 if (!*sFlags)
1199 strcpy_s(sFlags,STRING_BUFFER_LEN, "[none]");
1200
1201 VWrite("\t\t\t(%ld) ParamToken : (%08x) Name : %ls flags: %s (%08x)", num, inParamDef, paramName, sFlags, flags);
1202#ifdef FEATURE_COMINTEROP
1203 if (IsPdHasDefault(flags))
1204 VWriteLine(" Default: (%s) %ls", g_szMapElementType[dwCPlusFlags], VariantAsString(&defValue));
1205 else
1206#endif
1207 VWriteLine("");
1208 DisplayCustomAttributes(inParamDef, "\t\t\t");
1209
1210#ifdef FEATURE_COMINTEROP
1211 ::VariantClear(&defValue);
1212#endif
1213} // void MDInfo::DisplayParamInfo()
1214
1215
1216// displays all parameters for a given memberdef
1217//
1218
1219void MDInfo::DisplayParams(mdMethodDef inMethodDef)
1220{
1221 HCORENUM paramEnum = NULL;
1222 mdParamDef params[ENUM_BUFFER_SIZE];
1223 ULONG count, paramCount;
1224 bool first = true;
1225 HRESULT hr;
1226
1227
1228 while (SUCCEEDED(hr = m_pImport->EnumParams( &paramEnum, inMethodDef,
1229 params, NumItems(params), &count)) &&
1230 count > 0)
1231 {
1232 if (first)
1233 {
1234 m_pImport->CountEnum( paramEnum, &paramCount);
1235 VWriteLine("\t\t%d Parameters", paramCount);
1236 }
1237 for (ULONG i = 0; i < count; i++)
1238 {
1239 DisplayParamInfo(params[i]);
1240 DisplayFieldMarshal(params[i]);
1241 }
1242 first = false;
1243 }
1244 m_pImport->CloseEnum( paramEnum);
1245} // void MDInfo::DisplayParams()
1246
1247void MDInfo::DisplayGenericParams(mdToken tk, const char *prefix)
1248{
1249 HCORENUM paramEnum = NULL;
1250 mdParamDef params[ENUM_BUFFER_SIZE];
1251 ULONG count, paramCount;
1252 bool first = true;
1253 HRESULT hr;
1254
1255
1256 while (SUCCEEDED(hr = m_pImport->EnumGenericParams( &paramEnum, tk,
1257 params, NumItems(params), &count)) &&
1258 count > 0)
1259 {
1260 if (first)
1261 {
1262 m_pImport->CountEnum( paramEnum, &paramCount);
1263 VWriteLine("%s%d Generic Parameters", prefix, paramCount);
1264 }
1265 for (ULONG i = 0; i < count; i++)
1266 {
1267 DisplayGenericParamInfo(params[i], prefix);
1268 }
1269 first = false;
1270 }
1271 m_pImport->CloseEnum( paramEnum);
1272}
1273
1274void MDInfo::DisplayGenericParamInfo(mdGenericParam tkParam, const char *prefix)
1275{
1276 ULONG ulSeq;
1277 WCHAR paramName[STRING_BUFFER_LEN];
1278 ULONG nameLen;
1279 DWORD flags;
1280 mdToken tkOwner;
1281 char newprefix[30];
1282 HCORENUM constraintEnum = NULL;
1283 mdParamDef constraints[4];
1284 ULONG count, constraintCount;
1285 mdToken constraint;
1286 mdToken owner;
1287 bool first = true;
1288
1289 HRESULT hr = m_pImport->GetGenericParamProps(tkParam, &ulSeq, &flags, &tkOwner, NULL, paramName, NumItems(paramName), &nameLen);
1290 if (FAILED(hr)) Error("GetGenericParamProps failed.", hr);
1291
1292 VWriteLine("%s\t(%ld) GenericParamToken : (%08x) Name : %ls flags: %08x Owner: %08x", prefix, ulSeq, tkParam, paramName, flags, tkOwner);
1293
1294 // Any constraints for the GenericParam
1295 while (SUCCEEDED(hr = m_pImport->EnumGenericParamConstraints(&constraintEnum, tkParam,
1296 constraints, NumItems(constraints), &count)) &&
1297 count > 0)
1298 {
1299 if (first)
1300 {
1301 m_pImport->CountEnum( constraintEnum, &constraintCount);
1302 VWriteLine("%s\t\t%d Constraint(s)", prefix, constraintCount);
1303 }
1304 VWrite("%s\t\t", prefix);
1305 for (ULONG i=0; i< count; ++i)
1306 {
1307 hr = m_pImport->GetGenericParamConstraintProps(constraints[i], &owner, &constraint);
1308 if (owner != tkParam)
1309 VWrite("%08x (owner: %08x) ", constraint, owner);
1310 else
1311 VWrite("%08x ", constraint);
1312 }
1313 VWriteLine("");
1314 }
1315 m_pImport->CloseEnum(constraintEnum);
1316
1317 sprintf_s(newprefix, 30, "%s\t", prefix);
1318 DisplayCustomAttributes(tkParam, newprefix);
1319}
1320
1321LPCWSTR MDInfo::TokenName(mdToken inToken, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen)
1322{
1323 LPCUTF8 pName; // Token name in UTF8.
1324
1325 if (IsNilToken(inToken))
1326 return W("");
1327
1328 m_pImport->GetNameFromToken(inToken, &pName);
1329
1330 WszMultiByteToWideChar(CP_UTF8,0, pName,-1, buffer,bufLen);
1331
1332 return buffer;
1333} // LPCWSTR MDInfo::TokenName()
1334
1335// prints out name of typeref or typedef
1336//
1337
1338LPCWSTR MDInfo::TypeDeforRefName(mdToken inToken, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen)
1339{
1340 if (RidFromToken(inToken))
1341 {
1342 if (TypeFromToken(inToken) == mdtTypeDef)
1343 return (TypeDefName((mdTypeDef) inToken, buffer, bufLen));
1344 else if (TypeFromToken(inToken) == mdtTypeRef)
1345 return (TypeRefName((mdTypeRef) inToken, buffer, bufLen));
1346 else if (TypeFromToken(inToken) == mdtTypeSpec)
1347 return W("[TypeSpec]");
1348 else
1349 return W("[InvalidReference]");
1350 }
1351 else
1352 return W("");
1353} // LPCWSTR MDInfo::TypeDeforRefName()
1354
1355LPCWSTR MDInfo::MemberDeforRefName(mdToken inToken, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen)
1356{
1357 if (RidFromToken(inToken))
1358 {
1359 if (TypeFromToken(inToken) == mdtMethodDef || TypeFromToken(inToken) == mdtFieldDef)
1360 return (MemberName(inToken, buffer, bufLen));
1361 else if (TypeFromToken(inToken) == mdtMemberRef)
1362 return (MemberRefName((mdMemberRef) inToken, buffer, bufLen));
1363 else
1364 return W("[InvalidReference]");
1365 }
1366 else
1367 return W("");
1368} // LPCWSTR MDInfo::MemberDeforRefName()
1369
1370// prints out only the name of the given typedef
1371//
1372//
1373
1374LPCWSTR MDInfo::TypeDefName(mdTypeDef inTypeDef, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen)
1375{
1376 HRESULT hr;
1377
1378 hr = m_pImport->GetTypeDefProps(
1379 // [IN] The import scope.
1380 inTypeDef, // [IN] TypeDef token for inquiry.
1381 buffer, // [OUT] Put name here.
1382 bufLen, // [IN] size of name buffer in wide chars.
1383 NULL, // [OUT] put size of name (wide chars) here.
1384 NULL, // [OUT] Put flags here.
1385 NULL); // [OUT] Put base class TypeDef/TypeRef here.
1386 if (FAILED(hr))
1387 {
1388 swprintf_s(buffer, bufLen, W("[Invalid TypeDef]"));
1389 }
1390
1391 return buffer;
1392} // LPCWSTR MDInfo::TypeDefName()
1393
1394// prints out all the properties of a given typedef
1395//
1396
1397void MDInfo::DisplayTypeDefProps(mdTypeDef inTypeDef)
1398{
1399 HRESULT hr;
1400 WCHAR typeDefName[STRING_BUFFER_LEN];
1401 ULONG nameLen;
1402 DWORD flags;
1403 mdToken extends;
1404 ULONG dwPacking; // Packing size of class, if specified.
1405 ULONG dwSize; // Total size of class, if specified.
1406
1407 hr = m_pImport->GetTypeDefProps(
1408 inTypeDef, // [IN] TypeDef token for inquiry.
1409 typeDefName, // [OUT] Put name here.
1410 STRING_BUFFER_LEN, // [IN] size of name buffer in wide chars.
1411 &nameLen, // [OUT] put size of name (wide chars) here.
1412 &flags, // [OUT] Put flags here.
1413 &extends); // [OUT] Put base class TypeDef/TypeRef here.
1414 if (FAILED(hr)) Error("GetTypeDefProps failed.", hr);
1415
1416 char sFlags[STRING_BUFFER_LEN];
1417 WCHAR szTempBuf[STRING_BUFFER_LEN];
1418
1419 VWriteLine("\tTypDefName: %ls (%8.8X)",typeDefName,inTypeDef);
1420 VWriteLine("\tFlags : %s (%08x)",ClassFlags(flags, sFlags), flags);
1421 VWriteLine("\tExtends : %8.8X [%s] %ls",extends,TokenTypeName(extends),
1422 TypeDeforRefName(extends, szTempBuf, NumItems(szTempBuf)));
1423
1424 hr = m_pImport->GetClassLayout(inTypeDef, &dwPacking, 0,0,0, &dwSize);
1425 if (hr == S_OK)
1426 VWriteLine("\tLayout : Packing:%d, Size:%d", dwPacking, dwSize);
1427
1428 if (IsTdNested(flags))
1429 {
1430 mdTypeDef tkEnclosingClass;
1431
1432 hr = m_pImport->GetNestedClassProps(inTypeDef, &tkEnclosingClass);
1433 if (hr == S_OK)
1434 {
1435 VWriteLine("\tEnclosingClass : %ls (%8.8X)", TypeDeforRefName(tkEnclosingClass,
1436 szTempBuf, NumItems(szTempBuf)), tkEnclosingClass);
1437 }
1438 else if (hr == CLDB_E_RECORD_NOTFOUND)
1439 WriteLine("ERROR: EnclosingClass not found for NestedClass");
1440 else
1441 Error("GetNestedClassProps failed.", hr);
1442 }
1443} // void MDInfo::DisplayTypeDefProps()
1444
1445// Prints out the name of the given TypeRef
1446//
1447
1448LPCWSTR MDInfo::TypeRefName(mdTypeRef tr, __out_ecount(bufLen) LPWSTR buffer, ULONG bufLen)
1449{
1450 HRESULT hr;
1451
1452 hr = m_pImport->GetTypeRefProps(
1453 tr, // The class ref token.
1454 NULL, // Resolution scope.
1455 buffer, // Put the name here.
1456 bufLen, // Size of the name buffer, wide chars.
1457 NULL); // Put actual size of name here.
1458 if (FAILED(hr))
1459 {
1460 swprintf_s(buffer, bufLen, W("[Invalid TypeRef]"));
1461 }
1462
1463 return (buffer);
1464} // LPCWSTR MDInfo::TypeRefName()
1465
1466// Prints out all the info of the given TypeRef
1467//
1468
1469void MDInfo::DisplayTypeRefInfo(mdTypeRef tr)
1470{
1471 HRESULT hr;
1472 mdToken tkResolutionScope;
1473 WCHAR typeRefName[STRING_BUFFER_LEN];
1474 ULONG nameLen;
1475
1476 hr = m_pImport->GetTypeRefProps(
1477 tr, // The class ref token.
1478 &tkResolutionScope, // ResolutionScope.
1479 typeRefName, // Put the name here.
1480 STRING_BUFFER_LEN, // Size of the name buffer, wide chars.
1481 &nameLen); // Put actual size of name here.
1482
1483 if (FAILED(hr)) Error("GetTypeRefProps failed.", hr);
1484
1485 VWriteLine("Token: 0x%08x", tr);
1486 VWriteLine("ResolutionScope: 0x%08x", tkResolutionScope);
1487 VWriteLine("TypeRefName: %ls",typeRefName);
1488
1489 DisplayCustomAttributes(tr, "\t");
1490} // void MDInfo::DisplayTypeRefInfo()
1491
1492
1493void MDInfo::DisplayTypeSpecInfo(mdTypeSpec ts, const char *preFix)
1494{
1495 HRESULT hr;
1496 PCCOR_SIGNATURE pvSig;
1497 ULONG cbSig;
1498 ULONG cb;
1499
1500 InitSigBuffer();
1501
1502 hr = m_pImport->GetTypeSpecFromToken(
1503 ts, // The class ref token.
1504 &pvSig,
1505 &cbSig);
1506
1507 if (FAILED(hr)) Error("GetTypeSpecFromToken failed.", hr);
1508
1509// DisplaySignature(pvSig, cbSig, preFix);
1510
1511 if (FAILED(hr = GetOneElementType(pvSig, cbSig, &cb)))
1512 goto ErrExit;
1513
1514 VWriteLine("%s\tTypeSpec :%s", preFix, (LPSTR)m_sigBuf.Ptr());
1515
1516 // Hex, too?
1517 if (m_DumpFilter & dumpMoreHex)
1518 {
1519 char rcNewPrefix[80];
1520 sprintf_s(rcNewPrefix, 80, "%s\tSignature", preFix);
1521 DumpHex(rcNewPrefix, pvSig, cbSig, false, 24);
1522 }
1523ErrExit:
1524 return;
1525} // void MDInfo::DisplayTypeSpecInfo()
1526
1527void MDInfo::DisplayMethodSpecInfo(mdMethodSpec ms, const char *preFix)
1528{
1529 HRESULT hr;
1530 PCCOR_SIGNATURE pvSig;
1531 ULONG cbSig;
1532 mdToken tk;
1533
1534 InitSigBuffer();
1535
1536 hr = m_pImport->GetMethodSpecProps(
1537 ms, // The MethodSpec token
1538 &tk, // The MethodDef or MemberRef
1539 &pvSig, // Signature.
1540 &cbSig); // Size of signature.
1541
1542 VWriteLine("%s\tParent : 0x%08x", preFix, tk);
1543 DisplaySignature(pvSig, cbSig, preFix);
1544//ErrExit:
1545 return;
1546} // void MDInfo::DisplayMethodSpecInfo()
1547
1548// Return the passed-in buffer filled with a string detailing the class flags
1549// associated with the class.
1550//
1551
1552char *MDInfo::ClassFlags(DWORD flags, __out_ecount(STRING_BUFFER_LEN) char *sFlags)
1553{
1554 sFlags[0] = 0;
1555 ISFLAG(Td, NotPublic);
1556 ISFLAG(Td, Public);
1557 ISFLAG(Td, NestedPublic);
1558 ISFLAG(Td, NestedPrivate);
1559 ISFLAG(Td, NestedFamily);
1560 ISFLAG(Td, NestedAssembly);
1561 ISFLAG(Td, NestedFamANDAssem);
1562 ISFLAG(Td, NestedFamORAssem);
1563 ISFLAG(Td, AutoLayout);
1564 ISFLAG(Td, SequentialLayout);
1565 ISFLAG(Td, ExplicitLayout);
1566 ISFLAG(Td, Class);
1567 ISFLAG(Td, Interface);
1568 ISFLAG(Td, Abstract);
1569 ISFLAG(Td, Sealed);
1570 ISFLAG(Td, SpecialName);
1571 ISFLAG(Td, Import);
1572 ISFLAG(Td, Serializable);
1573 ISFLAG(Td, AnsiClass);
1574 ISFLAG(Td, UnicodeClass);
1575 ISFLAG(Td, AutoClass);
1576 ISFLAG(Td, BeforeFieldInit);
1577 ISFLAG(Td, Forwarder);
1578 // "Reserved" flags
1579 ISFLAG(Td, RTSpecialName);
1580 ISFLAG(Td, HasSecurity);
1581 ISFLAG(Td, WindowsRuntime);
1582 if (!*sFlags)
1583 strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
1584
1585 return sFlags;
1586} // char *MDInfo::ClassFlags()
1587
1588// prints out all info on the given typeDef, including all information that
1589// is specific to a given typedef
1590//
1591
1592void MDInfo::DisplayTypeDefInfo(mdTypeDef inTypeDef)
1593{
1594 DisplayTypeDefProps(inTypeDef);
1595
1596 // Get field layout information.
1597 HRESULT hr = NOERROR;
1598 COR_FIELD_OFFSET *rFieldOffset = NULL;
1599 ULONG cFieldOffset = 0;
1600 hr = m_pImport->GetClassLayout(inTypeDef, NULL, rFieldOffset, 0, &cFieldOffset, NULL);
1601 if (SUCCEEDED(hr) && cFieldOffset)
1602 {
1603 rFieldOffset = new COR_FIELD_OFFSET[cFieldOffset];
1604 if (rFieldOffset == NULL)
1605 Error("_calloc failed.", E_OUTOFMEMORY);
1606 hr = m_pImport->GetClassLayout(inTypeDef, NULL, rFieldOffset, cFieldOffset, &cFieldOffset, NULL);
1607 if (FAILED(hr)) { delete [] rFieldOffset; Error("GetClassLayout() failed.", hr); }
1608 }
1609
1610 //No reason to display members if we're displaying fields and methods separately
1611 DisplayGenericParams(inTypeDef, "\t");
1612 DisplayFields(inTypeDef, rFieldOffset, cFieldOffset);
1613 delete [] rFieldOffset;
1614 DisplayMethods(inTypeDef);
1615 DisplayProperties(inTypeDef);
1616 DisplayEvents(inTypeDef);
1617 DisplayMethodImpls(inTypeDef);
1618 DisplayPermissions(inTypeDef, "");
1619
1620 DisplayInterfaceImpls(inTypeDef);
1621 DisplayCustomAttributes(inTypeDef, "\t");
1622} // void MDInfo::DisplayTypeDefInfo()
1623
1624// print out information about every the given typeDef's interfaceImpls
1625//
1626
1627void MDInfo::DisplayInterfaceImpls(mdTypeDef inTypeDef)
1628{
1629 HCORENUM interfaceImplEnum = NULL;
1630 mdTypeRef interfaceImpls[ENUM_BUFFER_SIZE];
1631 ULONG count, totalCount = 1;
1632 HRESULT hr;
1633
1634 while(SUCCEEDED(hr = m_pImport->EnumInterfaceImpls( &interfaceImplEnum,
1635 inTypeDef,interfaceImpls,NumItems(interfaceImpls), &count)) &&
1636 count > 0)
1637 {
1638 for (ULONG i = 0; i < count; i++, totalCount++)
1639 {
1640 VWriteLine("\tInterfaceImpl #%d (%08x)", totalCount, interfaceImpls[i]);
1641 WriteLine("\t-------------------------------------------------------");
1642 DisplayInterfaceImplInfo(interfaceImpls[i]);
1643 DisplayPermissions(interfaceImpls[i], "\t");
1644 WriteLine("");
1645 }
1646 }
1647 m_pImport->CloseEnum( interfaceImplEnum);
1648} // void MDInfo::DisplayInterfaceImpls()
1649
1650// print the information for the given interface implementation
1651//
1652
1653void MDInfo::DisplayInterfaceImplInfo(mdInterfaceImpl inImpl)
1654{
1655 mdTypeDef typeDef;
1656 mdToken token;
1657 HRESULT hr;
1658
1659 WCHAR szTempBuf[STRING_BUFFER_LEN];
1660
1661 hr = m_pImport->GetInterfaceImplProps( inImpl, &typeDef, &token);
1662 if (FAILED(hr)) Error("GetInterfaceImplProps failed.", hr);
1663
1664 VWriteLine("\t\tClass : %ls",TypeDeforRefName(typeDef, szTempBuf, NumItems(szTempBuf)));
1665 VWriteLine("\t\tToken : %8.8X [%s] %ls",token,TokenTypeName(token), TypeDeforRefName(token, szTempBuf, NumItems(szTempBuf)));
1666
1667 DisplayCustomAttributes(inImpl, "\t\t");
1668} // void MDInfo::DisplayInterfaceImplInfo()
1669
1670// displays the information for a particular property
1671//
1672
1673void MDInfo::DisplayPropertyInfo(mdProperty inProp)
1674{
1675 HRESULT hr;
1676 mdTypeDef typeDef;
1677 WCHAR propName[STRING_BUFFER_LEN];
1678 DWORD flags;
1679#ifdef FEATURE_COMINTEROP
1680 VARIANT defaultValue;
1681#endif
1682 void const *pValue;
1683 ULONG cbValue;
1684 DWORD dwCPlusTypeFlag;
1685 mdMethodDef setter, getter, otherMethod[ENUM_BUFFER_SIZE];
1686 ULONG others;
1687 PCCOR_SIGNATURE pbSigBlob;
1688 ULONG ulSigBlob;
1689
1690
1691#ifdef FEATURE_COMINTEROP
1692 ::VariantInit(&defaultValue);
1693#endif
1694 hr = m_pImport->GetPropertyProps(
1695 inProp, // [IN] property token
1696 &typeDef, // [OUT] typedef containing the property declarion.
1697
1698 propName, // [OUT] Property name
1699 STRING_BUFFER_LEN, // [IN] the count of wchar of szProperty
1700 NULL, // [OUT] actual count of wchar for property name
1701
1702 &flags, // [OUT] property flags.
1703
1704 &pbSigBlob, // [OUT] Signature Blob.
1705 &ulSigBlob, // [OUT] Number of bytes in the signature blob.
1706
1707 &dwCPlusTypeFlag, // [OUT] default value
1708 &pValue,
1709 &cbValue,
1710
1711 &setter, // [OUT] setter method of the property
1712 &getter, // [OUT] getter method of the property
1713
1714 otherMethod, // [OUT] other methods of the property
1715 ENUM_BUFFER_SIZE, // [IN] size of rmdOtherMethod
1716 &others); // [OUT] total number of other method of this property
1717
1718 if (FAILED(hr)) Error("GetPropertyProps failed.", hr);
1719
1720 VWriteLine("\t\tProp.Name : %ls (%8.8X)",propName,inProp);
1721
1722 char sFlags[STRING_BUFFER_LEN];
1723
1724 sFlags[0] = 0;
1725 ISFLAG(Pr, SpecialName);
1726 ISFLAG(Pr, RTSpecialName);
1727 ISFLAG(Pr, HasDefault);
1728 if (!*sFlags)
1729 strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
1730
1731 VWriteLine("\t\tFlags : %s (%08x)", sFlags, flags);
1732
1733 if (ulSigBlob)
1734 DisplaySignature(pbSigBlob, ulSigBlob, "");
1735 else
1736 VWriteLine("\t\tERROR: no valid signature ");
1737
1738 WCHAR szTempBuf[STRING_BUFFER_LEN];
1739
1740#ifdef FEATURE_COMINTEROP
1741 _FillVariant((BYTE)dwCPlusTypeFlag, pValue, cbValue, &defaultValue);
1742 VWriteLine("\t\tDefltValue: %ls",VariantAsString(&defaultValue));
1743#endif
1744
1745 VWriteLine("\t\tSetter : (%08x) %ls",setter,MemberDeforRefName(setter, szTempBuf, NumItems(szTempBuf)));
1746 VWriteLine("\t\tGetter : (%08x) %ls",getter,MemberDeforRefName(getter, szTempBuf, NumItems(szTempBuf)));
1747
1748 // do something with others?
1749 VWriteLine("\t\t%ld Others",others);
1750 DisplayCustomAttributes(inProp, "\t\t");
1751
1752#ifdef FEATURE_COMINTEROP
1753 ::VariantClear(&defaultValue);
1754#endif
1755} // void MDInfo::DisplayPropertyInfo()
1756
1757// displays info for each property
1758//
1759
1760void MDInfo::DisplayProperties(mdTypeDef inTypeDef)
1761{
1762 HCORENUM propEnum = NULL;
1763 mdProperty props[ENUM_BUFFER_SIZE];
1764 ULONG count, totalCount = 1;
1765 HRESULT hr;
1766
1767
1768 while(SUCCEEDED(hr = m_pImport->EnumProperties( &propEnum,
1769 inTypeDef,props,NumItems(props), &count)) &&
1770 count > 0)
1771 {
1772 for (ULONG i = 0; i < count; i++, totalCount++)
1773 {
1774 VWriteLine("\tProperty #%d (%08x)", totalCount, props[i]);
1775 WriteLine("\t-------------------------------------------------------");
1776 DisplayPropertyInfo(props[i]);
1777 DisplayPermissions(props[i], "\t");
1778 WriteLine("");
1779 }
1780 }
1781 m_pImport->CloseEnum( propEnum);
1782} // void MDInfo::DisplayProperties()
1783
1784// Display all information about a particular event
1785//
1786
1787void MDInfo::DisplayEventInfo(mdEvent inEvent)
1788{
1789 HRESULT hr;
1790 mdTypeDef typeDef;
1791 WCHAR eventName[STRING_BUFFER_LEN];
1792 DWORD flags;
1793 mdToken eventType;
1794 mdMethodDef addOn, removeOn, fire, otherMethod[ENUM_BUFFER_SIZE];
1795 ULONG totalOther;
1796
1797
1798 hr = m_pImport->GetEventProps(
1799 // [IN] The scope.
1800 inEvent, // [IN] event token
1801 &typeDef, // [OUT] typedef containing the event declarion.
1802
1803 eventName, // [OUT] Event name
1804 STRING_BUFFER_LEN, // [IN] the count of wchar of szEvent
1805 NULL, // [OUT] actual count of wchar for event's name
1806
1807 &flags, // [OUT] Event flags.
1808 &eventType, // [OUT] EventType class
1809
1810 &addOn, // [OUT] AddOn method of the event
1811 &removeOn, // [OUT] RemoveOn method of the event
1812 &fire, // [OUT] Fire method of the event
1813
1814 otherMethod, // [OUT] other method of the event
1815 NumItems(otherMethod), // [IN] size of rmdOtherMethod
1816 &totalOther); // [OUT] total number of other method of this event
1817 if (FAILED(hr)) Error("GetEventProps failed.", hr);
1818
1819 VWriteLine("\t\tName : %ls (%8.8X)",eventName,inEvent);
1820
1821 char sFlags[STRING_BUFFER_LEN];
1822
1823 sFlags[0] = 0;
1824 ISFLAG(Ev, SpecialName);
1825 ISFLAG(Ev, RTSpecialName);
1826 if (!*sFlags)
1827 strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
1828
1829 VWriteLine("\t\tFlags : %s (%08x)", sFlags, flags);
1830
1831 WCHAR szTempBuf[STRING_BUFFER_LEN];
1832
1833 VWriteLine("\t\tEventType : %8.8X [%s]",eventType,TokenTypeName(eventType));
1834 VWriteLine("\t\tAddOnMethd: (%08x) %ls",addOn,MemberDeforRefName(addOn, szTempBuf, NumItems(szTempBuf)));
1835 VWriteLine("\t\tRmvOnMethd: (%08x) %ls",removeOn,MemberDeforRefName(removeOn, szTempBuf, NumItems(szTempBuf)));
1836 VWriteLine("\t\tFireMethod: (%08x) %ls",fire,MemberDeforRefName(fire, szTempBuf, NumItems(szTempBuf)));
1837
1838 VWriteLine("\t\t%ld OtherMethods",totalOther);
1839
1840 DisplayCustomAttributes(inEvent, "\t\t");
1841} // void MDInfo::DisplayEventInfo()
1842
1843// Display information about all events in a typedef
1844//
1845void MDInfo::DisplayEvents(mdTypeDef inTypeDef)
1846{
1847 HCORENUM eventEnum = NULL;
1848 mdProperty events[ENUM_BUFFER_SIZE];
1849 ULONG count, totalCount = 1;
1850 HRESULT hr;
1851
1852
1853 while(SUCCEEDED(hr = m_pImport->EnumEvents( &eventEnum,
1854 inTypeDef,events,NumItems(events), &count)) &&
1855 count > 0)
1856 {
1857 for (ULONG i = 0; i < count; i++, totalCount++)
1858 {
1859 VWriteLine("\tEvent #%d (%08x)", totalCount, events[i]);
1860 WriteLine("\t-------------------------------------------------------");
1861 DisplayEventInfo(events[i]);
1862 DisplayPermissions(events[i], "\t");
1863 WriteLine("");
1864 }
1865 }
1866 m_pImport->CloseEnum( eventEnum);
1867} // void MDInfo::DisplayEvents()
1868
1869
1870// print info for the passed-in custom attribute
1871// This function is used to print the custom attribute information for both TypeDefs and
1872// MethodDefs which need slightly different formatting. preFix helps fix it up.
1873//
1874
1875void MDInfo::DisplayCustomAttributeInfo(mdCustomAttribute inValue, const char *preFix)
1876{
1877 const BYTE *pValue; // The custom value.
1878 ULONG cbValue; // Length of the custom value.
1879 HRESULT hr; // A result.
1880 mdToken tkObj; // Attributed object.
1881 mdToken tkType; // Type of the custom attribute.
1882 mdToken tk; // For name lookup.
1883 LPCUTF8 pMethName=0; // Name of custom attribute ctor, if any.
1884 CQuickBytes qSigName; // Buffer to pretty-print signature.
1885 PCCOR_SIGNATURE pSig=0; // Signature of ctor.
1886 ULONG cbSig; // Size of the signature.
1887 BOOL bCoffSymbol = false; // true for coff symbol CA's.
1888 WCHAR rcName[MAX_CLASS_NAME]; // Name of the type.
1889
1890 hr = m_pImport->GetCustomAttributeProps( // S_OK or error.
1891 inValue, // The attribute.
1892 &tkObj, // The attributed object
1893 &tkType, // The attributes type.
1894 (const void**)&pValue, // Put pointer to data here.
1895 &cbValue); // Put size here.
1896 if (FAILED(hr)) Error("GetCustomAttributeProps failed.", hr);
1897
1898 VWriteLine("%s\tCustomAttribute Type: %08x", preFix, tkType);
1899
1900 // Get the name of the memberref or methoddef.
1901 tk = tkType;
1902 rcName[0] = L'\0';
1903 // Get the member name, and the parent token.
1904 switch (TypeFromToken(tk))
1905 {
1906 case mdtMemberRef:
1907 hr = m_pImport->GetNameFromToken(tk, &pMethName);
1908 if (FAILED(hr)) Error("GetNameFromToken failed.", hr);
1909 hr = m_pImport->GetMemberRefProps( tk, &tk, 0, 0, 0, &pSig, &cbSig);
1910 if (FAILED(hr)) Error("GetMemberRefProps failed.", hr);
1911 break;
1912 case mdtMethodDef:
1913 hr = m_pImport->GetNameFromToken(tk, &pMethName);
1914 if (FAILED(hr)) Error("GetNameFromToken failed.", hr);
1915 hr = m_pImport->GetMethodProps(tk, &tk, 0, 0, 0, 0, &pSig, &cbSig, 0, 0);
1916 if (FAILED(hr)) Error("GetMethodProps failed.", hr);
1917 break;
1918 } // switch
1919
1920 // Get the type name.
1921 switch (TypeFromToken(tk))
1922 {
1923 case mdtTypeDef:
1924 hr = m_pImport->GetTypeDefProps(tk, rcName,MAX_CLASS_NAME,0, 0,0);
1925 if (FAILED(hr)) Error("GetTypeDefProps failed.", hr);
1926 break;
1927 case mdtTypeRef:
1928 hr = m_pImport->GetTypeRefProps(tk, 0, rcName,MAX_CLASS_NAME,0);
1929 if (FAILED(hr)) Error("GetTypeRefProps failed.", hr);
1930 break;
1931 } // switch
1932
1933
1934 if (pSig && pMethName)
1935 {
1936 int iLen;
1937 LPWSTR pwzName = (LPWSTR)(new WCHAR[iLen= 1+(ULONG32)strlen(pMethName)]);
1938 if(pwzName)
1939 {
1940 WszMultiByteToWideChar(CP_UTF8,0, pMethName,-1, pwzName,iLen);
1941 PrettyPrintSigLegacy(pSig, cbSig, pwzName, &qSigName, m_pImport);
1942 delete [] pwzName;
1943 }
1944 }
1945
1946 VWrite("%s\tCustomAttributeName: %ls", preFix, rcName);
1947 if (pSig && pMethName)
1948 VWrite(" :: %S", qSigName.Ptr());
1949
1950 // Keep track of coff overhead.
1951 if (!wcscmp(W("__DecoratedName"), rcName))
1952 {
1953 bCoffSymbol = true;
1954 g_cbCoffNames += cbValue + 6;
1955 }
1956 WriteLine("");
1957
1958 VWriteLine("%s\tLength: %ld", preFix, cbValue);
1959 char newPreFix[40];
1960 sprintf_s(newPreFix, 40, "%s\tValue ", preFix);
1961 DumpHex(newPreFix, pValue, cbValue);
1962 if (bCoffSymbol)
1963 VWriteLine("%s\t %s", preFix, pValue);
1964
1965 // Try to decode the constructor blob. This is incomplete, but covers the most popular cases.
1966 if (pSig)
1967 { // Interpret the signature.
1968 PCCOR_SIGNATURE ps = pSig;
1969 ULONG cb;
1970 ULONG ulData;
1971 ULONG cParams;
1972 ULONG ulVal;
1973 UINT8 u1 = 0;
1974 UINT16 u2 = 0;
1975 UINT32 u4 = 0;
1976 UINT64 u8 = 0;
1977 unsigned __int64 uI64;
1978 double dblVal;
1979 ULONG cbVal;
1980 LPCUTF8 pStr;
1981 CustomAttributeParser CA(pValue, cbValue);
1982 CA.ValidateProlog();
1983
1984 // Get the calling convention.
1985 cb = CorSigUncompressData(ps, &ulData);
1986 ps += cb;
1987 // Get the count of params.
1988 cb = CorSigUncompressData(ps, &cParams);
1989 ps += cb;
1990 // Get the return value.
1991 cb = CorSigUncompressData(ps, &ulData);
1992 ps += cb;
1993 if (ulData == ELEMENT_TYPE_VOID)
1994 {
1995 VWrite("%s\tctor args: (", preFix);
1996 // For each param...
1997 for (ULONG i=0; i<cParams; ++i)
1998 { // Get the next param type.
1999 cb = CorSigUncompressData(ps, &ulData);
2000 ps += cb;
2001 if (i) Write(", ");
2002 DoObject:
2003 switch (ulData)
2004 {
2005 // For ET_OBJECT, the next byte in the blob is the ET of the actual data.
2006 case ELEMENT_TYPE_OBJECT:
2007 CA.GetU1(&u1);
2008 ulData = u1;
2009 goto DoObject;
2010 case ELEMENT_TYPE_I1:
2011 case ELEMENT_TYPE_U1:
2012 CA.GetU1(&u1);
2013 ulVal = u1;
2014 goto PrintVal;
2015 case ELEMENT_TYPE_I2:
2016 case ELEMENT_TYPE_U2:
2017 CA.GetU2(&u2);
2018 ulVal = u2;
2019 goto PrintVal;
2020 case ELEMENT_TYPE_I4:
2021 case ELEMENT_TYPE_U4:
2022 CA.GetU4(&u4);
2023 ulVal = u4;
2024 PrintVal:
2025 VWrite("%d", ulVal);
2026 break;
2027 case ELEMENT_TYPE_STRING:
2028 CA.GetString(&pStr, &cbVal);
2029 VWrite("\"%s\"", pStr);
2030 break;
2031 // The only class type that we accept is Type, which is stored as a string.
2032 case ELEMENT_TYPE_CLASS:
2033 // Eat the class type.
2034 cb = CorSigUncompressData(ps, &ulData);
2035 ps += cb;
2036 // Get the name of the type.
2037 CA.GetString(&pStr, &cbVal);
2038 VWrite("typeof(%s)", pStr);
2039 break;
2040 case SERIALIZATION_TYPE_TYPE:
2041 CA.GetString(&pStr, &cbVal);
2042 VWrite("typeof(%s)", pStr);
2043 break;
2044 case ELEMENT_TYPE_I8:
2045 case ELEMENT_TYPE_U8:
2046 CA.GetU8(&u8);
2047 uI64 = u8;
2048 VWrite("%#lx", uI64);
2049 break;
2050 case ELEMENT_TYPE_R4:
2051 dblVal = CA.GetR4();
2052 VWrite("%f", dblVal);
2053 break;
2054 case ELEMENT_TYPE_R8:
2055 dblVal = CA.GetR8();
2056 VWrite("%f", dblVal);
2057 break;
2058 default:
2059 // bail...
2060 i = cParams;
2061 Write(" <can not decode> ");
2062 break;
2063 }
2064 }
2065 WriteLine(")");
2066 }
2067
2068 }
2069 WriteLine("");
2070} // void MDInfo::DisplayCustomAttributeInfo()
2071
2072// Print all custom values for the given token
2073// This function is used to print the custom value information for all tokens.
2074// which need slightly different formatting. preFix helps fix it up.
2075//
2076
2077void MDInfo::DisplayCustomAttributes(mdToken inToken, const char *preFix)
2078{
2079 HCORENUM customAttributeEnum = NULL;
2080 mdTypeRef customAttributes[ENUM_BUFFER_SIZE];
2081 ULONG count, totalCount = 1;
2082 HRESULT hr;
2083
2084 while(SUCCEEDED(hr = m_pImport->EnumCustomAttributes( &customAttributeEnum, inToken, 0,
2085 customAttributes, NumItems(customAttributes), &count)) &&
2086 count > 0)
2087 {
2088 for (ULONG i = 0; i < count; i++, totalCount++)
2089 {
2090 VWriteLine("%sCustomAttribute #%d (%08x)", preFix, totalCount, customAttributes[i]);
2091 VWriteLine("%s-------------------------------------------------------", preFix);
2092 DisplayCustomAttributeInfo(customAttributes[i], preFix);
2093 }
2094 }
2095 m_pImport->CloseEnum( customAttributeEnum);
2096} // void MDInfo::DisplayCustomAttributes()
2097
2098// Show the passed-in token's permissions
2099//
2100//
2101
2102void MDInfo::DisplayPermissions(mdToken tk, const char *preFix)
2103{
2104 HCORENUM permissionEnum = NULL;
2105 mdPermission permissions[ENUM_BUFFER_SIZE];
2106 ULONG count, totalCount = 1;
2107 HRESULT hr;
2108
2109
2110 while (SUCCEEDED(hr = m_pImport->EnumPermissionSets( &permissionEnum,
2111 tk, 0, permissions, NumItems(permissions), &count)) &&
2112 count > 0)
2113 {
2114 for (ULONG i = 0; i < count; i++, totalCount++)
2115 {
2116 VWriteLine("%s\tPermission #%d (%08x)", preFix, totalCount, permissions[i]);
2117 VWriteLine("%s\t-------------------------------------------------------", preFix);
2118 DisplayPermissionInfo(permissions[i], preFix);
2119 WriteLine("");
2120 }
2121 }
2122 m_pImport->CloseEnum( permissionEnum);
2123} // void MDInfo::DisplayPermissions()
2124
2125// print properties of given rolecheck
2126//
2127//
2128
2129void MDInfo::DisplayPermissionInfo(mdPermission inPermission, const char *preFix)
2130{
2131 DWORD dwAction;
2132 const BYTE *pvPermission;
2133 ULONG cbPermission;
2134 const char *flagDesc = NULL;
2135 char newPreFix[STRING_BUFFER_LEN];
2136 HRESULT hr;
2137
2138
2139 hr = m_pImport->GetPermissionSetProps( inPermission, &dwAction,
2140 (const void**)&pvPermission, &cbPermission);
2141 if (FAILED(hr)) Error("GetPermissionSetProps failed.", hr);
2142
2143 switch(dwAction)
2144 {
2145 case dclActionNil: flagDesc = "ActionNil"; break;
2146 case dclRequest: flagDesc = "Request"; break;
2147 case dclDemand: flagDesc = "Demand"; break;
2148 case dclAssert: flagDesc = "Assert"; break;
2149 case dclDeny: flagDesc = "Deny"; break;
2150 case dclPermitOnly: flagDesc = "PermitOnly"; break;
2151 case dclLinktimeCheck: flagDesc = "LinktimeCheck"; break;
2152 case dclInheritanceCheck: flagDesc = "InheritanceCheck"; break;
2153 case dclRequestMinimum: flagDesc = "RequestMinimum"; break;
2154 case dclRequestOptional: flagDesc = "RequestOptional"; break;
2155 case dclRequestRefuse: flagDesc = "RequestRefuse"; break;
2156 case dclPrejitGrant: flagDesc = "PrejitGrant"; break;
2157 case dclPrejitDenied: flagDesc = "PrejitDenied"; break;
2158 case dclNonCasDemand: flagDesc = "NonCasDemand"; break;
2159 case dclNonCasLinkDemand: flagDesc = "NonCasLinkDemand"; break;
2160 case dclNonCasInheritance: flagDesc = "NonCasInheritance"; break;
2161
2162 }
2163 VWriteLine("%s\t\tAction : %s", preFix, flagDesc);
2164 VWriteLine("%s\t\tBlobLen : %d", preFix, cbPermission);
2165 if (cbPermission)
2166 {
2167 sprintf_s(newPreFix, STRING_BUFFER_LEN, "%s\tBlob", preFix);
2168 DumpHex(newPreFix, pvPermission, cbPermission, false, 24);
2169 }
2170
2171 sprintf_s (newPreFix, STRING_BUFFER_LEN, "\t\t%s", preFix);
2172 DisplayCustomAttributes(inPermission, newPreFix);
2173} // void MDInfo::DisplayPermissionInfo()
2174
2175
2176// simply prints out the given GUID in standard form
2177
2178LPWSTR MDInfo::GUIDAsString(GUID inGuid, __out_ecount(bufLen) LPWSTR guidString, ULONG bufLen)
2179{
2180 StringFromGUID2(inGuid, guidString, bufLen);
2181 return guidString;
2182} // LPWSTR MDInfo::GUIDAsString()
2183
2184#ifdef FEATURE_COMINTEROP
2185LPCWSTR MDInfo::VariantAsString(VARIANT *pVariant)
2186{
2187 HRESULT hr = S_OK;
2188 if (V_VT(pVariant) == VT_UNKNOWN)
2189 {
2190 _ASSERTE(V_UNKNOWN(pVariant) == NULL);
2191 return W("<NULL>");
2192 }
2193 else if (SUCCEEDED(hr = ::VariantChangeType(pVariant, pVariant, 0, VT_BSTR)))
2194 return V_BSTR(pVariant);
2195 else if (hr == DISP_E_BADVARTYPE && V_VT(pVariant) == VT_I8)
2196 {
2197 // allocate the bstr.
2198 char szStr[32];
2199 WCHAR wszStr[32];
2200 // Set variant type to bstr.
2201 V_VT(pVariant) = VT_BSTR;
2202 // Create the ansi string.
2203 sprintf_s(szStr, 32, "%I64d", V_CY(pVariant).int64);
2204 // Convert to unicode.
2205 WszMultiByteToWideChar(CP_ACP, 0, szStr, -1, wszStr, 32);
2206 // convert to bstr and set variant value.
2207 V_BSTR(pVariant) = ::SysAllocString(wszStr);
2208 if (V_BSTR(pVariant) == NULL)
2209 Error("SysAllocString() failed.", E_OUTOFMEMORY);
2210 return V_BSTR(pVariant);
2211 }
2212 else
2213 return W("ERROR");
2214
2215} // LPWSTR MDInfo::VariantAsString()
2216#endif
2217
2218bool TrySigUncompress(PCCOR_SIGNATURE pData, // [IN] compressed data
2219 ULONG *pDataOut, // [OUT] the expanded *pData
2220 ULONG *cbCur)
2221{
2222 ULONG ulSize = CorSigUncompressData(pData, pDataOut);
2223 if (ulSize == (ULONG)-1)
2224 {
2225 *cbCur = ulSize;
2226 return false;
2227 } else
2228 {
2229 *cbCur += ulSize;
2230 return true;
2231 }
2232}
2233
2234void MDInfo::DisplayFieldMarshal(mdToken inToken)
2235{
2236 PCCOR_SIGNATURE pvNativeType; // [OUT] native type of this field
2237 ULONG cbNativeType; // [OUT] the count of bytes of *ppvNativeType
2238 HRESULT hr;
2239
2240
2241 hr = m_pImport->GetFieldMarshal( inToken, &pvNativeType, &cbNativeType);
2242 if (FAILED(hr) && hr != CLDB_E_RECORD_NOTFOUND) Error("GetFieldMarshal failed.", hr);
2243 if (hr != CLDB_E_RECORD_NOTFOUND)
2244 {
2245 ULONG cbCur = 0;
2246 ULONG ulData;
2247 ULONG ulStrLoc;
2248
2249 char szNTDesc[STRING_BUFFER_LEN];
2250
2251 while (cbCur < cbNativeType)
2252 {
2253 ulStrLoc = 0;
2254
2255 ulData = NATIVE_TYPE_MAX;
2256 if (!TrySigUncompress(&pvNativeType[cbCur], &ulData, &cbCur))
2257 continue;
2258 if (ulData >= sizeof(g_szNativeType)/sizeof(*g_szNativeType))
2259 {
2260 cbCur = (ULONG)-1;
2261 continue;
2262 }
2263 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "%s ", g_szNativeType[ulData]);
2264 switch (ulData)
2265 {
2266 case NATIVE_TYPE_FIXEDSYSSTRING:
2267 {
2268 if (cbCur < cbNativeType)
2269 {
2270 if (!TrySigUncompress(&pvNativeType[cbCur], &ulData, &cbCur))
2271 continue;
2272 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "{StringElementCount: %d} ",ulData);
2273 }
2274 }
2275 break;
2276 case NATIVE_TYPE_FIXEDARRAY:
2277 {
2278 if (cbCur < cbNativeType)
2279 {
2280 if (!TrySigUncompress(&pvNativeType[cbCur], &ulData, &cbCur))
2281 continue;
2282 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "{ArrayElementCount: %d",ulData);
2283
2284 if (cbCur < cbNativeType)
2285 {
2286 if (!TrySigUncompress(&pvNativeType[cbCur], &ulData, &cbCur))
2287 continue;
2288 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, ", ArrayElementType(NT): %d",ulData);
2289 }
2290
2291 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc,"}");
2292 }
2293 }
2294 break;
2295 case NATIVE_TYPE_ARRAY:
2296 {
2297 if (cbCur < cbNativeType)
2298 {
2299 BOOL bElemTypeSpecified;
2300
2301 if (!TrySigUncompress(&pvNativeType[cbCur], &ulData, &cbCur))
2302 continue;
2303 if (ulData != NATIVE_TYPE_MAX)
2304 {
2305 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "{ArrayElementType(NT): %d", ulData);
2306 bElemTypeSpecified = TRUE;
2307 }
2308 else
2309 {
2310 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "{");
2311 bElemTypeSpecified = FALSE;
2312 }
2313
2314 if (cbCur < cbNativeType)
2315 {
2316 if (bElemTypeSpecified)
2317 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, ", ");
2318
2319 if (!TrySigUncompress(&pvNativeType[cbCur], &ulData, &cbCur))
2320 continue;
2321 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "SizeParamIndex: %d",ulData);
2322
2323 if (cbCur < cbNativeType)
2324 {
2325 if (!TrySigUncompress(&pvNativeType[cbCur], &ulData, &cbCur))
2326 continue;
2327 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, ", SizeParamMultiplier: %d",ulData);
2328
2329 if (cbCur < cbNativeType)
2330 {
2331 if (!TrySigUncompress(&pvNativeType[cbCur], &ulData, &cbCur))
2332 continue;
2333 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, ", SizeConst: %d",ulData);
2334 }
2335 }
2336 }
2337
2338 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "}");
2339 }
2340 }
2341 break;
2342 case NATIVE_TYPE_SAFEARRAY:
2343 {
2344 if (cbCur < cbNativeType)
2345 {
2346 if (!TrySigUncompress(&pvNativeType[cbCur], &ulData, &cbCur))
2347 continue;
2348 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "{SafeArraySubType(VT): %d, ",ulData);
2349
2350 // Extract the element type name if it is specified.
2351 if (cbCur < cbNativeType)
2352 {
2353 LPUTF8 strTemp = NULL;
2354 int strLen = 0;
2355 int ByteCountLength = 0;
2356
2357 strLen = CPackedLen::GetLength(&pvNativeType[cbCur], &ByteCountLength);
2358 cbCur += ByteCountLength;
2359 strTemp = (LPUTF8)(new char[strLen + 1]);
2360 if(strTemp)
2361 {
2362 memcpy(strTemp, (LPUTF8)&pvNativeType[cbCur], strLen);
2363 strTemp[strLen] = 0;
2364 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "ElementTypeName: %s}", strTemp);
2365 cbCur += strLen;
2366 _ASSERTE(cbCur == cbNativeType);
2367 delete [] strTemp;
2368 }
2369 }
2370 else
2371 {
2372 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "ElementTypeName: }");
2373 }
2374 }
2375 }
2376 break;
2377 case NATIVE_TYPE_CUSTOMMARSHALER:
2378 {
2379 LPUTF8 strTemp = NULL;
2380 int strLen = 0;
2381 int ByteCountLength = 0;
2382
2383 // Extract the typelib GUID.
2384 strLen = CPackedLen::GetLength(&pvNativeType[cbCur], &ByteCountLength);
2385 cbCur += ByteCountLength;
2386 strTemp = (LPUTF8)(new char[strLen + 1]);
2387 if(strTemp)
2388 {
2389 memcpy(strTemp, (LPUTF8)&pvNativeType[cbCur], strLen);
2390 strTemp[strLen] = 0;
2391 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "{Typelib: %s, ", strTemp);
2392 cbCur += strLen;
2393 _ASSERTE(cbCur < cbNativeType);
2394 delete [] strTemp;
2395 }
2396 // Extract the name of the native type.
2397 strLen = CPackedLen::GetLength(&pvNativeType[cbCur], &ByteCountLength);
2398 cbCur += ByteCountLength;
2399 strTemp = (LPUTF8)(new char[strLen + 1]);
2400 if(strTemp)
2401 {
2402 memcpy(strTemp, (LPUTF8)&pvNativeType[cbCur], strLen);
2403 strTemp[strLen] = 0;
2404 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "Native: %s, ", strTemp);
2405 cbCur += strLen;
2406 _ASSERTE(cbCur < cbNativeType);
2407 delete [] strTemp;
2408 }
2409
2410 // Extract the name of the custom marshaler.
2411 strLen = CPackedLen::GetLength(&pvNativeType[cbCur], &ByteCountLength);
2412 cbCur += ByteCountLength;
2413 strTemp = (LPUTF8)(new char[strLen + 1]);
2414 if(strTemp)
2415 {
2416 memcpy(strTemp, (LPUTF8)&pvNativeType[cbCur], strLen);
2417 strTemp[strLen] = 0;
2418 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "Marshaler: %s, ", strTemp);
2419 cbCur += strLen;
2420 _ASSERTE(cbCur < cbNativeType);
2421 delete [] strTemp;
2422 }
2423 // Extract the cookie string.
2424 strLen = CPackedLen::GetLength(&pvNativeType[cbCur], &ByteCountLength);
2425 cbCur += ByteCountLength;
2426 if (strLen > 0)
2427 {
2428 strTemp = (LPUTF8)(new char[strLen + 1]);
2429 if(strTemp)
2430 {
2431 memcpy(strTemp, (LPUTF8)&pvNativeType[cbCur], strLen);
2432 strTemp[strLen] = 0;
2433 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "Cookie: ");
2434
2435 // Copy the cookie string and transform the embedded nulls into \0's.
2436 for (int i = 0; i < strLen - 1; i++, cbCur++)
2437 {
2438 if (strTemp[i] == 0)
2439 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "\\0");
2440 else
2441 szNTDesc[ulStrLoc++] = strTemp[i];
2442 }
2443 szNTDesc[ulStrLoc++] = strTemp[strLen - 1];
2444 cbCur++;
2445 delete [] strTemp;
2446 }
2447 }
2448 else
2449 {
2450 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "Cookie: ");
2451 }
2452
2453 // Finish the custom marshaler native type description.
2454 ulStrLoc += sprintf_s(szNTDesc + ulStrLoc, STRING_BUFFER_LEN-ulStrLoc, "}");
2455 _ASSERTE(cbCur <= cbNativeType);
2456 }
2457 break;
2458 default:
2459 {
2460 // normal nativetype element: do nothing
2461 }
2462 }
2463 VWriteLine("\t\t\t\t%s",szNTDesc);
2464 if (ulData >= NATIVE_TYPE_MAX)
2465 break;
2466 }
2467 if (cbCur == (ULONG)-1)
2468 {
2469 // There was something that we didn't grok in the signature.
2470 // Just dump out the blob as hex
2471 VWrite("\t\t\t\t{", szNTDesc);
2472 while (cbNativeType--)
2473 VWrite(" %2.2X", *pvNativeType++);
2474 VWriteLine(" }");
2475 }
2476 }
2477} // void MDInfo::DisplayFieldMarshal()
2478
2479void MDInfo::DisplayPinvokeInfo(mdToken inToken)
2480{
2481 HRESULT hr = NOERROR;
2482 DWORD flags;
2483 WCHAR rcImport[512];
2484 mdModuleRef tkModuleRef;
2485
2486 char sFlags[STRING_BUFFER_LEN];
2487
2488 hr = m_pImport->GetPinvokeMap(inToken, &flags, rcImport,
2489 NumItems(rcImport), 0, &tkModuleRef);
2490 if (FAILED(hr))
2491 {
2492 if (hr != CLDB_E_RECORD_NOTFOUND)
2493 VWriteLine("ERROR: GetPinvokeMap failed.", hr);
2494 return;
2495 }
2496
2497 WriteLine("\t\tPinvoke Map Data:");
2498 VWriteLine("\t\tEntry point: %S", rcImport);
2499 VWriteLine("\t\tModule ref: %08x", tkModuleRef);
2500
2501 sFlags[0] = 0;
2502 ISFLAG(Pm, NoMangle);
2503 ISFLAG(Pm, CharSetNotSpec);
2504 ISFLAG(Pm, CharSetAnsi);
2505 ISFLAG(Pm, CharSetUnicode);
2506 ISFLAG(Pm, CharSetAuto);
2507 ISFLAG(Pm, SupportsLastError);
2508 ISFLAG(Pm, CallConvWinapi);
2509 ISFLAG(Pm, CallConvCdecl);
2510 ISFLAG(Pm, CallConvStdcall);
2511 ISFLAG(Pm, CallConvThiscall);
2512 ISFLAG(Pm, CallConvFastcall);
2513
2514 ISFLAG(Pm, BestFitEnabled);
2515 ISFLAG(Pm, BestFitDisabled);
2516 ISFLAG(Pm, BestFitUseAssem);
2517 ISFLAG(Pm, ThrowOnUnmappableCharEnabled);
2518 ISFLAG(Pm, ThrowOnUnmappableCharDisabled);
2519 ISFLAG(Pm, ThrowOnUnmappableCharUseAssem);
2520 if (!*sFlags)
2521 strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
2522
2523 VWriteLine("\t\tMapping flags: %s (%08x)", sFlags, flags);
2524} // void MDInfo::DisplayPinvokeInfo()
2525
2526
2527/////////////////////////////////////////////////////////////////////////
2528// void DisplaySignature(PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob);
2529//
2530// Display COM+ signature -- taken from cordump.cpp's DumpSignature
2531/////////////////////////////////////////////////////////////////////////
2532void MDInfo::DisplaySignature(PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob, const char *preFix)
2533{
2534 ULONG cbCur = 0;
2535 ULONG cb;
2536 // 428793: Prefix complained correctly about unitialized data.
2537 ULONG ulData = (ULONG) IMAGE_CEE_CS_CALLCONV_MAX;
2538 ULONG ulArgs;
2539 HRESULT hr = NOERROR;
2540 ULONG ulSigBlobStart = ulSigBlob;
2541
2542 // initialize sigBuf
2543 InitSigBuffer();
2544
2545 cb = CorSigUncompressData(pbSigBlob, &ulData);
2546 VWriteLine("%s\t\tCallCnvntn: %s", preFix, (g_strCalling[ulData & IMAGE_CEE_CS_CALLCONV_MASK]));
2547 if (cb>ulSigBlob)
2548 goto ErrExit;
2549 cbCur += cb;
2550 ulSigBlob -= cb;
2551
2552 if (ulData & IMAGE_CEE_CS_CALLCONV_HASTHIS)
2553 VWriteLine("%s\t\thasThis ", preFix);
2554 if (ulData & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS)
2555 VWriteLine("%s\t\texplicit ", preFix);
2556 if (ulData & IMAGE_CEE_CS_CALLCONV_GENERIC)
2557 VWriteLine("%s\t\tgeneric ", preFix);
2558
2559 // initialize sigBuf
2560 InitSigBuffer();
2561 if ( isCallConv(ulData,IMAGE_CEE_CS_CALLCONV_FIELD) )
2562 {
2563
2564 // display field type
2565 if (FAILED(hr = GetOneElementType(&pbSigBlob[cbCur], ulSigBlob, &cb)))
2566 goto ErrExit;
2567 VWriteLine("%s\t\tField type: %s", preFix, (LPSTR)m_sigBuf.Ptr());
2568 if (cb>ulSigBlob)
2569 goto ErrExit;
2570 cbCur += cb;
2571 ulSigBlob -= cb;
2572 }
2573 else
2574 {
2575 if (ulData & IMAGE_CEE_CS_CALLCONV_GENERIC)
2576 {
2577 ULONG ulTyArgs;
2578 cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulTyArgs);
2579 if (cb>ulSigBlob)
2580 goto ErrExit;
2581 cbCur += cb;
2582 ulSigBlob -= cb;
2583 VWriteLine("%s\t\tType Arity:%d ", preFix, ulTyArgs);
2584 }
2585 cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulArgs);
2586 if (cb>ulSigBlob)
2587 goto ErrExit;
2588 cbCur += cb;
2589 ulSigBlob -= cb;
2590
2591 if (ulData != IMAGE_CEE_CS_CALLCONV_LOCAL_SIG && ulData != IMAGE_CEE_CS_CALLCONV_GENERICINST)
2592 {
2593 // display return type when it is not a local varsig
2594 if (FAILED(hr = GetOneElementType(&pbSigBlob[cbCur], ulSigBlob, &cb)))
2595 goto ErrExit;
2596 VWriteLine("%s\t\tReturnType:%s", preFix, (LPSTR)m_sigBuf.Ptr());
2597 if (cb>ulSigBlob)
2598 goto ErrExit;
2599 cbCur += cb;
2600 ulSigBlob -= cb;
2601 }
2602
2603 // display count of argument
2604 // display arguments
2605 if (ulSigBlob)
2606 VWriteLine("%s\t\t%ld Arguments", preFix, ulArgs);
2607 else
2608 VWriteLine("%s\t\tNo arguments.", preFix);
2609
2610 ULONG i = 0;
2611 while (i < ulArgs && ulSigBlob > 0)
2612 {
2613 ULONG ulDataTemp;
2614
2615 // Handle the sentinal for varargs because it isn't counted in the args.
2616 CorSigUncompressData(&pbSigBlob[cbCur], &ulDataTemp);
2617 ++i;
2618
2619 // initialize sigBuf
2620 InitSigBuffer();
2621
2622 if (FAILED(hr = GetOneElementType(&pbSigBlob[cbCur], ulSigBlob, &cb)))
2623 goto ErrExit;
2624
2625 VWriteLine("%s\t\t\tArgument #%ld: %s",preFix, i, (LPSTR)m_sigBuf.Ptr());
2626
2627 if (cb>ulSigBlob)
2628 goto ErrExit;
2629
2630 cbCur += cb;
2631 ulSigBlob -= cb;
2632 }
2633 }
2634
2635 // Nothing consumed but not yet counted.
2636 cb = 0;
2637
2638ErrExit:
2639 // We should have consumed all signature blob. If not, dump the sig in hex.
2640 // Also dump in hex if so requested.
2641 if (m_DumpFilter & dumpMoreHex || ulSigBlob != 0)
2642 {
2643 // Did we not consume enough, or try to consume too much?
2644 if (cb > ulSigBlob)
2645 WriteLine("\tERROR IN SIGNATURE: Signature should be larger.");
2646 else
2647 if (cb < ulSigBlob)
2648 {
2649 VWrite("\tERROR IN SIGNATURE: Not all of signature blob was consumed. %d byte(s) remain", ulSigBlob);
2650 // If it is short, just append it to the end.
2651 if (ulSigBlob < 4)
2652 {
2653 Write(": ");
2654 for (; ulSigBlob; ++cbCur, --ulSigBlob)
2655 VWrite("%02x ", pbSigBlob[cbCur]);
2656 WriteLine("");
2657 goto ErrExit2;
2658 }
2659 WriteLine("");
2660 }
2661
2662 // Any appropriate error message has been issued. Dump sig in hex, as determined
2663 // by error or command line switch.
2664 cbCur = 0;
2665 ulSigBlob = ulSigBlobStart;
2666 char rcNewPrefix[80];
2667 sprintf_s(rcNewPrefix, 80, "%s\t\tSignature ", preFix);
2668 DumpHex(rcNewPrefix, pbSigBlob, ulSigBlob, false, 24);
2669 }
2670ErrExit2:
2671 if (FAILED(hr))
2672 Error("ERROR!! Bad signature blob value!");
2673 return;
2674} // void MDInfo::DisplaySignature()
2675
2676
2677/////////////////////////////////////////////////////////////////////////
2678// HRESULT GetOneElementType(mdScope tkScope, BYTE *pbSigBlob, ULONG ulSigBlob, ULONG *pcb)
2679//
2680// Adds description of element type to the end of buffer -- caller must ensure
2681// buffer is large enough.
2682/////////////////////////////////////////////////////////////////////////
2683HRESULT MDInfo::GetOneElementType(PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob, ULONG *pcb)
2684{
2685 HRESULT hr = S_OK; // A result.
2686 ULONG cbCur = 0;
2687 ULONG cb;
2688 ULONG ulData = ELEMENT_TYPE_MAX;
2689 ULONG ulTemp;
2690 int iTemp = 0;
2691 mdToken tk;
2692
2693 cb = CorSigUncompressData(pbSigBlob, &ulData);
2694 cbCur += cb;
2695
2696 // Handle the modifiers.
2697 if (ulData & ELEMENT_TYPE_MODIFIER)
2698 {
2699 if (ulData == ELEMENT_TYPE_SENTINEL)
2700 IfFailGo(AddToSigBuffer("<ELEMENT_TYPE_SENTINEL>"));
2701 else if (ulData == ELEMENT_TYPE_PINNED)
2702 IfFailGo(AddToSigBuffer("PINNED"));
2703 else
2704 {
2705 hr = E_FAIL;
2706 goto ErrExit;
2707 }
2708 if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
2709 goto ErrExit;
2710 cbCur += cb;
2711 goto ErrExit;
2712 }
2713
2714 // Handle the underlying element types.
2715 if (ulData >= ELEMENT_TYPE_MAX)
2716 {
2717 hr = E_FAIL;
2718 goto ErrExit;
2719 }
2720 while (ulData == ELEMENT_TYPE_PTR || ulData == ELEMENT_TYPE_BYREF)
2721 {
2722 IfFailGo(AddToSigBuffer(" "));
2723 IfFailGo(AddToSigBuffer(g_szMapElementType[ulData]));
2724 cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
2725 cbCur += cb;
2726 }
2727 IfFailGo(AddToSigBuffer(" "));
2728 IfFailGo(AddToSigBuffer(g_szMapElementType[ulData]));
2729 if (CorIsPrimitiveType((CorElementType)ulData) ||
2730 ulData == ELEMENT_TYPE_TYPEDBYREF ||
2731 ulData == ELEMENT_TYPE_OBJECT ||
2732 ulData == ELEMENT_TYPE_I ||
2733 ulData == ELEMENT_TYPE_U)
2734 {
2735 // If this is a primitive type, we are done
2736 goto ErrExit;
2737 }
2738 if (ulData == ELEMENT_TYPE_VALUETYPE ||
2739 ulData == ELEMENT_TYPE_CLASS ||
2740 ulData == ELEMENT_TYPE_CMOD_REQD ||
2741 ulData == ELEMENT_TYPE_CMOD_OPT)
2742 {
2743 cb = CorSigUncompressToken(&pbSigBlob[cbCur], &tk);
2744 cbCur += cb;
2745
2746 // get the name of type ref. Don't care if truncated
2747 if (TypeFromToken(tk) == mdtTypeDef || TypeFromToken(tk) == mdtTypeRef)
2748 {
2749 sprintf_s(m_tempFormatBuffer, STRING_BUFFER_LEN, " %ls",TypeDeforRefName(tk, m_szTempBuf, NumItems(m_szTempBuf)));
2750 IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
2751 }
2752 else
2753 {
2754 _ASSERTE(TypeFromToken(tk) == mdtTypeSpec);
2755 sprintf_s(m_tempFormatBuffer, STRING_BUFFER_LEN, " %8x", tk);
2756 IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
2757 }
2758 if (ulData == ELEMENT_TYPE_CMOD_REQD ||
2759 ulData == ELEMENT_TYPE_CMOD_OPT)
2760 {
2761 if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
2762 goto ErrExit;
2763 cbCur += cb;
2764 }
2765
2766 goto ErrExit;
2767 }
2768 if (ulData == ELEMENT_TYPE_SZARRAY)
2769 {
2770 // display the base type of SZARRAY
2771 if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
2772 goto ErrExit;
2773 cbCur += cb;
2774 goto ErrExit;
2775 }
2776 // instantiated type
2777 if (ulData == ELEMENT_TYPE_GENERICINST)
2778 {
2779 // display the type constructor
2780 if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
2781 goto ErrExit;
2782 cbCur += cb;
2783 ULONG numArgs;
2784 cb = CorSigUncompressData(&pbSigBlob[cbCur], &numArgs);
2785 cbCur += cb;
2786 IfFailGo(AddToSigBuffer("<"));
2787
2788 while (numArgs > 0)
2789 {
2790 if (cbCur > ulSigBlob)
2791 goto ErrExit;
2792 if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
2793 goto ErrExit;
2794 cbCur += cb;
2795 --numArgs;
2796 if (numArgs > 0)
2797 IfFailGo(AddToSigBuffer(","));
2798 }
2799 IfFailGo(AddToSigBuffer(">"));
2800 goto ErrExit;
2801 }
2802 if (ulData == ELEMENT_TYPE_VAR)
2803 {
2804 ULONG index;
2805 cb = CorSigUncompressData(&pbSigBlob[cbCur], &index);
2806 cbCur += cb;
2807 sprintf_s(m_tempFormatBuffer, STRING_BUFFER_LEN, "!%d", index);
2808 IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
2809 goto ErrExit;
2810 }
2811 if (ulData == ELEMENT_TYPE_MVAR)
2812 {
2813 ULONG index;
2814 cb = CorSigUncompressData(&pbSigBlob[cbCur], &index);
2815 cbCur += cb;
2816 sprintf_s(m_tempFormatBuffer, STRING_BUFFER_LEN, "!!%d", index);
2817 IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
2818 goto ErrExit;
2819 }
2820 if (ulData == ELEMENT_TYPE_FNPTR)
2821 {
2822 cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
2823 cbCur += cb;
2824 if (ulData & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS)
2825 IfFailGo(AddToSigBuffer(" explicit"));
2826 if (ulData & IMAGE_CEE_CS_CALLCONV_HASTHIS)
2827 IfFailGo(AddToSigBuffer(" hasThis"));
2828
2829 IfFailGo(AddToSigBuffer(" "));
2830 IfFailGo(AddToSigBuffer(g_strCalling[ulData & IMAGE_CEE_CS_CALLCONV_MASK]));
2831
2832 // Get number of args
2833 ULONG numArgs;
2834 cb = CorSigUncompressData(&pbSigBlob[cbCur], &numArgs);
2835 cbCur += cb;
2836
2837 // do return type
2838 if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
2839 goto ErrExit;
2840 cbCur += cb;
2841
2842 IfFailGo(AddToSigBuffer("("));
2843 while (numArgs > 0)
2844 {
2845 if (cbCur > ulSigBlob)
2846 goto ErrExit;
2847 if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
2848 goto ErrExit;
2849 cbCur += cb;
2850 --numArgs;
2851 if (numArgs > 0)
2852 IfFailGo(AddToSigBuffer(","));
2853 }
2854 IfFailGo(AddToSigBuffer(" )"));
2855 goto ErrExit;
2856 }
2857
2858 if(ulData != ELEMENT_TYPE_ARRAY) return E_FAIL;
2859
2860 // display the base type of SDARRAY
2861 if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
2862 goto ErrExit;
2863 cbCur += cb;
2864
2865 // display the rank of MDARRAY
2866 cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
2867 cbCur += cb;
2868 sprintf_s(m_tempFormatBuffer, STRING_BUFFER_LEN, " %d", ulData);
2869 IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
2870 if (ulData == 0)
2871 // we are done if no rank specified
2872 goto ErrExit;
2873
2874 // how many dimensions have size specified?
2875 cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
2876 cbCur += cb;
2877 sprintf_s(m_tempFormatBuffer, STRING_BUFFER_LEN, " %d", ulData);
2878 IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
2879 while (ulData)
2880 {
2881 cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulTemp);
2882 sprintf_s(m_tempFormatBuffer, STRING_BUFFER_LEN, " %d", ulTemp);
2883 IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
2884 cbCur += cb;
2885 ulData--;
2886 }
2887 // how many dimensions have lower bounds specified?
2888 cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
2889 cbCur += cb;
2890 sprintf_s(m_tempFormatBuffer, STRING_BUFFER_LEN, " %d", ulData);
2891 IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
2892 while (ulData)
2893 {
2894
2895 cb = CorSigUncompressSignedInt(&pbSigBlob[cbCur], &iTemp);
2896 sprintf_s(m_tempFormatBuffer, STRING_BUFFER_LEN, " %d", iTemp);
2897 IfFailGo(AddToSigBuffer(m_tempFormatBuffer));
2898 cbCur += cb;
2899 ulData--;
2900 }
2901
2902ErrExit:
2903 if (cbCur > ulSigBlob)
2904 hr = E_FAIL;
2905 *pcb = cbCur;
2906 return hr;
2907} // HRESULT MDInfo::GetOneElementType()
2908
2909// Display the fields of the N/Direct custom value structure.
2910
2911void MDInfo::DisplayCorNativeLink(COR_NATIVE_LINK *pCorNLnk, const char *preFix)
2912{
2913 // Print the LinkType.
2914 const char *curField = "\tLink Type : ";
2915 switch(pCorNLnk->m_linkType)
2916 {
2917 case nltNone:
2918 VWriteLine("%s%s%s(%02x)", preFix, curField, "nltNone", pCorNLnk->m_linkType);
2919 break;
2920 case nltAnsi:
2921 VWriteLine("%s%s%s(%02x)", preFix, curField, "nltAnsi", pCorNLnk->m_linkType);
2922 break;
2923 case nltUnicode:
2924 VWriteLine("%s%s%s(%02x)", preFix, curField, "nltUnicode", pCorNLnk->m_linkType);
2925 break;
2926 case nltAuto:
2927 VWriteLine("%s%s%s(%02x)", preFix, curField, "nltAuto", pCorNLnk->m_linkType);
2928 break;
2929 default:
2930 _ASSERTE(!"Invalid Native Link Type!");
2931 }
2932
2933 // Print the link flags
2934 curField = "\tLink Flags : ";
2935 switch(pCorNLnk->m_flags)
2936 {
2937 case nlfNone:
2938 VWriteLine("%s%s%s(%02x)", preFix, curField, "nlfNone", pCorNLnk->m_flags);
2939 break;
2940 case nlfLastError:
2941 VWriteLine("%s%s%s(%02x)", preFix, curField, "nlfLastError", pCorNLnk->m_flags);
2942 break;
2943 default:
2944 _ASSERTE(!"Invalid Native Link Flags!");
2945 }
2946
2947 // Print the entry point.
2948 WCHAR memRefName[STRING_BUFFER_LEN];
2949 HRESULT hr;
2950 hr = m_pImport->GetMemberRefProps( pCorNLnk->m_entryPoint, NULL, memRefName,
2951 STRING_BUFFER_LEN, NULL, NULL, NULL);
2952 if (FAILED(hr)) Error("GetMemberRefProps failed.", hr);
2953 VWriteLine("%s\tEntry Point : %ls (0x%08x)", preFix, memRefName, pCorNLnk->m_entryPoint);
2954} // void MDInfo::DisplayCorNativeLink()
2955
2956// Fills given varaint with value given in pValue and of type in bCPlusTypeFlag
2957//
2958// Taken from MetaInternal.cpp
2959
2960HRESULT _FillVariant(
2961 BYTE bCPlusTypeFlag,
2962 const void *pValue,
2963 ULONG cbValue,
2964 VARIANT *pvar)
2965{
2966 HRESULT hr = NOERROR;
2967 switch (bCPlusTypeFlag)
2968 {
2969 case ELEMENT_TYPE_BOOLEAN:
2970 V_VT(pvar) = VT_BOOL;
2971 V_BOOL(pvar) = *((BYTE*)pValue); //*((UNALIGNED VARIANT_BOOL *)pValue);
2972 break;
2973 case ELEMENT_TYPE_I1:
2974 V_VT(pvar) = VT_I1;
2975 V_I1(pvar) = *((CHAR*)pValue);
2976 break;
2977 case ELEMENT_TYPE_U1:
2978 V_VT(pvar) = VT_UI1;
2979 V_UI1(pvar) = *((BYTE*)pValue);
2980 break;
2981 case ELEMENT_TYPE_I2:
2982 V_VT(pvar) = VT_I2;
2983 V_I2(pvar) = GET_UNALIGNED_VAL16(pValue);
2984 break;
2985 case ELEMENT_TYPE_U2:
2986 case ELEMENT_TYPE_CHAR:
2987 V_VT(pvar) = VT_UI2;
2988 V_UI2(pvar) = GET_UNALIGNED_VAL16(pValue);
2989 break;
2990 case ELEMENT_TYPE_I4:
2991 V_VT(pvar) = VT_I4;
2992 V_I4(pvar) = GET_UNALIGNED_VAL32(pValue);
2993 break;
2994 case ELEMENT_TYPE_U4:
2995 V_VT(pvar) = VT_UI4;
2996 V_UI4(pvar) = GET_UNALIGNED_VAL32(pValue);
2997 break;
2998 case ELEMENT_TYPE_R4:
2999 {
3000 V_VT(pvar) = VT_R4;
3001 __int32 Value = GET_UNALIGNED_VAL32(pValue);
3002 V_R4(pvar) = (float &)Value;
3003 }
3004 break;
3005 case ELEMENT_TYPE_R8:
3006 {
3007 V_VT(pvar) = VT_R8;
3008 __int64 Value = GET_UNALIGNED_VAL64(pValue);
3009 V_R8(pvar) = (double &) Value;
3010 }
3011
3012 break;
3013 case ELEMENT_TYPE_STRING:
3014 {
3015 V_VT(pvar) = VT_BSTR;
3016 WCHAR *TempString;;
3017#if BIGENDIAN
3018 TempString = (WCHAR *)alloca(cbValue);
3019 memcpy(TempString, pValue, cbValue);
3020 SwapStringLength(TempString, cbValue/sizeof(WCHAR));
3021#else
3022 TempString = (WCHAR *)pValue;
3023#endif
3024 // allocated bstr here
3025 V_BSTR(pvar) = ::SysAllocStringLen((LPWSTR)TempString, cbValue/sizeof(WCHAR));
3026 if (V_BSTR(pvar) == NULL)
3027 hr = E_OUTOFMEMORY;
3028 }
3029 break;
3030 case ELEMENT_TYPE_CLASS:
3031 V_VT(pvar) = VT_UNKNOWN;
3032 V_UNKNOWN(pvar) = NULL;
3033 // _ASSERTE( GET_UNALIGNED_VAL32(pValue) == 0);
3034 break;
3035 case ELEMENT_TYPE_I8:
3036 V_VT(pvar) = VT_I8;
3037 V_CY(pvar).int64 = GET_UNALIGNED_VAL64(pValue);
3038 break;
3039 case ELEMENT_TYPE_U8:
3040 V_VT(pvar) = VT_UI8;
3041 V_CY(pvar).int64 = GET_UNALIGNED_VAL64(pValue);
3042 break;
3043 case ELEMENT_TYPE_VOID:
3044 V_VT(pvar) = VT_EMPTY;
3045 break;
3046 default:
3047 _ASSERTE(!"bad constant value type!");
3048 }
3049
3050 return hr;
3051} // HRESULT _FillVariant()
3052
3053void MDInfo::DisplayAssembly()
3054{
3055 if (m_pAssemblyImport)
3056 {
3057 DisplayAssemblyInfo();
3058 DisplayAssemblyRefs();
3059 DisplayFiles();
3060 DisplayExportedTypes();
3061 DisplayManifestResources();
3062 }
3063} // void MDInfo::DisplayAssembly()
3064
3065void MDInfo::DisplayAssemblyInfo()
3066{
3067 HRESULT hr;
3068 mdAssembly mda;
3069 const BYTE *pbPublicKey;
3070 ULONG cbPublicKey;
3071 ULONG ulHashAlgId;
3072 WCHAR szName[STRING_BUFFER_LEN];
3073 ASSEMBLYMETADATA MetaData;
3074 DWORD dwFlags;
3075
3076 hr = m_pAssemblyImport->GetAssemblyFromScope(&mda);
3077 if (hr == CLDB_E_RECORD_NOTFOUND)
3078 return;
3079 else if (FAILED(hr)) Error("GetAssemblyFromScope() failed.", hr);
3080
3081 // Get the required sizes for the arrays of locales, processors etc.
3082 ZeroMemory(&MetaData, sizeof(ASSEMBLYMETADATA));
3083 hr = m_pAssemblyImport->GetAssemblyProps(mda,
3084 NULL, NULL, // Public Key.
3085 NULL, // Hash Algorithm.
3086 NULL, 0, NULL, // Name.
3087 &MetaData,
3088 NULL); // Flags.
3089 if (FAILED(hr)) Error("GetAssemblyProps() failed.", hr);
3090
3091 // Allocate space for the arrays in the ASSEMBLYMETADATA structure.
3092 if (MetaData.cbLocale)
3093 MetaData.szLocale = new WCHAR[MetaData.cbLocale];
3094 if (MetaData.ulProcessor)
3095 MetaData.rProcessor = new DWORD[MetaData.ulProcessor];
3096 if (MetaData.ulOS)
3097 MetaData.rOS = new OSINFO[MetaData.ulOS];
3098
3099 hr = m_pAssemblyImport->GetAssemblyProps(mda,
3100 (const void **)&pbPublicKey, &cbPublicKey,
3101 &ulHashAlgId,
3102 szName, STRING_BUFFER_LEN, NULL,
3103 &MetaData,
3104 &dwFlags);
3105 if (FAILED(hr)) Error("GetAssemblyProps() failed.", hr);
3106 WriteLine("Assembly");
3107 WriteLine("-------------------------------------------------------");
3108 VWriteLine("\tToken: 0x%08x", mda);
3109 VWriteLine("\tName : %ls", szName);
3110 DumpHex("\tPublic Key ", pbPublicKey, cbPublicKey, false, 24);
3111 VWriteLine("\tHash Algorithm : 0x%08x", ulHashAlgId);
3112 DisplayASSEMBLYMETADATA(&MetaData);
3113 if(MetaData.szLocale) delete [] MetaData.szLocale;
3114 if(MetaData.rProcessor) delete [] MetaData.rProcessor;
3115 if(MetaData.rOS) delete [] MetaData.rOS;
3116
3117 char sFlags[STRING_BUFFER_LEN];
3118 DWORD flags = dwFlags;
3119
3120 sFlags[0] = 0;
3121 ISFLAG(Af, PublicKey);
3122 ISFLAG(Af, Retargetable);
3123 ISFLAG(AfContentType_, WindowsRuntime);
3124
3125 if (!*sFlags)
3126 strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
3127
3128 VWriteLine("\tFlags : %s (%08x)", sFlags, dwFlags);
3129 DisplayCustomAttributes(mda, "\t");
3130 DisplayPermissions(mda, "\t");
3131 WriteLine("");
3132} // void MDInfo::DisplayAssemblyInfo()
3133
3134void MDInfo::DisplayAssemblyRefs()
3135{
3136 HCORENUM assemblyRefEnum = NULL;
3137 mdAssemblyRef AssemblyRefs[ENUM_BUFFER_SIZE];
3138 ULONG count;
3139 ULONG totalCount = 1;
3140 HRESULT hr;
3141
3142 while (SUCCEEDED(hr = m_pAssemblyImport->EnumAssemblyRefs( &assemblyRefEnum,
3143 AssemblyRefs, NumItems(AssemblyRefs), &count)) &&
3144 count > 0)
3145 {
3146 for (ULONG i = 0; i < count; i++, totalCount++)
3147 {
3148 VWriteLine("AssemblyRef #%d (%08x)", totalCount, AssemblyRefs[i]);
3149 WriteLine("-------------------------------------------------------");
3150 DisplayAssemblyRefInfo(AssemblyRefs[i]);
3151 WriteLine("");
3152 }
3153 }
3154 m_pAssemblyImport->CloseEnum(assemblyRefEnum);
3155} // void MDInfo::DisplayAssemblyRefs()
3156
3157void MDInfo::DisplayAssemblyRefInfo(mdAssemblyRef inAssemblyRef)
3158{
3159 HRESULT hr;
3160 const BYTE *pbPublicKeyOrToken;
3161 ULONG cbPublicKeyOrToken;
3162 WCHAR szName[STRING_BUFFER_LEN];
3163 ASSEMBLYMETADATA MetaData;
3164 const BYTE *pbHashValue;
3165 ULONG cbHashValue;
3166 DWORD dwFlags;
3167
3168 VWriteLine("\tToken: 0x%08x", inAssemblyRef);
3169
3170 // Get sizes for the arrays in the ASSEMBLYMETADATA structure.
3171 ZeroMemory(&MetaData, sizeof(ASSEMBLYMETADATA));
3172 hr = m_pAssemblyImport->GetAssemblyRefProps(inAssemblyRef,
3173 NULL, NULL, // Public Key or Token.
3174 NULL, 0, NULL, // Name.
3175 &MetaData,
3176 NULL, NULL, // HashValue.
3177 NULL); // Flags.
3178 if (FAILED(hr)) Error("GetAssemblyRefProps() failed.", hr);
3179
3180 // Allocate space for the arrays in the ASSEMBLYMETADATA structure.
3181 if (MetaData.cbLocale)
3182 MetaData.szLocale = new WCHAR[MetaData.cbLocale];
3183 if (MetaData.ulProcessor)
3184 MetaData.rProcessor = new DWORD[MetaData.ulProcessor];
3185 if (MetaData.ulOS)
3186 MetaData.rOS = new OSINFO[MetaData.ulOS];
3187
3188 hr = m_pAssemblyImport->GetAssemblyRefProps(inAssemblyRef,
3189 (const void **)&pbPublicKeyOrToken, &cbPublicKeyOrToken,
3190 szName, STRING_BUFFER_LEN, NULL,
3191 &MetaData,
3192 (const void **)&pbHashValue, &cbHashValue,
3193 &dwFlags);
3194 if (FAILED(hr)) Error("GetAssemblyRefProps() failed.", hr);
3195
3196 DumpHex("\tPublic Key or Token", pbPublicKeyOrToken, cbPublicKeyOrToken, false, 24);
3197 VWriteLine("\tName: %ls", szName);
3198 DisplayASSEMBLYMETADATA(&MetaData);
3199 if(MetaData.szLocale) delete [] MetaData.szLocale;
3200 if(MetaData.rProcessor) delete [] MetaData.rProcessor;
3201 if(MetaData.rOS) delete [] MetaData.rOS;
3202 DumpHex("\tHashValue Blob", pbHashValue, cbHashValue, false, 24);
3203
3204 char sFlags[STRING_BUFFER_LEN];
3205 DWORD flags = dwFlags;
3206
3207 sFlags[0] = 0;
3208 ISFLAG(Af, PublicKey);
3209 ISFLAG(Af, Retargetable);
3210 ISFLAG(AfContentType_, WindowsRuntime);
3211#if 0
3212 ISFLAG(Af, LegacyLibrary);
3213 ISFLAG(Af, LegacyPlatform);
3214 ISFLAG(Af, Library);
3215 ISFLAG(Af, Platform);
3216#endif
3217 if (!*sFlags)
3218 strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
3219
3220 VWriteLine("\tFlags: %s (%08x)", sFlags, dwFlags);
3221 DisplayCustomAttributes(inAssemblyRef, "\t");
3222 WriteLine("");
3223} // void MDInfo::DisplayAssemblyRefInfo()
3224
3225void MDInfo::DisplayFiles()
3226{
3227 HCORENUM fileEnum = NULL;
3228 mdFile Files[ENUM_BUFFER_SIZE];
3229 ULONG count;
3230 ULONG totalCount = 1;
3231 HRESULT hr;
3232
3233 while (SUCCEEDED(hr = m_pAssemblyImport->EnumFiles( &fileEnum,
3234 Files, NumItems(Files), &count)) &&
3235 count > 0)
3236 {
3237 for (ULONG i = 0; i < count; i++, totalCount++)
3238 {
3239 VWriteLine("File #%d (%08x)", totalCount, Files[i]);
3240 WriteLine("-------------------------------------------------------");
3241 DisplayFileInfo(Files[i]);
3242 WriteLine("");
3243 }
3244 }
3245 m_pAssemblyImport->CloseEnum(fileEnum);
3246} // void MDInfo::DisplayFiles()
3247
3248void MDInfo::DisplayFileInfo(mdFile inFile)
3249{
3250 HRESULT hr;
3251 WCHAR szName[STRING_BUFFER_LEN];
3252 const BYTE *pbHashValue;
3253 ULONG cbHashValue;
3254 DWORD dwFlags;
3255
3256 VWriteLine("\tToken: 0x%08x", inFile);
3257
3258 hr = m_pAssemblyImport->GetFileProps(inFile,
3259 szName, STRING_BUFFER_LEN, NULL,
3260 (const void **)&pbHashValue, &cbHashValue,
3261 &dwFlags);
3262 if (FAILED(hr)) Error("GetFileProps() failed.", hr);
3263 VWriteLine("\tName : %ls", szName);
3264 DumpHex("\tHashValue Blob ", pbHashValue, cbHashValue, false, 24);
3265
3266 char sFlags[STRING_BUFFER_LEN];
3267 DWORD flags = dwFlags;
3268
3269 sFlags[0] = 0;
3270 ISFLAG(Ff, ContainsMetaData);
3271 ISFLAG(Ff, ContainsNoMetaData);
3272 if (!*sFlags)
3273 strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
3274
3275 VWriteLine("\tFlags : %s (%08x)", sFlags, dwFlags);
3276 DisplayCustomAttributes(inFile, "\t");
3277 WriteLine("");
3278
3279} // MDInfo::DisplayFileInfo()
3280
3281void MDInfo::DisplayExportedTypes()
3282{
3283 HCORENUM comTypeEnum = NULL;
3284 mdExportedType ExportedTypes[ENUM_BUFFER_SIZE];
3285 ULONG count;
3286 ULONG totalCount = 1;
3287 HRESULT hr;
3288
3289 while (SUCCEEDED(hr = m_pAssemblyImport->EnumExportedTypes( &comTypeEnum,
3290 ExportedTypes, NumItems(ExportedTypes), &count)) &&
3291 count > 0)
3292 {
3293 for (ULONG i = 0; i < count; i++, totalCount++)
3294 {
3295 VWriteLine("ExportedType #%d (%08x)", totalCount, ExportedTypes[i]);
3296 WriteLine("-------------------------------------------------------");
3297 DisplayExportedTypeInfo(ExportedTypes[i]);
3298 WriteLine("");
3299 }
3300 }
3301 m_pAssemblyImport->CloseEnum(comTypeEnum);
3302} // void MDInfo::DisplayExportedTypes()
3303
3304void MDInfo::DisplayExportedTypeInfo(mdExportedType inExportedType)
3305{
3306 HRESULT hr;
3307 WCHAR szName[STRING_BUFFER_LEN];
3308 mdToken tkImplementation;
3309 mdTypeDef tkTypeDef;
3310 DWORD dwFlags;
3311 char sFlags[STRING_BUFFER_LEN];
3312
3313 VWriteLine("\tToken: 0x%08x", inExportedType);
3314
3315 hr = m_pAssemblyImport->GetExportedTypeProps(inExportedType,
3316 szName, STRING_BUFFER_LEN, NULL,
3317 &tkImplementation,
3318 &tkTypeDef,
3319 &dwFlags);
3320 if (FAILED(hr)) Error("GetExportedTypeProps() failed.", hr);
3321 VWriteLine("\tName: %ls", szName);
3322 VWriteLine("\tImplementation token: 0x%08x", tkImplementation);
3323 VWriteLine("\tTypeDef token: 0x%08x", tkTypeDef);
3324 VWriteLine("\tFlags : %s (%08x)",ClassFlags(dwFlags, sFlags), dwFlags);
3325 DisplayCustomAttributes(inExportedType, "\t");
3326 WriteLine("");
3327} // void MDInfo::DisplayExportedTypeInfo()
3328
3329void MDInfo::DisplayManifestResources()
3330{
3331 HCORENUM manifestResourceEnum = NULL;
3332 mdManifestResource ManifestResources[ENUM_BUFFER_SIZE];
3333 ULONG count;
3334 ULONG totalCount = 1;
3335 HRESULT hr;
3336
3337 while (SUCCEEDED(hr = m_pAssemblyImport->EnumManifestResources( &manifestResourceEnum,
3338 ManifestResources, NumItems(ManifestResources), &count)) &&
3339 count > 0)
3340 {
3341 for (ULONG i = 0; i < count; i++, totalCount++)
3342 {
3343 VWriteLine("ManifestResource #%d (%08x)", totalCount, ManifestResources[i]);
3344 WriteLine("-------------------------------------------------------");
3345 DisplayManifestResourceInfo(ManifestResources[i]);
3346 WriteLine("");
3347 }
3348 }
3349 m_pAssemblyImport->CloseEnum(manifestResourceEnum);
3350} // void MDInfo::DisplayManifestResources()
3351
3352void MDInfo::DisplayManifestResourceInfo(mdManifestResource inManifestResource)
3353{
3354 HRESULT hr;
3355 WCHAR szName[STRING_BUFFER_LEN];
3356 mdToken tkImplementation;
3357 DWORD dwOffset;
3358 DWORD dwFlags;
3359
3360 VWriteLine("\tToken: 0x%08x", inManifestResource);
3361
3362 hr = m_pAssemblyImport->GetManifestResourceProps(inManifestResource,
3363 szName, STRING_BUFFER_LEN, NULL,
3364 &tkImplementation,
3365 &dwOffset,
3366 &dwFlags);
3367 if (FAILED(hr)) Error("GetManifestResourceProps() failed.", hr);
3368 VWriteLine("Name: %ls", szName);
3369 VWriteLine("Implementation token: 0x%08x", tkImplementation);
3370 VWriteLine("Offset: 0x%08x", dwOffset);
3371
3372 char sFlags[STRING_BUFFER_LEN];
3373 DWORD flags = dwFlags;
3374
3375 sFlags[0] = 0;
3376 ISFLAG(Mr, Public);
3377 ISFLAG(Mr, Private);
3378 if (!*sFlags)
3379 strcpy_s(sFlags, STRING_BUFFER_LEN, "[none]");
3380
3381 VWriteLine("\tFlags: %s (%08x)", sFlags, dwFlags);
3382 DisplayCustomAttributes(inManifestResource, "\t");
3383 WriteLine("");
3384} // void MDInfo::DisplayManifestResourceInfo()
3385
3386void MDInfo::DisplayASSEMBLYMETADATA(ASSEMBLYMETADATA *pMetaData)
3387{
3388 ULONG i;
3389
3390 VWriteLine("\tVersion: %d.%d.%d.%d", pMetaData->usMajorVersion, pMetaData->usMinorVersion, pMetaData->usBuildNumber, pMetaData->usRevisionNumber);
3391 VWriteLine("\tMajor Version: 0x%08x", pMetaData->usMajorVersion);
3392 VWriteLine("\tMinor Version: 0x%08x", pMetaData->usMinorVersion);
3393 VWriteLine("\tBuild Number: 0x%08x", pMetaData->usBuildNumber);
3394 VWriteLine("\tRevision Number: 0x%08x", pMetaData->usRevisionNumber);
3395 VWriteLine("\tLocale: %ls", pMetaData->cbLocale ? pMetaData->szLocale : W("<null>"));
3396 for (i = 0; i < pMetaData->ulProcessor; i++)
3397 VWriteLine("\tProcessor #%ld: 0x%08x", i+1, pMetaData->rProcessor[i]);
3398 for (i = 0; i < pMetaData->ulOS; i++)
3399 {
3400 VWriteLine("\tOS #%ld:", i+1);
3401 VWriteLine("\t\tOS Platform ID: 0x%08x", pMetaData->rOS[i].dwOSPlatformId);
3402 VWriteLine("\t\tOS Major Version: 0x%08x", pMetaData->rOS[i].dwOSMajorVersion);
3403 VWriteLine("\t\tOS Minor Version: 0x%08x", pMetaData->rOS[i].dwOSMinorVersion);
3404 }
3405} // void MDInfo::DisplayASSEMBLYMETADATA()
3406
3407void MDInfo::DisplayUserStrings()
3408{
3409 HCORENUM stringEnum = NULL; // string enumerator.
3410 mdString Strings[ENUM_BUFFER_SIZE]; // String tokens from enumerator.
3411 CQuickArray<WCHAR> rUserString; // Buffer to receive string.
3412 WCHAR *szUserString; // Working pointer into buffer.
3413 ULONG chUserString; // Size of user string.
3414 CQuickArray<char> rcBuf; // Buffer to hold the BLOB version of the string.
3415 char *szBuf; // Working pointer into buffer.
3416 ULONG chBuf; // Saved size of the user string.
3417 ULONG count; // Items returned from enumerator.
3418 ULONG totalCount = 1; // Running count of strings.
3419 bool bUnprint = false; // Is an unprintable character found?
3420 HRESULT hr; // A result.
3421 while (SUCCEEDED(hr = m_pImport->EnumUserStrings( &stringEnum,
3422 Strings, NumItems(Strings), &count)) &&
3423 count > 0)
3424 {
3425 if (totalCount == 1)
3426 { // If only one, it is the NULL string, so don't print it.
3427 WriteLine("User Strings");
3428 WriteLine("-------------------------------------------------------");
3429 }
3430 for (ULONG i = 0; i < count; i++, totalCount++)
3431 {
3432 do { // Try to get the string into the existing buffer.
3433 hr = m_pImport->GetUserString( Strings[i], rUserString.Ptr(),(ULONG32)rUserString.MaxSize(), &chUserString);
3434 if (hr == CLDB_S_TRUNCATION)
3435 { // Buffer wasn't big enough, try to enlarge it.
3436 if (FAILED(rUserString.ReSizeNoThrow(chUserString)))
3437 Error("malloc failed.", E_OUTOFMEMORY);
3438 continue;
3439 }
3440 } while (hr == CLDB_S_TRUNCATION);
3441 if (FAILED(hr)) Error("GetUserString failed.", hr);
3442
3443 szUserString = rUserString.Ptr();
3444 chBuf = chUserString;
3445
3446 VWrite("%08x : (%2d) L\"", Strings[i], chUserString);
3447 for (ULONG j=0; j<chUserString; j++)
3448 {
3449 switch (*szUserString)
3450 {
3451 case 0:
3452 Write("\\0"); break;
3453 case L'\r':
3454 Write("\\r"); break;
3455 case L'\n':
3456 Write("\\n"); break;
3457 case L'\t':
3458 Write("\\t"); break;
3459 default:
3460 if (iswprint(*szUserString))
3461 VWrite("%lc", *szUserString);
3462 else
3463 {
3464 bUnprint = true;
3465 Write(".");
3466 }
3467 break;
3468 }
3469 ++szUserString;
3470 if((j>0)&&((j&0x7F)==0)) WriteLine("");
3471 }
3472 WriteLine("\"");
3473
3474 // Print the user string as a blob if an unprintable character is found.
3475 if (bUnprint)
3476 {
3477 bUnprint = false;
3478 szUserString = rUserString.Ptr();
3479 if (FAILED(hr = rcBuf.ReSizeNoThrow(81))) //(chBuf * 5 + 1);
3480 Error("ReSize failed.", hr);
3481 szBuf = rcBuf.Ptr();
3482 ULONG j,k;
3483 WriteLine("\t\tUser string has unprintables, hex format below:");
3484 for (j = 0,k=0; j < chBuf; j++)
3485 {
3486 sprintf_s (&szBuf[k*5], 81, "%04x ", szUserString[j]);
3487 k++;
3488 if((k==16)||(j == (chBuf-1)))
3489 {
3490 szBuf[k*5] = '\0';
3491 VWriteLine("\t\t%s", szBuf);
3492 k=0;
3493 }
3494 }
3495 }
3496 }
3497 }
3498 if (stringEnum)
3499 m_pImport->CloseEnum(stringEnum);
3500} // void MDInfo::DisplayUserStrings()
3501
3502void MDInfo::DisplayUnsatInfo()
3503{
3504 HRESULT hr = S_OK;
3505
3506 HCORENUM henum = 0;
3507 mdToken tk;
3508 ULONG cMethods;
3509
3510 Write("\nUnresolved Externals\n");
3511 Write("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
3512
3513 while ( (hr = m_pImport->EnumUnresolvedMethods(
3514 &henum,
3515 &tk,
3516 1,
3517 &cMethods)) == S_OK && cMethods )
3518 {
3519 if ( TypeFromToken(tk) == mdtMethodDef )
3520 {
3521 // a method definition without implementation
3522 DisplayMethodInfo( tk );
3523 }
3524 else if ( TypeFromToken(tk) == mdtMemberRef )
3525 {
3526 // an unresolved MemberRef to a global function
3527 DisplayMemberRefInfo( tk, "" );
3528 }
3529 else
3530 {
3531 _ASSERTE(!"Unknown token kind!");
3532 }
3533 }
3534 m_pImport->CloseEnum(henum);
3535} // void MDInfo::DisplayUnsatInfo()
3536
3537//*******************************************************************************
3538// This code is used for debugging purposes only. This will just print out the
3539// entire database.
3540//*******************************************************************************
3541const char *MDInfo::DumpRawNameOfType(ULONG iType)
3542{
3543 if (iType <= iRidMax)
3544 {
3545 const char *pNameTable;
3546 m_pTables->GetTableInfo(iType, 0,0,0,0, &pNameTable);
3547 return pNameTable;
3548 }
3549 else
3550 // Is the field a coded token?
3551 if (iType <= iCodedTokenMax)
3552 {
3553 int iCdTkn = iType - iCodedToken;
3554 const char *pNameCdTkn;
3555 m_pTables->GetCodedTokenInfo(iCdTkn, 0,0, &pNameCdTkn);
3556 return pNameCdTkn;
3557 }
3558
3559 // Fixed type.
3560 switch (iType)
3561 {
3562 case iBYTE:
3563 return "BYTE";
3564 case iSHORT:
3565 return "short";
3566 case iUSHORT:
3567 return "USHORT";
3568 case iLONG:
3569 return "long";
3570 case iULONG:
3571 return "ULONG";
3572 case iSTRING:
3573 return "string";
3574 case iGUID:
3575 return "GUID";
3576 case iBLOB:
3577 return "blob";
3578 }
3579 // default:
3580 static char buf[30];
3581 sprintf_s(buf, 30, "unknown type 0x%02x", iType);
3582 return buf;
3583} // const char *MDInfo::DumpRawNameOfType()
3584
3585void MDInfo::DumpRawCol(ULONG ixTbl, ULONG ixCol, ULONG rid, bool bStats)
3586{
3587 ULONG ulType; // Type of a column.
3588 ULONG ulVal; // Value of a column.
3589 LPCUTF8 pString; // Pointer to a string.
3590 const void *pBlob; // Pointer to a blob.
3591 ULONG cb; // Size of something.
3592
3593 m_pTables->GetColumn(ixTbl, ixCol, rid, &ulVal);
3594 m_pTables->GetColumnInfo(ixTbl, ixCol, 0, 0, &ulType, 0);
3595
3596 if (ulType <= iRidMax)
3597 {
3598 const char *pNameTable;
3599 m_pTables->GetTableInfo(ulType, 0,0,0,0, &pNameTable);
3600 VWrite("%s[%x]", pNameTable, ulVal);
3601 }
3602 else
3603 // Is the field a coded token?
3604 if (ulType <= iCodedTokenMax)
3605 {
3606 int iCdTkn = ulType - iCodedToken;
3607 const char *pNameCdTkn;
3608 m_pTables->GetCodedTokenInfo(iCdTkn, 0,0, &pNameCdTkn);
3609 VWrite("%s[%08x]", pNameCdTkn, ulVal);
3610 }
3611 else
3612 {
3613 // Fixed type.
3614 switch (ulType)
3615 {
3616 case iBYTE:
3617 VWrite("%02x", ulVal);
3618 break;
3619 case iSHORT:
3620 case iUSHORT:
3621 VWrite("%04x", ulVal);
3622 break;
3623 case iLONG:
3624 case iULONG:
3625 VWrite("%08x", ulVal);
3626 break;
3627 case iSTRING:
3628 if (ulVal && (m_DumpFilter & dumpNames))
3629 {
3630 m_pTables->GetString(ulVal, &pString);
3631 VWrite("(%x)\"%s\"", ulVal, pString);
3632 }
3633 else
3634 VWrite("string#%x", ulVal);
3635 if (bStats && ulVal)
3636 {
3637 m_pTables->GetString(ulVal, &pString);
3638 cb = (ULONG) strlen(pString) + 1;
3639 VWrite("(%d)", cb);
3640 }
3641 break;
3642 case iGUID:
3643 VWrite("guid#%x", ulVal);
3644 if (bStats && ulVal)
3645 {
3646 VWrite("(16)");
3647 }
3648 break;
3649 case iBLOB:
3650 VWrite("blob#%x", ulVal);
3651 if (bStats && ulVal)
3652 {
3653 m_pTables->GetBlob(ulVal, &cb, &pBlob);
3654 cb += 1;
3655 if (cb > 128)
3656 cb += 1;
3657 if (cb > 16535)
3658 cb += 1;
3659 VWrite("(%d)", cb);
3660 }
3661 break;
3662 default:
3663 VWrite("unknown type 0x%04x", ulVal);
3664 break;
3665 }
3666 }
3667} // void MDInfo::DumpRawCol()
3668
3669ULONG MDInfo::DumpRawColStats(ULONG ixTbl, ULONG ixCol, ULONG cRows)
3670{
3671 ULONG rslt = 0;
3672 ULONG ulType; // Type of a column.
3673 ULONG ulVal; // Value of a column.
3674 LPCUTF8 pString; // Pointer to a string.
3675 const void *pBlob; // Pointer to a blob.
3676 ULONG cb; // Size of something.
3677
3678 m_pTables->GetColumnInfo(ixTbl, ixCol, 0, 0, &ulType, 0);
3679
3680 if (IsHeapType(ulType))
3681 {
3682 for (ULONG rid=1; rid<=cRows; ++rid)
3683 {
3684 m_pTables->GetColumn(ixTbl, ixCol, rid, &ulVal);
3685 // Fixed type.
3686 switch (ulType)
3687 {
3688 case iSTRING:
3689 if (ulVal)
3690 {
3691 m_pTables->GetString(ulVal, &pString);
3692 cb = (ULONG) strlen(pString);
3693 rslt += cb + 1;
3694 }
3695 break;
3696 case iGUID:
3697 if (ulVal)
3698 rslt += 16;
3699 break;
3700 case iBLOB:
3701 if (ulVal)
3702 {
3703 m_pTables->GetBlob(ulVal, &cb, &pBlob);
3704 rslt += cb + 1;
3705 if (cb > 128)
3706 rslt += 1;
3707 if (cb > 16535)
3708 rslt += 1;
3709 }
3710 break;
3711 default:
3712 break;
3713 }
3714 }
3715 }
3716 return rslt;
3717} // ULONG MDInfo::DumpRawColStats()
3718
3719int MDInfo::DumpHex(
3720 const char *szPrefix, // String prefix for first line.
3721 const void *pvData, // The data to print.
3722 ULONG cbData, // Bytes of data to print.
3723 int bText, // If true, also dump text.
3724 ULONG nLine) // Bytes per line to print.
3725{
3726 const BYTE *pbData = static_cast<const BYTE*>(pvData);
3727 ULONG i; // Loop control.
3728 ULONG nPrint; // Number to print in an iteration.
3729 ULONG nSpace; // Spacing calculations.
3730 ULONG nPrefix; // Size of the prefix.
3731 ULONG nLines=0; // Number of lines printed.
3732 const char *pPrefix; // For counting spaces in the prefix.
3733
3734 // Round down to 8 characters.
3735 nLine = nLine & ~0x7;
3736
3737 for (nPrefix=0, pPrefix=szPrefix; *pPrefix; ++pPrefix)
3738 {
3739 if (*pPrefix == '\t')
3740 nPrefix = (nPrefix + 8) & ~7;
3741 else
3742 ++nPrefix;
3743 }
3744 //nPrefix = strlen(szPrefix);
3745 do
3746 { // Write the line prefix.
3747 if (szPrefix)
3748 VWrite("%s:", szPrefix);
3749 else
3750 VWrite("%*s:", nPrefix, "");
3751 szPrefix = 0;
3752 ++nLines;
3753
3754 // Calculate spacing.
3755 nPrint = min(cbData, nLine);
3756 nSpace = nLine - nPrint;
3757
3758 // dump in hex.
3759 for(i=0; i<nPrint; i++)
3760 {
3761 if ((i&7) == 0)
3762 Write(" ");
3763 VWrite("%02x ", pbData[i]);
3764 }
3765 if (bText)
3766 {
3767 // Space out to the text spot.
3768 if (nSpace)
3769 VWrite("%*s", nSpace*3+nSpace/8, "");
3770 // Dump in text.
3771 Write(">");
3772 for(i=0; i<nPrint; i++)
3773 VWrite("%c", (isprint(pbData[i])) ? pbData[i] : ' ');
3774 // Space out the text, and finish the line.
3775 VWrite("%*s<", nSpace, "");
3776 }
3777 VWriteLine("");
3778
3779 // Next data to print.
3780 cbData -= nPrint;
3781 pbData += nPrint;
3782 }
3783 while (cbData > 0);
3784
3785 return nLines;
3786} // int MDInfo::DumpHex()
3787
3788void MDInfo::DumpRawHeaps()
3789{
3790 HRESULT hr; // A result.
3791 ULONG ulSize; // Bytes in a heap.
3792 const BYTE *pData; // Pointer to a blob.
3793 ULONG cbData; // Size of a blob.
3794 ULONG oData; // Offset of current blob.
3795 char rcPrefix[30]; // To format line prefix.
3796
3797 m_pTables->GetBlobHeapSize(&ulSize);
3798 VWriteLine("");
3799 VWriteLine("Blob Heap: %d(%#x) bytes", ulSize,ulSize);
3800 oData = 0;
3801 do
3802 {
3803 m_pTables->GetBlob(oData, &cbData, (const void**)&pData);
3804 sprintf_s(rcPrefix, 30, "%5x,%-2x", oData, cbData);
3805 DumpHex(rcPrefix, pData, cbData);
3806 hr = m_pTables->GetNextBlob(oData, &oData);
3807 }
3808 while (hr == S_OK);
3809
3810 m_pTables->GetStringHeapSize(&ulSize);
3811 VWriteLine("");
3812 VWriteLine("String Heap: %d(%#x) bytes", ulSize,ulSize);
3813 oData = 0;
3814 const char *pString;
3815 do
3816 {
3817 m_pTables->GetString(oData, &pString);
3818 if (m_DumpFilter & dumpMoreHex)
3819 {
3820 sprintf_s(rcPrefix, 30, "%08x", oData);
3821 DumpHex(rcPrefix, pString, (ULONG)strlen(pString)+1);
3822 }
3823 else
3824 if (*pString != 0)
3825 VWrite("%08x: %s\n", oData, pString);
3826 hr = m_pTables->GetNextString(oData, &oData);
3827 }
3828 while (hr == S_OK);
3829 VWriteLine("");
3830
3831 DisplayUserStrings();
3832
3833} // void MDInfo::DumpRawHeaps()
3834
3835
3836void MDInfo::DumpRaw(int iDump, bool bunused)
3837{
3838 ULONG cTables; // Tables in the database.
3839 ULONG cCols; // Columns in a table.
3840 ULONG cRows; // Rows in a table.
3841 ULONG cbRow; // Bytes in a row of a table.
3842 ULONG iKey; // Key column of a table.
3843 const char *pNameTable; // Name of a table.
3844 ULONG oCol; // Offset of a column.
3845 ULONG cbCol; // Size of a column.
3846 ULONG ulType; // Type of a column.
3847 const char *pNameColumn; // Name of a column.
3848 ULONG ulSize;
3849
3850 // Heaps is easy -- there is a specific bit for that.
3851 bool bStats = (m_DumpFilter & dumpStats) != 0;
3852 // Rows are harder. Was there something else that limited data?
3853 BOOL bRows = (m_DumpFilter & (dumpSchema | dumpHeader)) == 0;
3854 BOOL bSchema = bRows || (m_DumpFilter & dumpSchema);
3855 // (m_DumpFilter & (dumpSchema | dumpHeader | dumpCSV | dumpRaw | dumpStats | dumpRawHeaps))
3856
3857 if (m_pTables2)
3858 {
3859 // Get the raw metadata header.
3860 const BYTE *pbData = NULL;
3861 const BYTE *pbStream = NULL; // One of the stream.s
3862 const BYTE *pbMd = NULL; // The metadata stream.
3863 ULONG cbData = 0;
3864 ULONG cbStream = 0; // One of the streams.
3865 ULONG cbMd = 0; // The metadata stream.
3866 const char *pName;
3867 HRESULT hr = S_OK;
3868 ULONG ix;
3869
3870 m_pTables2->GetMetaDataStorage((const void**)&pbData, &cbData);
3871
3872 // Per the ECMA spec, the section data looks like this:
3873 struct MDSTORAGESIGNATURE
3874 {
3875 ULONG lSignature; // "Magic" signature.
3876 USHORT iMajorVer; // Major file version.
3877 USHORT iMinorVer; // Minor file version.
3878 ULONG iExtraData; // Offset to next structure of information
3879 ULONG iVersionString; // Length of version string
3880 BYTE pVersion[0]; // Version string
3881 };
3882 struct MDSTORAGEHEADER
3883 {
3884 BYTE fFlags; // STGHDR_xxx flags.
3885 BYTE pad;
3886 USHORT iStreams; // How many streams are there.
3887 };
3888 const MDSTORAGESIGNATURE *pStorage = (const MDSTORAGESIGNATURE *) pbData;
3889 const MDSTORAGEHEADER *pSHeader = (const MDSTORAGEHEADER *)(pbData + sizeof(MDSTORAGESIGNATURE) + pStorage->iVersionString);
3890
3891 VWriteLine("Metadata section: 0x%08x, version: %d.%d, extra: %d, version len: %d, version: %s", pStorage->lSignature, pStorage->iMajorVer, pStorage->iMinorVer, pStorage->iExtraData, pStorage->iVersionString, pStorage->pVersion);
3892 VWriteLine(" flags: 0x%02x, streams: %d", pSHeader->fFlags, pSHeader->iStreams);
3893 if (m_DumpFilter & dumpMoreHex)
3894 {
3895 const BYTE *pbEnd = pbData;
3896 ULONG cb = sizeof(MDSTORAGESIGNATURE) + pStorage->iVersionString + sizeof(MDSTORAGEHEADER);
3897 hr = m_pTables2->GetMetaDataStreamInfo(0, &pName, (const void**)&pbEnd, &cbStream);
3898 if (hr == S_OK)
3899 cb = (ULONG)(pbEnd - pbData);
3900 DumpHex(" ", pbData, cb);
3901 }
3902
3903 for (ix=0; hr == S_OK; ++ix)
3904 {
3905 hr = m_pTables2->GetMetaDataStreamInfo(ix, &pName, (const void**)&pbStream, &cbStream);
3906 if (hr != S_OK)
3907 break;
3908 if (strcmp(pName, "#~") == 0 || strcmp(pName, "#-") == 0)
3909 {
3910 pbMd = pbStream;
3911 cbMd = cbStream;
3912 }
3913
3914 VWriteLine("Stream %d: name: %s, size %d", ix, pName, cbStream);
3915 // hex for individual stream headers in metadata section dump. hex for
3916 // the streams themselves distributed throughout the dump.
3917 }
3918
3919 if (pbMd)
3920 {
3921 // Per ECMA, the metadata header looks like this:
3922 struct MD
3923 {
3924 ULONG m_ulReserved; // Reserved, must be zero.
3925 BYTE m_major; // Version numbers.
3926 BYTE m_minor;
3927 BYTE m_heaps; // Bits for heap sizes.
3928 BYTE m_rid; // log-base-2 of largest rid.
3929 unsigned __int64 m_maskvalid; // Bit mask of present table counts.
3930 unsigned __int64 m_sorted; // Bit mask of sorted tables. };
3931 };
3932
3933 const MD *pMd;
3934 pMd = (const MD *)pbMd;
3935
3936 VWriteLine("Metadata header: %d.%d, heaps: 0x%02x, rid: 0x%02x, valid: 0x%016I64x, sorted: 0x%016I64x",
3937 pMd->m_major, pMd->m_minor, pMd->m_heaps, pMd->m_rid,
3938 (ULONGLONG)GET_UNALIGNED_VAL64(&(pMd->m_maskvalid)),
3939 (ULONGLONG)GET_UNALIGNED_VAL64(&(pMd->m_sorted)));
3940
3941 if (m_DumpFilter & dumpMoreHex)
3942 {
3943 DumpHex(" ", pbMd, sizeof(MD));
3944 }
3945 }
3946 VWriteLine("");
3947 }
3948
3949 m_pTables->GetNumTables(&cTables);
3950
3951 m_pTables->GetStringHeapSize(&ulSize);
3952 VWrite("Strings: %d(%#x)", ulSize, ulSize);
3953 m_pTables->GetBlobHeapSize(&ulSize);
3954 VWrite(", Blobs: %d(%#x)", ulSize, ulSize);
3955 m_pTables->GetGuidHeapSize(&ulSize);
3956 VWrite(", Guids: %d(%#x)", ulSize, ulSize);
3957 m_pTables->GetUserStringHeapSize(&ulSize);
3958 VWriteLine(", User strings: %d(%#x)", ulSize, ulSize);
3959
3960 for (ULONG ixTbl = 0; ixTbl < cTables; ++ixTbl)
3961 {
3962 m_pTables->GetTableInfo(ixTbl, &cbRow, &cRows, &cCols, &iKey, &pNameTable);
3963
3964 if (bRows) // when dumping rows, print a break between row data and schema
3965 VWriteLine("=================================================");
3966 VWriteLine("%2d(%#x): %-20s cRecs:%5d(%#x), cbRec:%3d(%#x), cbTable:%6d(%#x)",
3967 ixTbl, ixTbl, pNameTable, cRows, cRows, cbRow, cbRow, cbRow * cRows, cbRow * cRows);
3968
3969 if (!bSchema && !bRows)
3970 continue;
3971
3972 // Dump column definitions for the table.
3973 ULONG ixCol;
3974 for (ixCol=0; ixCol<cCols; ++ixCol)
3975 {
3976 m_pTables->GetColumnInfo(ixTbl, ixCol, &oCol, &cbCol, &ulType, &pNameColumn);
3977
3978 VWrite(" col %2x:%c %-12s oCol:%2x, cbCol:%x, %-7s",
3979 ixCol, ((ixCol==iKey)?'*':' '), pNameColumn, oCol, cbCol, DumpRawNameOfType(ulType));
3980
3981 if (bStats)
3982 {
3983 ulSize = DumpRawColStats(ixTbl, ixCol, cRows);
3984 if (ulSize)
3985 VWrite("(%d)", ulSize);
3986 }
3987 VWriteLine("");
3988 }
3989
3990 if (!bRows)
3991 continue;
3992
3993 // Dump the rows.
3994 for (ULONG rid = 1; rid <= cRows; ++rid)
3995 {
3996 if (rid == 1)
3997 VWriteLine("-------------------------------------------------");
3998 VWrite(" %3x == ", rid);
3999 for (ixCol=0; ixCol < cCols; ++ixCol)
4000 {
4001 if (ixCol) VWrite(", ");
4002 VWrite("%d:", ixCol);
4003 DumpRawCol(ixTbl, ixCol, rid, bStats);
4004 }
4005 VWriteLine("");
4006 }
4007 }
4008} // void MDInfo::DumpRaw()
4009
4010void MDInfo::DumpRawCSV()
4011{
4012 ULONG cTables; // Tables in the database.
4013 ULONG cCols; // Columns in a table.
4014 ULONG cRows; // Rows in a table.
4015 ULONG cbRow; // Bytes in a row of a table.
4016 const char *pNameTable; // Name of a table.
4017 ULONG ulSize;
4018
4019 m_pTables->GetNumTables(&cTables);
4020
4021 VWriteLine("Name,Size,cRecs,cbRec");
4022
4023 m_pTables->GetStringHeapSize(&ulSize);
4024 VWriteLine("Strings,%d", ulSize);
4025
4026 m_pTables->GetBlobHeapSize(&ulSize);
4027 VWriteLine("Blobs,%d", ulSize);
4028
4029 m_pTables->GetGuidHeapSize(&ulSize);
4030 VWriteLine("Guids,%d", ulSize);
4031
4032 for (ULONG ixTbl = 0; ixTbl < cTables; ++ixTbl)
4033 {
4034 m_pTables->GetTableInfo(ixTbl, &cbRow, &cRows, &cCols, NULL, &pNameTable);
4035 VWriteLine("%s,%d,%d,%d", pNameTable, cbRow*cRows, cRows, cbRow);
4036 }
4037
4038} // void MDInfo::DumpRawCSV()
4039
4040