/*
* PERWAPI - An API for Reading and Writing PE Files
*
* Copyright (c) Diane Corney, Queensland University of Technology, 2004.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the PERWAPI Copyright as included with this
* distribution in the file PERWAPIcopyright.rtf.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY as is explained in the copyright notice.
*
* The author may be contacted at d.corney@qut.edu.au
*
* Version Date: 26/01/07
*/
using System;
using System.IO;
using System.Collections;
using System.Security.Cryptography;
namespace QUT.PERWAPI
{
/**************************************************************************/
public abstract class FileRef : MetaDataElement
{
protected static readonly uint HasMetaData = 0x0;
protected static readonly uint HasNoMetaData = 0x1;
protected uint nameIx = 0, hashIx = 0;
protected byte[] hashBytes;
protected string name;
protected bool entryPoint = false;
protected uint flags;
/*-------------------- Constructors ---------------------------------*/
internal FileRef(string name, byte[] hashBytes)
{
this.hashBytes = hashBytes;
this.name = name;
tabIx = MDTable.File;
}
internal FileRef(PEReader buff)
{
flags = buff.ReadUInt32();
name = buff.GetString();
hashBytes = buff.GetBlob();
tabIx = MDTable.File;
}
internal static void Read(PEReader buff, TableRow[] files)
{
for (int i = 0; i < files.Length; i++)
{
uint flags = buff.ReadUInt32();
if (flags == HasMetaData)
files[i] = new ModuleFile(buff.GetString(), buff.GetBlob());
else
files[i] = new ResourceFile(buff.GetString(), buff.GetBlob());
}
}
public string Name() { return name; }
public byte[] GetHash() { return hashBytes; }
internal sealed override void BuildTables(MetaDataOut md)
{
md.AddToTable(MDTable.File, this);
nameIx = md.AddToStringsHeap(name);
hashIx = md.AddToBlobHeap(hashBytes);
if (entryPoint) md.SetEntryPoint(this);
}
internal static uint Size(MetaData md)
{
return 4 + md.StringsIndexSize() + md.BlobIndexSize();
}
internal sealed override void Write(PEWriter output)
{
output.Write(flags);
output.StringsIndex(nameIx);
output.BlobIndex(hashIx);
}
internal sealed override uint GetCodedIx(CIx code)
{
switch (code)
{
case (CIx.HasCustomAttr): return 16;
case (CIx.Implementation): return 0;
}
return 0;
}
}
/**************************************************************************/
///
/// Descriptor for a file referenced in THIS assembly/module (.file)
///
internal class ModuleFile : FileRef
{
internal ModuleRef fileModule;
internal ModuleFile(string name, byte[] hashBytes, bool entryPoint)
: base(name, hashBytes)
{
flags = HasMetaData;
this.entryPoint = entryPoint;
}
internal ModuleFile(string name, byte[] hashBytes)
: base(name, hashBytes)
{
flags = HasMetaData;
}
internal void SetEntryPoint() { entryPoint = true; }
internal void SetHash(byte[] hashVal) { hashBytes = hashVal; }
}
/**************************************************************************/
///
/// Descriptor for a file containing a managed resource
///
public class ResourceFile : FileRef
{
static ArrayList files = new ArrayList();
/*-------------------- Constructors ---------------------------------*/
public ResourceFile(string name, byte[] hashValue)
: base(name, hashValue)
{
flags = HasNoMetaData;
files.Add(this);
}
public static ResourceFile GetFile(string name)
{
for (int i = 0; i < files.Count; i++)
{
if (((ResourceFile)files[i]).name.Equals(name))
return (ResourceFile)files[i];
}
return null;
}
}
}