//
// Copyright (c) 2002
// Ronald Kevin Burton
//
// This material is provided "as is", with absolutely no warranty expressed
// or implied. This software is provided solely as part of ".NET Common Language
// Runtime Unleashed" to help illustrate concepts and principles described in 
// that book. Any use is at your own risk.
//
// Permission to use or copy this software for any purpose is hereby granted 
// without fee, provided the above notices are retained on all copies.
// Permission to modify the code and to distribute modified code is granted,
// provided the above notices are retained, and a notice that the code was
// modified is included with the above copyright notice.
//
// 
// MetadataTablesPage2.cpp : plik implementacji
//

#include "stdafx.h"

#include "AssemblyDoc.h"
#include "AssemblyView.h"
#include "MetadataTablesPage.h"

void CMetadataTablesPage::HandleSingleFieldMarshal(DWORD index, const META_TABLE_ENTRY& t, CAssemblyView* , HTREEITEM tvitem)
{
	HTREEITEM treeRowItem;
	PBYTE row;
	DWORD parentIndex;
	DWORD nativeIndex;

	WCHAR lBuffer[128];

	// Rodzic (indeks tablicy Field lub Param; jest to zakodowany indeks HasFieldMarshal)
	// NativeType (indeks sterty Blob)

	row = t.Address + t.RowSize * index;

	if(t.IndexSizes & 0x01)
	{
		parentIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		parentIndex = *((USHORT *)row);
		row += 2;
	}

	wsprintf(lBuffer, L"Rodzic: 0x%08X", parentIndex);
	treeRowItem = m_ctrlTableTree.InsertItem(lBuffer, tvitem);

	// Wartość
	if(t.HeapSizes & 0x04)
	{
		nativeIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		nativeIndex = *((USHORT *)row);
		row += 2;
	}
	wsprintf(lBuffer, L"Macierzysty: 0x%08X", nativeIndex);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);
}

void CMetadataTablesPage::HandleFieldMarshal(const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	for(DWORD i = 0; i < t.Rows; ++i)
	{
		HandleSingleFieldMarshal(i, t, pView, tvitem);
	}
}

void CMetadataTablesPage::HandleSingleDeclSecurity(DWORD index, const META_TABLE_ENTRY& t, CAssemblyView* , HTREEITEM tvitem)
{
	HTREEITEM treeRowItem;
	PBYTE row;
	USHORT action;
	DWORD parentIndex;
	DWORD permissionIndex;

	WCHAR lBuffer[128];

	// Akcja (dwubajtowa wartość)
	// Rodzic (indeks tablicy TypeDef, Method lub Assembly; jest to zakodowany indeks HasDeclSecurity)
	// PermissionSet (indeks sterty Blob) 

	row = t.Address + t.RowSize * index;

	action = *((USHORT *)row);
	row += 2;

	wsprintf(lBuffer, L"Akcja: 0x%04X", action);
	treeRowItem = m_ctrlTableTree.InsertItem(lBuffer, tvitem);

	if(t.IndexSizes & 0x02)
	{
		parentIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		parentIndex = *((USHORT *)row);
		row += 2;
	}

	wsprintf(lBuffer, L"Rodzic: 0x%08X", parentIndex);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);

	// Uprawnienie
	if(t.HeapSizes & 0x04)
	{
		permissionIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		permissionIndex = *((USHORT *)row);
		row += 2;
	}
	wsprintf(lBuffer, L"Uprawnienie: 0x%08X", permissionIndex);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);
}

void CMetadataTablesPage::HandleDeclSecurity(const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	for(DWORD i = 0; i < t.Rows; ++i)
	{
		HandleSingleDeclSecurity(i, t, pView, tvitem);
	}
}

void CMetadataTablesPage::HandleSingleClassLayout(DWORD index, const META_TABLE_ENTRY& t, CAssemblyView* , HTREEITEM tvitem)
{
	HTREEITEM treeRowItem;
	PBYTE row;
	USHORT packingSize;
	DWORD classSize;
	DWORD parentIndex;

	WCHAR lBuffer[128];

	// PackingSize (dwubajtowa stała)
	// ClassSize (4-bajtowa stała)
	// Rodzic (indeks tablicy TypeDef)

	row = t.Address + t.RowSize * index;

	packingSize = *((USHORT *)row);
	row += 2;

	classSize = *((ULONG *)row);
	row += 4;

	wsprintf(lBuffer, L"Wielkość upakowania/Wielkość klasy: 0x%04X 0x%08X", packingSize, classSize);
	treeRowItem = m_ctrlTableTree.InsertItem(lBuffer, tvitem);

	if(t.IndexSizes & 0x01)
	{
		parentIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		parentIndex = *((USHORT *)row);
		row += 2;
	}

	wsprintf(lBuffer, L"Rodzic: 0x%08X", parentIndex);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);
}

void CMetadataTablesPage::HandleClassLayout(const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	for(DWORD i = 0; i < t.Rows; ++i)
	{
		HandleSingleClassLayout(i, t, pView, tvitem);
	}
}

void CMetadataTablesPage::HandleSingleStandAloneSig(DWORD index, const META_TABLE_ENTRY& t, CAssemblyView* , HTREEITEM tvitem)
{
	HTREEITEM treeRowItem;
	PBYTE row;
	DWORD signature;

	WCHAR lBuffer[128];

	// Sygnatura (indeks sterty Blob)
	row = t.Address + t.RowSize * index;

	if(t.HeapSizes & 0x04)
	{
		signature = *((DWORD *)row);
		row += 4;
	}
	else
	{
		signature = *((USHORT *)row);
		row += 2;
	}

	wsprintf(lBuffer, L"Sygnatura: 0x%08X", signature);
	treeRowItem = m_ctrlTableTree.InsertItem(lBuffer, tvitem);
}

void CMetadataTablesPage::HandleStandAloneSig(const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	for(DWORD i = 0; i < t.Rows; ++i)
	{
		HandleSingleStandAloneSig(i, t, pView, tvitem);
	}
}

void CMetadataTablesPage::HandleSingleEventMap(DWORD index, const META_TABLE_ENTRY& t, CAssemblyView* , HTREEITEM tvitem)
{
	HTREEITEM treeRowItem;
	PBYTE row;
	DWORD parentIndex;
	DWORD eventListIndex;

	WCHAR lBuffer[128];

	// Rodzic (indeks tablicy TypeDef)
	// EventList (indeks tablicy Event).

	row = t.Address + t.RowSize * index;

	if(t.IndexSizes & 0x01)
	{
		parentIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		parentIndex = *((USHORT *)row);
		row += 2;
	}

	wsprintf(lBuffer, L"Rodzic: 0x%08X", parentIndex);
	treeRowItem = m_ctrlTableTree.InsertItem(lBuffer, tvitem);

	if(t.IndexSizes & 0x02)
	{
		eventListIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		eventListIndex = *((USHORT *)row);
		row += 2;
	}
	wsprintf(lBuffer, L"Lista zdarzeń: 0x%08X", eventListIndex);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);
}

void CMetadataTablesPage::HandleEventMap(const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	for(DWORD i = 0; i < t.Rows; ++i)
	{
		HandleSingleEventMap(i, t, pView, tvitem);
	}
}

void CMetadataTablesPage::HandleSingleEvent(DWORD index, const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	HTREEITEM treeRowItem;
	PBYTE row;
	USHORT eventFlags;
	DWORD nameIndex;
	DWORD typeIndex;

	WCHAR lBuffer[128];

	// EventFlags (dwubajtowa maska bitowa typu EventAttribute, sekcja 22.1.4)
	// Nazwa (indeks sterty String)
	// EventType (indeks tablicy TypeDef, TypeRef lub TypeSpec; jest to zakodowany indeks TypeDefOrRef)  [odpowiada to typowi zdarzenia; nie jest to typ, do którego należy zdarzenie]

	row = t.Address + t.RowSize * index;

	eventFlags = *((USHORT *)row);
	row += 2;

	if(t.HeapSizes & 0x01)
	{
		nameIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		nameIndex = *((USHORT *)row);
		row += 2;
	}

	wcscpy(lBuffer, pView->StringTableEntry(nameIndex).c_str());
	treeRowItem = m_ctrlTableTree.InsertItem(lBuffer, tvitem);

	wsprintf(lBuffer, L"Znaczniki: 0x%04X", eventFlags);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);

	if(t.IndexSizes & 0x02)
	{
		typeIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		typeIndex = *((USHORT *)row);
		row += 2;
	}
	wsprintf(lBuffer, L"Typ: 0x%08X", typeIndex);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);
}

void CMetadataTablesPage::HandleEvent(const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	for(DWORD i = 0; i < t.Rows; ++i)
	{
		HandleSingleEvent(i, t, pView, tvitem);
	}
}

void CMetadataTablesPage::HandleSinglePropertyMap(DWORD index, const META_TABLE_ENTRY& t, CAssemblyView* , HTREEITEM tvitem)
{
	HTREEITEM treeRowItem;
	PBYTE row;
	DWORD parentIndex;
	DWORD propertyList;

	WCHAR lBuffer[128];

	// Rodzic (indeks tablicy TypeDef)
	// PropertyList (indeks sterty Property). Znakuje pierwsze ciągłe uruchomienie Properties należących do rodzica. Praca jest kontynuowana aż do osiągnięcia mniejszej wartości:
	//   ostatniego wiersza tablicy Property
	//   kolejnego uruchomienia Properties, które można odnaleźć poprzez zbadanie PropertyList kolejnego wiersza w tej tablicy PropertyMap

	row = t.Address + t.RowSize * index;

	if(t.IndexSizes & 0x01)
	{
		parentIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		parentIndex = *((USHORT *)row);
		row += 2;
	}

	wsprintf(lBuffer, L"Rodzic: 0x%04X", parentIndex);
	treeRowItem = m_ctrlTableTree.InsertItem(lBuffer, tvitem);

	if(t.IndexSizes & 0x02)
	{
		propertyList = *((DWORD *)row);
		row += 4;
	}
	else
	{
		propertyList = *((USHORT *)row);
		row += 2;
	}
	wsprintf(lBuffer, L"Lista właściwości: 0x%08X", propertyList);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);
}

void CMetadataTablesPage::HandlePropertyMap(const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	for(DWORD i = 0; i < t.Rows; ++i)
	{
		HandleSinglePropertyMap(i, t, pView, tvitem);
	}
}

void CMetadataTablesPage::HandleSingleProperty(DWORD index, const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	HTREEITEM treeRowItem;
	PBYTE row;
	USHORT propertyFlags;
	DWORD nameIndex;
	DWORD typeIndex;

	WCHAR lBuffer[128];

	// Znaczniki (dwubajtowa maska bitowa typu PropertyAttributes, sekcja 22.1.13)
	// Nazwa (indeks sterty String)
	// Typ (indeks sterty Blob) [nazwa tej kolumny jest myląca, gdyż nie ma tu indeksów tablic TypeDef lub TypeRef, a jedynie indeksy sygnatury w stercie Blob właściwości)

	row = t.Address + t.RowSize * index;

	propertyFlags = *((USHORT *)row);
	row += 2;

	if(t.HeapSizes & 0x02)
	{
		nameIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		nameIndex = *((USHORT *)row);
		row += 2;
	}

	wcscpy(lBuffer, pView->StringTableEntry(nameIndex).c_str());
	treeRowItem = m_ctrlTableTree.InsertItem(lBuffer, tvitem);

	wsprintf(lBuffer, L"Znaczniki: 0x%04X", propertyFlags);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);

	if(t.IndexSizes & 0x04)
	{
		typeIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		typeIndex = *((USHORT *)row);
		row += 2;
	}
	wsprintf(lBuffer, L"Typ: 0x%08X", typeIndex);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);
}

void CMetadataTablesPage::HandleProperty(const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	for(DWORD i = 0; i < t.Rows; ++i)
	{
		HandleSingleProperty(i, t, pView, tvitem);
	}
}

void CMetadataTablesPage::HandleSingleMethodSemantics(DWORD index, const META_TABLE_ENTRY& t, CAssemblyView* , HTREEITEM tvitem)
{
	HTREEITEM treeRowItem;
	PBYTE row;
	USHORT semantics;
	DWORD methodIndex;
	DWORD associationIndex;

	WCHAR lBuffer[128];

	// Semantyka (dwubajtowa maska bitowa typu MethodSemanticsAttributes, sekcja 22.1.10)
	// Metoda (indeks tablicy Method)
	// Powiązanie (indeks tablicy Event lub Property; jest to zakodowany indeks HasSemantics) 

	row = t.Address + t.RowSize * index;

	semantics = *((USHORT *)row);
	row += 2;

	if(t.IndexSizes & 0x02)
	{
		methodIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		methodIndex = *((USHORT *)row);
		row += 2;
	}

	wsprintf(lBuffer, L"Semantyka: 0x%04X", semantics);
	treeRowItem = m_ctrlTableTree.InsertItem(lBuffer, tvitem);

	wsprintf(lBuffer, L"Metoda: 0x%04X", methodIndex);
	treeRowItem = m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);

	if(t.IndexSizes & 0x04)
	{
		associationIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		associationIndex = *((USHORT *)row);
		row += 2;
	}
	wsprintf(lBuffer, L"Powiązanie: 0x%08X", associationIndex);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);
}

void CMetadataTablesPage::HandleMethodSemantics(const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	for(DWORD i = 0; i < t.Rows; ++i)
	{
		HandleSingleMethodSemantics(i, t, pView, tvitem);
	}
}

void CMetadataTablesPage::HandleSingleTypeSpec(DWORD index, const META_TABLE_ENTRY& t, CAssemblyView* , HTREEITEM tvitem)
{
	PBYTE row;
	DWORD signature;

	WCHAR lBuffer[128];

	// Sygnatura (indeks sterty Blob, gdzie obiekt blob jest sformatowany zgodnie z wytycznymi w sekcji 22.2.14)

	row = t.Address + t.RowSize * index;

	if(t.HeapSizes & 0x04)
	{
		signature = *((DWORD *)row);
		row += 4;
	}
	else
	{
		signature = *((USHORT *)row);
		row += 2;
	}

	wsprintf(lBuffer, L"Sygnatura: 0x%04X", signature);
	m_ctrlTableTree.InsertItem(lBuffer, tvitem);

}

void CMetadataTablesPage::HandleTypeSpec(const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	for(DWORD i = 0; i < t.Rows; ++i)
	{
		HandleSingleTypeSpec(i, t, pView, tvitem);
	}
}

void CMetadataTablesPage::HandleSingleFieldRVA(DWORD index, const META_TABLE_ENTRY& t, CAssemblyView* , HTREEITEM tvitem)
{
	PBYTE row;
	DWORD rva;
	DWORD fieldIndex;

	WCHAR lBuffer[128];

	// RVA (4-bajtowa stała)
	// Pole (indeks tablicy Field)

	row = t.Address + t.RowSize * index;

	rva = *((DWORD *)row);
	row += 4;

	if(t.IndexSizes & 0x02)
	{
		fieldIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		fieldIndex = *((USHORT *)row);
		row += 2;
	}

	wsprintf(lBuffer, L"RVA: 0x%08X", rva);
	HTREEITEM treeRowItem = m_ctrlTableTree.InsertItem(lBuffer, tvitem);

	wsprintf(lBuffer, L"Pole: 0x%08X", fieldIndex);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);
}

void CMetadataTablesPage::HandleFieldRVA(const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	for(DWORD i = 0; i < t.Rows; ++i)
	{
		HandleSingleFieldRVA(i, t, pView, tvitem);
	}
}

void CMetadataTablesPage::HandleSingleAssemblyProcessor(DWORD index, const META_TABLE_ENTRY& t, CAssemblyView* , HTREEITEM tvitem)
{
	PBYTE row;
	DWORD processor;

	WCHAR lBuffer[128];

	// Procesor (4-bajtowa stała)

	row = t.Address + t.RowSize * index;

	processor = *((DWORD *)row);
	row += 4;

	wsprintf(lBuffer, L"Procesor: 0x%08X", processor);
	m_ctrlTableTree.InsertItem(lBuffer, tvitem);
}

void CMetadataTablesPage::HandleAssemblyProcessor(const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	for(DWORD i = 0; i < t.Rows; ++i)
	{
		HandleSingleAssemblyProcessor(i, t, pView, tvitem);
	}
}

void CMetadataTablesPage::HandleSingleAssemblyOS(DWORD index, const META_TABLE_ENTRY& t, CAssemblyView* , HTREEITEM tvitem)
{
	PBYTE row;
	DWORD platform;
	DWORD major;
	DWORD minor;

	WCHAR lBuffer[128];

	// OSPlatformID  (4-bajtowa stała)
	// OSMajorVersion (4-bajtowa stała)
	// OSMinorVersion (4-bajtowa stała)

	row = t.Address + t.RowSize * index;

	platform = *((DWORD *)row);
	row += 4;
	major = *((DWORD *)row);
	row += 4;
	minor = *((DWORD *)row);
	row += 4;

	wsprintf(lBuffer, L"Platforma: 0x%08X", platform);
	m_ctrlTableTree.InsertItem(lBuffer, tvitem);
	wsprintf(lBuffer, L"Wersja: 0x%08X.0x%08X", major, minor);
	m_ctrlTableTree.InsertItem(lBuffer, tvitem);
}

void CMetadataTablesPage::HandleAssemblyOS(const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	for(DWORD i = 0; i < t.Rows; ++i)
	{
		HandleSingleAssemblyOS(i, t, pView, tvitem);
	}
}

void CMetadataTablesPage::HandleSingleAssemblyRefProcessor(DWORD index, const META_TABLE_ENTRY& t, CAssemblyView* , HTREEITEM tvitem)
{
	PBYTE row;
	DWORD processor;
	DWORD assemblyRefIndex;

	WCHAR lBuffer[128];

	// Procesor (4-bajtowa stała)
	// AssemblyRef  (indeks tablicy AssemblyRef)

	row = t.Address + t.RowSize * index;

	processor = *((DWORD *)row);
	row += 4;

	wsprintf(lBuffer, L"Procesor: 0x%08X", processor);
	m_ctrlTableTree.InsertItem(lBuffer, tvitem);

	if(t.IndexSizes & 0x02)
	{
		assemblyRefIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		assemblyRefIndex = *((USHORT *)row);
		row += 2;
	}
	wsprintf(lBuffer, L"AssemblyRef: 0x%08X", assemblyRefIndex);
	m_ctrlTableTree.InsertItem(lBuffer, tvitem);
}

void CMetadataTablesPage::HandleAssemblyRefProcessor(const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	for(DWORD i = 0; i < t.Rows; ++i)
	{
		HandleSingleAssemblyRefProcessor(i, t, pView, tvitem);
	}
}

void CMetadataTablesPage::HandleSingleAssemblyRefOS(DWORD index, const META_TABLE_ENTRY& t, CAssemblyView* , HTREEITEM tvitem)
{
	PBYTE row;
	DWORD platform;
	DWORD major;
	DWORD minor;
	DWORD assemblyRefIndex;

	WCHAR lBuffer[128];

	// OSPlatformID  (4-bajtowa stała)
	// OSMajorVersion (4-bajtowa stała)
	// OSMinorVersion (4-bajtowa stała)
	// AssemblyRef  (indeks tablicy AssemblyRef)

	row = t.Address + t.RowSize * index;

	platform = *((DWORD *)row);
	row += 4;
	major = *((DWORD *)row);
	row += 4;
	minor = *((DWORD *)row);
	row += 4;

	wsprintf(lBuffer, L"Platforma: 0x%08X", platform);
	m_ctrlTableTree.InsertItem(lBuffer, tvitem);
	wsprintf(lBuffer, L"Wersja: 0x%08X.0x%08X", major, minor);
	m_ctrlTableTree.InsertItem(lBuffer, tvitem);

	if(t.IndexSizes & 0x08)
	{
		assemblyRefIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		assemblyRefIndex = *((USHORT *)row);
		row += 2;
	}
	wsprintf(lBuffer, L"AssemblyRef: 0x%08X", assemblyRefIndex);
	m_ctrlTableTree.InsertItem(lBuffer, tvitem);
}

void CMetadataTablesPage::HandleAssemblyRefOS(const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	for(DWORD i = 0; i < t.Rows; ++i)
	{
		HandleSingleAssemblyRefOS(i, t, pView, tvitem);
	}
}

void CMetadataTablesPage::HandleSingleFile(DWORD index, const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	PBYTE row;
	DWORD flags;
	DWORD nameIndex;
	DWORD hashValue;

	WCHAR lBuffer[128];

	// Znaczniki (4-bajtowa maska bitowa typu FileAttributes, sekcja 22.1.6)
	// Nazwa (indeks sterty String)
	// HashValue (indeks sterty Blob)

	row = t.Address + t.RowSize * index;

	flags = *((DWORD *)row);
	row += 4;

	if(t.HeapSizes & 0x01)
	{
		nameIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		nameIndex = *((USHORT *)row);
		row += 2;
	}

	if(t.HeapSizes & 0x04)
	{
		hashValue = *((DWORD *)row);
		row += 4;
	}
	else
	{
		hashValue = *((USHORT *)row);
		row += 2;
	}

	wcscpy(lBuffer, pView->StringTableEntry(nameIndex).c_str());
	HTREEITEM treeRowItem = m_ctrlTableTree.InsertItem(lBuffer, tvitem);

	wsprintf(lBuffer, L"Znaczniki: 0x%08X", flags);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);

	wsprintf(lBuffer, L"Skrót: 0x%08X", hashValue);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);
}

void CMetadataTablesPage::HandleFile(const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	for(DWORD i = 0; i < t.Rows; ++i)
	{
		HandleSingleFile(i, t, pView, tvitem);
	}
}

void CMetadataTablesPage::HandleSingleExportedType(DWORD index, const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	PBYTE row;
	DWORD flags;
	DWORD typeDefId;
	DWORD nameIndex;
	DWORD nameSpaceIndex;
	DWORD implementation;

	WCHAR lBuffer[256];

	// Znaczniki (4-bajtowa maska bitowa typu TypeAttributes, sekcja 22.1.14)
	// TypeDefId (4-bajtowy indeks tablicy TypeDef innego modułu w tym podzespole). To pole służy tylko jako wskazówka. Jeśli wpis w docelowej tablicy TypeDef odpowiada wpisom TypeName i TypeNamespace w tej tablicy, to rozwiązywanie powiodło się. Niezgodność oznacza, iż CLI powinien powrócić do przeszukiwania docelowej tablicy TypeDef.
	// TypeName (indeks sterty String)
	// TypeNamespace (indeks sterty String)
	// Implementacja. Może to być indeks (a konkretnie zakodowany indeks implementacji) jednej z dwóch poniższych tablic:
	//   Tablicy plików, której wpisy informują o module w aktualnym podzespole, który zawiera TypeDef
	//   Tablicy ExportedType, w której dany wpis jest otaczającym typem dla danego zagnieżdżonego typu

	row = t.Address + t.RowSize * index;

	flags = *((DWORD *)row);
	row += 4;

	typeDefId = *((DWORD *)row);
	row += 4;

	if(t.HeapSizes & 0x01)
	{
		nameIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		nameIndex = *((USHORT *)row);
		row += 2;
	}
	if(t.HeapSizes & 0x01)
	{
		nameSpaceIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		nameSpaceIndex = *((USHORT *)row);
		row += 2;
	}

	if(t.IndexSizes & 0x10)
	{
		implementation = *((DWORD *)row);
		row += 4;
	}
	else
	{
		implementation = *((USHORT *)row);
		row += 2;
	}

	wsprintf(lBuffer, L"%ls.%ls",
			          pView->StringTableEntry(nameSpaceIndex).c_str(),
			          pView->StringTableEntry(nameIndex).c_str());
	HTREEITEM treeRowItem = m_ctrlTableTree.InsertItem(lBuffer, tvitem);

	wsprintf(lBuffer, L"Znaczniki: 0x%08X", flags);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);
	wsprintf(lBuffer, L"Id: 0x%08X", typeDefId);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);

	wsprintf(lBuffer, L"Implementacja: 0x%08X", implementation);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);
}

void CMetadataTablesPage::HandleExportedType(const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	for(DWORD i = 0; i < t.Rows; ++i)
	{
		HandleSingleExportedType(i, t, pView, tvitem);
	}
}

void CMetadataTablesPage::HandleSingleManifestResource(DWORD index, const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	PBYTE row;
	DWORD offset;
	DWORD flags;
	DWORD nameIndex;
	DWORD implementation;

	WCHAR lBuffer[128];

	// Przesunięcie (4-bajtowa stała)
	// Znaczniki (4-bajtowa maska bitowa typu ManifestResourceAttributes, sekcja 22.1.8) 
	// Nazwa (indeks sterty String)
	// Implementacja (indeks tablicy File lub AssemblyRef albo pusta wartość; jest to zakodowany indeks implementacji)

	row = t.Address + t.RowSize * index;

	offset = *((DWORD *)row);
	row += 4;
	flags = *((DWORD *)row);
	row += 4;

	if(t.HeapSizes & 0x01)
	{
		nameIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		nameIndex = *((USHORT *)row);
		row += 2;
	}

	if(t.IndexSizes & 0x08)
	{
		implementation = *((DWORD *)row);
		row += 4;
	}
	else
	{
		implementation = *((USHORT *)row);
		row += 2;
	}

	wcscpy(lBuffer, pView->StringTableEntry(nameIndex).c_str());
	HTREEITEM treeRowItem = m_ctrlTableTree.InsertItem(lBuffer, tvitem);

	wsprintf(lBuffer, L"Przesunięcie: 0x%08X", offset);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);

	wsprintf(lBuffer, L"Znaczniki: 0x%08X", flags);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);

	wsprintf(lBuffer, L"Implementacja: 0x%08X", implementation);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);
}

void CMetadataTablesPage::HandleManifestResource(const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	for(DWORD i = 0; i < t.Rows; ++i)
	{
		HandleSingleManifestResource(i, t, pView, tvitem);
	}
}

void CMetadataTablesPage::HandleSingleNestedClass(DWORD index, const META_TABLE_ENTRY& t, CAssemblyView*, HTREEITEM tvitem)
{
	PBYTE row;
	DWORD nestedIndex;
	DWORD enclosingIndex;

	WCHAR lBuffer[128];

	// NestedClass (indeks tablicy TypeDef)
	// EnclosingClass (indeks tablicy TypeDef)

	row = t.Address + t.RowSize * index;

	if(t.IndexSizes & 0x01)
	{
		nestedIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		nestedIndex = *((USHORT *)row);
		row += 2;
	}

	if(t.IndexSizes & 0x02)
	{
		enclosingIndex = *((DWORD *)row);
		row += 4;
	}
	else
	{
		enclosingIndex = *((USHORT *)row);
		row += 2;
	}

	wsprintf(lBuffer, L"Zagnieżdżona klasa: 0x%08X", nestedIndex);
	HTREEITEM treeRowItem = m_ctrlTableTree.InsertItem(lBuffer, tvitem);

	wsprintf(lBuffer, L"Otaczająca klasa: 0x%08X", enclosingIndex);
	m_ctrlTableTree.InsertItem(lBuffer, treeRowItem);
}

void CMetadataTablesPage::HandleNestedClass(const META_TABLE_ENTRY& t, CAssemblyView* pView, HTREEITEM tvitem)
{
	for(DWORD i = 0; i < t.Rows; ++i)
	{
		HandleSingleNestedClass(i, t, pView, tvitem);
	}
}
