use crate::errors::FileParseError;
use crate::field::Field;
use crate::pe::header::DataDirectoryEntry;
use crate::utils::{extract_u16, extract_u32};
pub const COR20_HEADER_SIZE: usize = 72;
pub const COMIMAGE_FLAGS_ILONLY: u32 = 0x0000_0001;
pub struct Cor20Header {
pub cb: Field<u32>,
pub major_runtime_version: Field<u16>,
pub minor_runtime_version: Field<u16>,
pub metadata: DataDirectoryEntry,
pub flags: Field<u32>,
pub entry_point_token: Field<u32>,
pub resources: DataDirectoryEntry,
pub strong_name_signature: DataDirectoryEntry,
pub code_manager_table: DataDirectoryEntry,
pub vtable_fixups: DataDirectoryEntry,
pub export_address_table_jumps: DataDirectoryEntry,
pub managed_native_header: DataDirectoryEntry,
}
impl Cor20Header {
pub fn parse(buffer: &[u8], offset: usize) -> Result<Self, FileParseError> {
let cb = extract_u32(buffer, offset)?;
if cb < COR20_HEADER_SIZE as u32 {
return Err(FileParseError::InvalidFileFormat);
}
if buffer.len() < offset + cb as usize {
return Err(FileParseError::BufferOverflow);
}
Ok(Cor20Header {
cb: Field::new(cb, offset, 4),
major_runtime_version: Field::new(extract_u16(buffer, offset + 4)?, offset + 4, 2),
minor_runtime_version: Field::new(extract_u16(buffer, offset + 6)?, offset + 6, 2),
metadata: DataDirectoryEntry::parse(buffer, offset + 8)?,
flags: Field::new(extract_u32(buffer, offset + 16)?, offset + 16, 4),
entry_point_token: Field::new(extract_u32(buffer, offset + 20)?, offset + 20, 4),
resources: DataDirectoryEntry::parse(buffer, offset + 24)?,
strong_name_signature: DataDirectoryEntry::parse(buffer, offset + 32)?,
code_manager_table: DataDirectoryEntry::parse(buffer, offset + 40)?,
vtable_fixups: DataDirectoryEntry::parse(buffer, offset + 48)?,
export_address_table_jumps: DataDirectoryEntry::parse(buffer, offset + 56)?,
managed_native_header: DataDirectoryEntry::parse(buffer, offset + 64)?,
})
}
pub fn is_il_only(&self) -> bool {
self.flags.value & COMIMAGE_FLAGS_ILONLY != 0
}
}