usecrate::endian::{LittleEndian as LE, U16Bytes}; usecrate::pe; usecrate::read::{ReadError, ReadRef, Result};
/// The `.rsrc` section of a PE file. /// /// Returned by [`DataDirectories::resource_directory`](super::DataDirectories::resource_directory). #[derive(Debug, Clone, Copy)] pubstruct ResourceDirectory<'data> {
data: &'data [u8],
}
impl<'data> ResourceDirectory<'data> { /// Construct from the data of the `.rsrc` section. pubfn new(data: &'data [u8]) -> Self {
ResourceDirectory { data }
}
/// A table of resource entries. #[derive(Debug, Clone)] pubstruct ResourceDirectoryTable<'data> { /// The table header. pub header: &'data pe::ImageResourceDirectory, /// The table entries. pub entries: &'data [pe::ImageResourceDirectoryEntry],
}
impl<'data> ResourceDirectoryTable<'data> { fn parse(data: &'data [u8], offset: u32) -> Result<Self> { letmut offset = u64::from(offset); let header = data
.read::<pe::ImageResourceDirectory>(&mut offset)
.read_error("Invalid resource table header")?; let entries_count = header.number_of_id_entries.get(LE) as usize
+ header.number_of_named_entries.get(LE) as usize; let entries = data
.read_slice::<pe::ImageResourceDirectoryEntry>(&mut offset, entries_count)
.read_error("Invalid resource table entries")?;
Ok(Self { header, entries })
}
}
impl pe::ImageResourceDirectoryEntry { /// Returns true if the entry has a name, rather than an ID. pubfn has_name(&self) -> bool { self.name_or_id.get(LE) & pe::IMAGE_RESOURCE_NAME_IS_STRING != 0
}
/// Returns the section offset of the name. /// /// Valid if `has_name()` returns true. fn name(&self) -> ResourceName { let offset = self.name_or_id.get(LE) & !pe::IMAGE_RESOURCE_NAME_IS_STRING;
ResourceName { offset }
}
/// Returns the ID. /// /// Valid if `has_string_name()` returns false. fn id(&self) -> u16 {
(self.name_or_id.get(LE) & 0x0000_FFFF) as u16
}
/// Returns the entry name pubfn name_or_id(&self) -> ResourceNameOrId { ifself.has_name() {
ResourceNameOrId::Name(self.name())
} else {
ResourceNameOrId::Id(self.id())
}
}
/// Returns true if the entry is a subtable. pubfn is_table(&self) -> bool { self.offset_to_data_or_directory.get(LE) & pe::IMAGE_RESOURCE_DATA_IS_DIRECTORY != 0
}
/// Returns the section offset of the associated table or data. pubfn data_offset(&self) -> u32 { self.offset_to_data_or_directory.get(LE) & !pe::IMAGE_RESOURCE_DATA_IS_DIRECTORY
}
/// Returns the data associated to this directory entry. pubfn data<'data>(
&self,
section: ResourceDirectory<'data>,
) -> Result<ResourceDirectoryEntryData<'data>> { ifself.is_table() {
ResourceDirectoryTable::parse(section.data, self.data_offset())
.map(ResourceDirectoryEntryData::Table)
} else {
section
.data
.read_at::<pe::ImageResourceDataEntry>(self.data_offset().into())
.read_error("Invalid resource entry")
.map(ResourceDirectoryEntryData::Data)
}
}
}
/// Data associated with a resource directory entry. #[derive(Debug, Clone)] pubenum ResourceDirectoryEntryData<'data> { /// A subtable entry.
Table(ResourceDirectoryTable<'data>), /// A resource data entry.
Data(&'data pe::ImageResourceDataEntry),
}
impl<'data> ResourceDirectoryEntryData<'data> { /// Converts to an option of table. /// /// Helper for iterator filtering. pubfn table(self) -> Option<ResourceDirectoryTable<'data>> { matchself { Self::Table(dir) => Some(dir),
_ => None,
}
}
/// Converts to an option of data entry. /// /// Helper for iterator filtering. pubfn data(self) -> Option<&'data pe::ImageResourceDataEntry> { matchself { Self::Data(rsc) => Some(rsc),
_ => None,
}
}
}
impl ResourceName { /// Converts to a `String`. pubfn to_string_lossy(&self, directory: ResourceDirectory<'_>) -> Result<String> { let d = self.data(directory)?.iter().map(|c| c.get(LE));
/// Returns the string unicode buffer. pubfn data<'data>(
&self,
directory: ResourceDirectory<'data>,
) -> Result<&'data [U16Bytes<LE>]> { letmut offset = u64::from(self.offset); let len = directory
.data
.read::<U16Bytes<LE>>(&mut offset)
.read_error("Invalid resource name offset")?;
directory
.data
.read_slice::<U16Bytes<LE>>(&mut offset, len.get(LE).into())
.read_error("Invalid resource name length")
}
/// Returns the string buffer as raw bytes. pubfn raw_data<'data>(&self, directory: ResourceDirectory<'data>) -> Result<&'data [u8]> { self.data(directory).map(crate::pod::bytes_of_slice)
}
}
/// A resource name or ID. /// /// Can be either a string or a numeric ID. #[derive(Debug)] pubenum ResourceNameOrId { /// A resource name.
Name(ResourceName), /// A resource ID.
Id(u16),
}
impl ResourceNameOrId { /// Converts to an option of name. /// /// Helper for iterator filtering. pubfn name(self) -> Option<ResourceName> { matchself { Self::Name(name) => Some(name),
_ => None,
}
}
/// Converts to an option of ID. /// /// Helper for iterator filtering. pubfn id(self) -> Option<u16> { matchself { Self::Id(id) => Some(id),
_ => None,
}
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.25 Sekunden
(vorverarbeitet am 2026-06-18)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.