Metadata File Format


This section provides a brief description of the logical layout of metadata in files. It provides very superficial coverage of this topic, as this subject is generally considered to be an advanced topic and is beyond the scope of this book.

The creation of metadata follows one of two paths: using an unmanaged API or using a managed API. Unmanaged APIs could be considered a lower “level path; they do not provide much support to ensure that the structures produced are consistent. In contrast, managed APIs form a higher-level path . They were used earlier in this chapter to create a dynamic type.

Logically, a CLR file looks like Figure 3.10. It follows the standard Windows Portable Executable (PE) file layout. The metadata, seen in the middle of the figure, is stored in either tables or heaps. A table can be considered an array of structures that uses indexes to identify each new record, whereas a heap is essentially a sequence of bytes. The reason for the difference is that some aspects of metadata ”for example, the version number of an assembly ”are regular and can be stored in tables. The name of an assembly, however, is a string and therefore can be of varying length. In such a case, it is better to store the name in a heap and provide an address that indicates the start of the string.

Figure 3.10. A CLR file

graphics/03fig10.gif

Metadata tokens are used to identify metadata. A metadata token is four bytes in size. The most significant byte represents the type of metadata element referred to by the token and, therefore, identifies the metadata structure holding the definition. The remaining three bytes serve as indexes into that structure used to locate the metadata. A quick examination of corhdr.h would reveal the following:

 typedef ULONG32 mdToken;  ... typedef mdToken mdModule; typedef mdToken mdTypeRef; typedef mdToken mdTypeDef; typedef mdToken mdFieldDef; ... 

From the first line, you can see that metadata tokens are type-defined to be 32-bit unsigned values. Two types of tokens exist: definitions, such as mdTypeDef , and references, such as mdTypeRef . A definition defines the type, indicating that the type lives within this assembly. A reference refers to a type in another assembly.

Listing 3.10 uses a mixture of both Managed and Unmanaged C++ to access the raw metadata tables within a PE file. Note that this program is very poorly written, as it includes little or no error checking and very some terse variable names . This approach keeps the example simple, but it is definitely not good coding practice.

Listing 3.10 Accessing metadata tables within a PE file
 #using <mscorlib.dll> #include <cor.h> using namespace System; void PrintTypeDefProperties(IMetaDataImport *imdi,                             mdTypeDef token) {   const ULONG maxNameSize = 1024;   WCHAR lTypeName[maxNameSize];   ULONG actualNameSize = 0;   DWORD flags = 0;   mdToken extends;   imdi->GetTypeDefProps (token, lTypeName, maxNameSize,                          &actualNameSize, &flags,                          &extends);   String *s = lTypeName;   Console::WriteLine(s); } int main() {   CoInitialize(0);   IMetaDataDispenser *imdd = 0;   IMetaDataImport *imdi = 0;   IMetaDataAssemblyImport *imdai = 0;   HRESULT hr =           CoCreateInstance(CLSID_CorMetaDataDispenser,                            NULL, CLSCTX_INPROC_SERVER,                            IID_IMetaDataDispenser,                            (void**)&imdd);   unsigned short pModuleFilename [] =           L"C:\WINDOWS\...\v1.0.3705\mscorlib.dll";   HRESULT h = imdd->OpenScope(pModuleFilename, 0,                               IID_IMetaDataImport,                               (IUnknown **)&imdi);   h = imdd->OpenScope(pModuleFilename, 0,     IID_IMetaDataAssemblyImport, (IUnknown **)&imdai);   HCORENUM enr = 0;   const arraySize = 256;   mdTypeDef lTypeDefTokens[arraySize];   ULONG count = 0;   h = imdi->EnumTypeDefs (&enr, lTypeDefTokens, arraySize,                           &count);   for (ULONG i = 0; i != count; ++i)   {      PrintTypeDefProperties(imdi, lTypeDefTokens[i]);   }   imdi->CloseEnum (enr);   imdd->Release();   imdi->Release();   imdai->Release();   CoUninitialize();   return 0; } 

Executing the program in Listing 3.10 produces the following output:

 System.Object  System.ICloneable System.Collections.IEnumerable System.Collections.ICollection System.Collections.IList System.Array SorterObjectArray ... System.Collections.Hashtable bucket KeyCollection ValueCollection SyncHashtable System.Collections.IDictionaryEnumerator HashtableEnumerator System.Collections.Queue SynchronizedQueue QueueEnumerator 


Programming in the .NET Environment
Programming in the .NET Environment
ISBN: 0201770180
EAN: 2147483647
Year: 2002
Pages: 146

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net