LCOV - code coverage report
Current view: top level - src/pe - resources.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 21.8 % 560 122
Test Date: 2026-04-12:00:00:00 Functions: 19.3 % 135 26

            Line data    Source code
       1              : //! This module contains the different structures involved in the PE's resource tree
       2              : //!
       3              : //! One can access this tree using either: [`crate::pe::Binary::resources`] or by parsing raw bytes
       4              : //! with [`Node::from_slice`]. The [`Manager`] provides a logical API over the resource tree
       5              : //! to access specifics parts of the tree.
       6              : 
       7              : use lief_ffi as ffi;
       8              : 
       9              : use std::pin::Pin;
      10              : use std::{fmt, marker::PhantomData};
      11              : 
      12              : use crate::common::into_optional;
      13              : use crate::to_slice;
      14              : use crate::{common::FromFFI, declare_iterator};
      15              : 
      16              : /// This enum represents a node in the resource tree which can be either: a **directory** node
      17              : /// or a data (leaf) node.
      18          598 : #[derive(Debug)]
      19              : pub enum Node<'a> {
      20              :     /// A *data* node (i.e. a leaf)
      21              :     Data(Data<'a>),
      22              :     /// A directory node
      23              :     Directory(Directory<'a>),
      24              : }
      25              : 
      26              : impl Node<'_> {
      27              :     /// Parse a resource tree from the provided slice. The original RVA must be provided
      28              :     /// to resolve the content of the data nodes.
      29          130 :     pub fn from_slice(content: &[u8], rva: u64) -> Option<Node<'_>> {
      30          130 :         unsafe {
      31          130 :             let ptr = ffi::PE_ResourceNode::from_slice(content.as_ptr(), content.len(), rva);
      32          130 :             if ptr.is_null() {
      33            0 :                 return None;
      34          130 :             }
      35          130 :             Some(Node::from_ffi(ptr))
      36              :         }
      37          130 :     }
      38              : }
      39              : 
      40              : /// Trait that is shared by both [`Node::Data`] and [`Node::Directory`].
      41              : pub trait NodeBase {
      42              :     #[doc(hidden)]
      43              :     fn get_base(&self) -> &ffi::PE_ResourceNode;
      44              : 
      45              :     #[doc(hidden)]
      46              :     fn base_as_pin_mut(&mut self) -> Pin<&mut ffi::PE_ResourceNode>;
      47              : 
      48              :     /// Integer that identifies the Type, Name, or Language ID of the entry
      49              :     /// depending on its [`NodeBase::depth`] in the tree
      50         2626 :     fn id(&self) -> u32 {
      51         2626 :         self.get_base().id()
      52         2626 :     }
      53              : 
      54              :     /// Current depth of the Node in the resource tree
      55          468 :     fn depth(&self) -> u32 {
      56          468 :         self.get_base().depth()
      57          468 :     }
      58              : 
      59              :     /// Iterator on node's children
      60         2678 :     fn children(&self) -> Children<'_> {
      61         2678 :         Children::new(self.get_base().childs())
      62         2678 :     }
      63              : 
      64              :     /// Name of the node (if any)
      65            0 :     fn name(&self) -> Option<String> {
      66            0 :         if !self.get_base().has_name() {
      67            0 :             return None;
      68            0 :         }
      69            0 :         Some(self.get_base().name().to_string())
      70            0 :     }
      71              : 
      72              :     /// Add a new child node to the current and return the newly-added node
      73            0 :     fn add_child(&mut self, node: &Node) -> Node<'_> {
      74            0 :         Node::from_ffi(self.base_as_pin_mut().add_child(node.get_base()))
      75            0 :     }
      76              : 
      77              :     /// Delete the child node with the given id
      78            0 :     fn delete_child(&mut self, id: u32) {
      79            0 :         self.base_as_pin_mut().delete_child(id);
      80            0 :     }
      81              : }
      82              : 
      83              : impl std::fmt::Debug for &dyn NodeBase {
      84         2626 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      85         2626 :         f.debug_struct("NodeBase").field("id", &self.id()).finish()
      86         2626 :     }
      87              : }
      88              : 
      89              : impl std::fmt::Display for &dyn NodeBase {
      90            0 :     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
      91            0 :         write!(f, "{}", self.get_base().print())
      92            0 :     }
      93              : }
      94              : 
      95              : impl<'a> FromFFI<ffi::PE_ResourceNode> for Node<'a> {
      96         5304 :     fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::PE_ResourceNode>) -> Self {
      97         5304 :         unsafe {
      98         5304 :             let cmd_ref = ffi_entry.as_ref().unwrap();
      99         5304 : 
     100         5304 :             if ffi::PE_ResourceDirectory::classof(cmd_ref) {
     101         3276 :                 let raw = {
     102         3276 :                     type From = cxx::UniquePtr<ffi::PE_ResourceNode>;
     103         3276 :                     type To = cxx::UniquePtr<ffi::PE_ResourceDirectory>;
     104         3276 :                     std::mem::transmute::<From, To>(ffi_entry)
     105         3276 :                 };
     106         3276 :                 Node::Directory(Directory::from_ffi(raw))
     107              :             } else {
     108         2028 :                 assert!(
     109         2028 :                     ffi::PE_ResourceData::classof(cmd_ref),
     110            0 :                     "Must be a ResourceData node"
     111              :                 );
     112              : 
     113         2028 :                 let raw = {
     114         2028 :                     type From = cxx::UniquePtr<ffi::PE_ResourceNode>;
     115         2028 :                     type To = cxx::UniquePtr<ffi::PE_ResourceData>;
     116         2028 :                     std::mem::transmute::<From, To>(ffi_entry)
     117         2028 :                 };
     118         2028 :                 Node::Data(Data::from_ffi(raw))
     119              :             }
     120              :         }
     121         5304 :     }
     122              : }
     123              : 
     124              : pub struct Data<'a> {
     125              :     ptr: cxx::UniquePtr<ffi::PE_ResourceData>,
     126              :     _owner: PhantomData<&'a Node<'a>>,
     127              : }
     128              : 
     129              : impl Data<'_> {
     130              :     /// Create a new Data node with the provided payload
     131            0 :     pub fn with_buffer(buffer: &[u8]) -> Data<'static> {
     132            0 :         unsafe {
     133            0 :             Data::from_ffi(ffi::PE_ResourceData::create_from_data(
     134            0 :                 buffer.as_ptr(),
     135            0 :                 buffer.len(),
     136            0 :             ))
     137            0 :         }
     138            0 :     }
     139              : 
     140              :     /// Create a new Data node
     141            0 :     pub fn new() -> Data<'static> {
     142            0 :         Data::from_ffi(ffi::PE_ResourceData::create())
     143            0 :     }
     144              : 
     145              :     /// Return the code page that is used to decode code point
     146              :     /// values within the resource data. Typically, the code page is the unicode code page.
     147         2028 :     pub fn code_page(&self) -> u32 {
     148         2028 :         self.ptr.code_page()
     149         2028 :     }
     150              : 
     151              :     /// Reserved value. Should be `0`
     152         2028 :     pub fn reserved(&self) -> u32 {
     153         2028 :         self.ptr.reserved()
     154         2028 :     }
     155              : 
     156              :     /// Offset of the content within the resource
     157              :     ///
     158              :     /// <div class="warning">this value may change when rebuilding resource table</div>
     159         2028 :     pub fn offset(&self) -> u32 {
     160         2028 :         self.ptr.offset()
     161         2028 :     }
     162              : 
     163              :     /// Resource content
     164         2028 :     pub fn content(&self) -> &[u8] {
     165         2028 :         to_slice!(self.ptr.content());
     166         2028 :     }
     167              : 
     168              :     /// Change or set the raw data associated with this node
     169            0 :     pub fn set_content(&mut self, content: &[u8]) -> &mut Self {
     170            0 :         unsafe {
     171            0 :             self.ptr
     172            0 :                 .pin_mut()
     173            0 :                 .set_content(content.as_ptr(), content.len());
     174            0 :         }
     175            0 :         self
     176            0 :     }
     177              : 
     178              :     /// Change or set the code page
     179            0 :     pub fn set_code_page(&mut self, code_page: u32) -> &mut Self {
     180            0 :         self.ptr.pin_mut().set_code_page(code_page);
     181            0 :         self
     182            0 :     }
     183              : 
     184              :     /// Change or set the *reserved* field
     185            0 :     pub fn set_reserved(&mut self, reserved: u32) -> &mut Self {
     186            0 :         self.ptr.pin_mut().set_reserved(reserved);
     187            0 :         self
     188            0 :     }
     189              : }
     190              : 
     191              : impl NodeBase for Data<'_> {
     192         2028 :     fn get_base(&self) -> &ffi::PE_ResourceNode {
     193         2028 :         self.ptr.as_ref().unwrap().as_ref()
     194         2028 :     }
     195              : 
     196            0 :     fn base_as_pin_mut(&mut self) -> Pin<&mut ffi::PE_ResourceNode> {
     197            0 :         unsafe {
     198            0 :             Pin::new_unchecked({
     199            0 :                 (self.ptr.as_ref().unwrap().as_ref() as *const ffi::PE_ResourceNode
     200            0 :                     as *mut ffi::PE_ResourceNode)
     201            0 :                     .as_mut()
     202            0 :                     .unwrap()
     203            0 :             })
     204            0 :         }
     205            0 :     }
     206              : }
     207              : 
     208              : impl fmt::Debug for Data<'_> {
     209         2028 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     210         2028 :         let base = self as &dyn NodeBase;
     211         2028 :         f.debug_struct("Data")
     212         2028 :             .field("base", &base)
     213         2028 :             .field("code_page", &self.code_page())
     214         2028 :             .field("reserved", &self.reserved())
     215         2028 :             .field("offset", &self.offset())
     216         2028 :             .finish()
     217         2028 :     }
     218              : }
     219              : 
     220              : impl<'a> FromFFI<ffi::PE_ResourceData> for Data<'a> {
     221         2028 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourceData>) -> Self {
     222         2028 :         Self {
     223         2028 :             ptr,
     224         2028 :             _owner: PhantomData,
     225         2028 :         }
     226         2028 :     }
     227              : }
     228              : 
     229              : pub struct Directory<'a> {
     230              :     ptr: cxx::UniquePtr<ffi::PE_ResourceDirectory>,
     231              :     _owner: PhantomData<&'a Node<'a>>,
     232              : }
     233              : 
     234              : impl Directory<'_> {
     235              :     /// Create a new Directory node with the given d
     236            0 :     pub fn with_id(id: u32) -> Directory<'static> {
     237            0 :         Directory::from_ffi(ffi::PE_ResourceDirectory::create_from_id(id))
     238            0 :     }
     239              : 
     240              :     /// Create a new Directory node
     241            0 :     pub fn new() -> Directory<'static> {
     242            0 :         Directory::from_ffi(ffi::PE_ResourceDirectory::create())
     243            0 :     }
     244              : 
     245              :     /// Resource characteristics. This field is reserved for future use.
     246              :     /// It is currently set to zero.
     247          598 :     pub fn characteristics(&self) -> u32 {
     248          598 :         self.ptr.characteristics()
     249          598 :     }
     250              : 
     251              :     /// The time that the resource data was created by the
     252              :     /// resource compiler.
     253          598 :     pub fn time_date_stamp(&self) -> u32 {
     254          598 :         self.ptr.time_date_stamp()
     255          598 :     }
     256              : 
     257              :     /// The major version number, set by the user.
     258          598 :     pub fn major_version(&self) -> u32 {
     259          598 :         self.ptr.major_version()
     260          598 :     }
     261              : 
     262              :     /// The minor version number, set by the user.
     263          598 :     pub fn minor_version(&self) -> u32 {
     264          598 :         self.ptr.minor_version()
     265          598 :     }
     266              : 
     267              :     /// The number of directory entries immediately
     268              :     /// following the table that use strings to identify Type,
     269              :     /// Name, or Language entries (depending on the level of the table).
     270          598 :     pub fn numberof_name_entries(&self) -> u32 {
     271          598 :         self.ptr.numberof_name_entries()
     272          598 :     }
     273              : 
     274              :     /// The number of directory entries immediately
     275              :     /// following the Name entries that use numeric IDs for
     276              :     /// Type, Name, or Language entries.
     277          598 :     pub fn numberof_id_entries(&self) -> u32 {
     278          598 :         self.ptr.numberof_id_entries()
     279          598 :     }
     280              : }
     281              : 
     282              : impl NodeBase for Directory<'_> {
     283         3744 :     fn get_base(&self) -> &ffi::PE_ResourceNode {
     284         3744 :         self.ptr.as_ref().unwrap().as_ref()
     285         3744 :     }
     286              : 
     287            0 :     fn base_as_pin_mut(&mut self) -> Pin<&mut ffi::PE_ResourceNode> {
     288            0 :         unsafe {
     289            0 :             Pin::new_unchecked({
     290            0 :                 (self.ptr.as_ref().unwrap().as_ref() as *const ffi::PE_ResourceNode
     291            0 :                     as *mut ffi::PE_ResourceNode)
     292            0 :                     .as_mut()
     293            0 :                     .unwrap()
     294            0 :             })
     295            0 :         }
     296            0 :     }
     297              : }
     298              : 
     299              : impl NodeBase for Node<'_> {
     300            0 :     fn get_base(&self) -> &ffi::PE_ResourceNode {
     301            0 :         match &self {
     302            0 :             Node::Data(n) => n.get_base(),
     303            0 :             Node::Directory(n) => n.get_base(),
     304              :         }
     305            0 :     }
     306              : 
     307            0 :     fn base_as_pin_mut(&mut self) -> Pin<&mut ffi::PE_ResourceNode> {
     308            0 :         match self {
     309            0 :             Node::Data(n) => n.base_as_pin_mut(),
     310            0 :             Node::Directory(n) => n.base_as_pin_mut(),
     311              :         }
     312            0 :     }
     313              : }
     314              : 
     315              : impl fmt::Debug for Directory<'_> {
     316          598 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     317          598 :         let base = self as &dyn NodeBase;
     318          598 :         f.debug_struct("Directory")
     319          598 :             .field("base", &base)
     320          598 :             .field("characteristics", &self.characteristics())
     321          598 :             .field("time_date_stamp", &self.time_date_stamp())
     322          598 :             .field("major_version", &self.major_version())
     323          598 :             .field("minor_version", &self.minor_version())
     324          598 :             .field("numberof_name_entries", &self.numberof_name_entries())
     325          598 :             .field("numberof_id_entries", &self.numberof_id_entries())
     326          598 :             .finish()
     327          598 :     }
     328              : }
     329              : 
     330              : impl<'a> FromFFI<ffi::PE_ResourceDirectory> for Directory<'a> {
     331         3276 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourceDirectory>) -> Self {
     332         3276 :         Self {
     333         3276 :             ptr,
     334         3276 :             _owner: PhantomData,
     335         3276 :         }
     336         3276 :     }
     337              : }
     338              : 
     339              : /// This manager abstracts the tree representation to provide a comprehensive API over
     340              : /// the information wrapped by the resources tree.
     341              : pub struct Manager<'a> {
     342              :     ptr: cxx::UniquePtr<ffi::PE_ResourcesManager>,
     343              :     _owner: PhantomData<&'a Node<'a>>,
     344              : }
     345              : 
     346              : impl<'a> FromFFI<ffi::PE_ResourcesManager> for Manager<'a> {
     347          130 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourcesManager>) -> Self {
     348          130 :         Self {
     349          130 :             ptr,
     350          130 :             _owner: PhantomData,
     351          130 :         }
     352          130 :     }
     353              : }
     354              : 
     355              : #[allow(non_camel_case_types)]
     356            0 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
     357              : pub enum Types {
     358              :     CURSOR,
     359              :     BITMAP,
     360              :     ICON,
     361              :     MENU,
     362              :     DIALOG,
     363              :     STRING,
     364              :     FONTDIR,
     365              :     FONT,
     366              :     ACCELERATOR,
     367              :     RCDATA,
     368              :     MESSAGETABLE,
     369              :     GROUP_CURSOR,
     370              :     GROUP_ICON,
     371              :     VERSION,
     372              :     DLGINCLUDE,
     373              :     PLUGPLAY,
     374              :     VXD,
     375              :     ANICURSOR,
     376              :     ANIICON,
     377              :     HTML,
     378              :     MANIFEST,
     379              :     UNKNOWN(u32),
     380              : }
     381              : 
     382              : impl From<u32> for Types {
     383            0 :     fn from(value: u32) -> Self {
     384            0 :         match value {
     385            0 :             0x00000001 => Types::CURSOR,
     386            0 :             0x00000002 => Types::BITMAP,
     387            0 :             0x00000003 => Types::ICON,
     388            0 :             0x00000004 => Types::MENU,
     389            0 :             0x00000005 => Types::DIALOG,
     390            0 :             0x00000006 => Types::STRING,
     391            0 :             0x00000007 => Types::FONTDIR,
     392            0 :             0x00000008 => Types::FONT,
     393            0 :             0x00000009 => Types::ACCELERATOR,
     394            0 :             0x0000000a => Types::RCDATA,
     395            0 :             0x0000000b => Types::MESSAGETABLE,
     396            0 :             0x0000000c => Types::GROUP_CURSOR,
     397            0 :             0x0000000e => Types::GROUP_ICON,
     398            0 :             0x00000010 => Types::VERSION,
     399            0 :             0x00000011 => Types::DLGINCLUDE,
     400            0 :             0x00000013 => Types::PLUGPLAY,
     401            0 :             0x00000014 => Types::VXD,
     402            0 :             0x00000015 => Types::ANICURSOR,
     403            0 :             0x00000016 => Types::ANIICON,
     404            0 :             0x00000017 => Types::HTML,
     405            0 :             0x00000018 => Types::MANIFEST,
     406            0 :             _ => Types::UNKNOWN(value),
     407              :         }
     408            0 :     }
     409              : }
     410              : impl From<Types> for u32 {
     411            0 :     fn from(value: Types) -> u32 {
     412            0 :         match value {
     413            0 :             Types::CURSOR => 0x00000001,
     414            0 :             Types::BITMAP => 0x00000002,
     415            0 :             Types::ICON => 0x00000003,
     416            0 :             Types::MENU => 0x00000004,
     417            0 :             Types::DIALOG => 0x00000005,
     418            0 :             Types::STRING => 0x00000006,
     419            0 :             Types::FONTDIR => 0x00000007,
     420            0 :             Types::FONT => 0x00000008,
     421            0 :             Types::ACCELERATOR => 0x00000009,
     422            0 :             Types::RCDATA => 0x0000000a,
     423            0 :             Types::MESSAGETABLE => 0x0000000b,
     424            0 :             Types::GROUP_CURSOR => 0x0000000c,
     425            0 :             Types::GROUP_ICON => 0x0000000e,
     426            0 :             Types::VERSION => 0x00000010,
     427            0 :             Types::DLGINCLUDE => 0x00000011,
     428            0 :             Types::PLUGPLAY => 0x00000013,
     429            0 :             Types::VXD => 0x00000014,
     430            0 :             Types::ANICURSOR => 0x00000015,
     431            0 :             Types::ANIICON => 0x00000016,
     432            0 :             Types::HTML => 0x00000017,
     433            0 :             Types::MANIFEST => 0x00000018,
     434            0 :             Types::UNKNOWN(value) => value,
     435              :         }
     436            0 :     }
     437              : }
     438              : 
     439              : impl Manager<'_> {
     440              :     /// Return the manifest as a string. This manifest matches the node associated with
     441              :     /// the type: [`Types::MANIFEST`].
     442            0 :     pub fn manifest(&self) -> String {
     443            0 :         self.ptr.manifest().to_string()
     444            0 :     }
     445              : 
     446              :     /// Change or set the manifest. If the manifest node path does not exist,
     447              :     /// all required nodes are created.
     448            0 :     pub fn set_manifest(&mut self, content: &str) {
     449            0 :         self.ptr.pin_mut().set_manifest(content);
     450            0 :     }
     451              : 
     452              :     /// Try to find the node associated with the given [`Types`]
     453              :     ///
     454              :     /// This type corresponds to the [`Node::id`] at the **level 1** of the
     455              :     /// resource tree.
     456            0 :     pub fn find_by_type(&self, res_type: Types) -> Option<Node<'_>> {
     457            0 :         into_optional(self.ptr.find_node_type(res_type.into()))
     458            0 :     }
     459              : 
     460              :     /// Return the list of [`Types`] exposed by the resource tree.
     461            0 :     pub fn types(&self) -> Vec<Types> {
     462            0 :         self.ptr
     463            0 :             .get_types()
     464            0 :             .iter()
     465            0 :             .map(|v| Types::from(*v))
     466            0 :             .collect()
     467            0 :     }
     468              : 
     469              :     /// Return the HTML resources as a list of strings
     470            0 :     pub fn html(&self) -> Vec<String> {
     471            0 :         self.ptr.html().iter().map(|s| s.to_string()).collect()
     472            0 :     }
     473              : 
     474              :     /// Return an iterator over the resource icons
     475            0 :     pub fn icons(&self) -> Icons<'_> {
     476            0 :         Icons::new(self.ptr.icons())
     477            0 :     }
     478              : 
     479              :     /// Return an iterator over the resource version entries
     480            0 :     pub fn version(&self) -> Versions<'_> {
     481            0 :         Versions::new(self.ptr.version())
     482            0 :     }
     483              : 
     484              :     /// Return an iterator over the resource accelerator entries
     485            0 :     pub fn accelerator(&self) -> Accelerators<'_> {
     486            0 :         Accelerators::new(self.ptr.accelerator())
     487            0 :     }
     488              : 
     489              :     /// Return an iterator over the string table entries
     490            0 :     pub fn string_table(&self) -> StringTableEntries<'_> {
     491            0 :         StringTableEntries::new(self.ptr.string_table())
     492            0 :     }
     493              : 
     494              :     /// Print the current resources a tree in a pretty representation.
     495              :     ///
     496              :     /// ```text
     497              :     /// │  ├── Directory ID: 0016 (0x0010) type: VERSION
     498              :     /// │  │  └── Directory ID: 0001 (0x0001)
     499              :     /// │  │      └── Data ID: 1033 (0x0409) [...]
     500              :     /// │  │          ├── Hex: c0:03:34:00:00:00:[...]
     501              :     /// │  │          └── Str: ..4...V.S._.V.E.R.S.
     502              :     /// │  └── Directory ID: 0024 (0x0018) type: MANIFEST
     503              :     /// │      └── Directory ID: 0001 (0x0001)
     504              :     /// │          └── Data ID: 1033 (0x0409) [...]
     505              :     /// │              ├── Hex: 3c:3f:78:6d:6c:20:[...]
     506              :     /// │              └── Str: <?xml version="1.0"
     507              :     /// ```
     508            0 :     pub fn print_tree(&self) -> String {
     509            0 :         self.ptr.print_tree().to_string()
     510            0 :     }
     511              : 
     512              :     /// Same as [`Manager::print_tree`] but with a maximal depth provided in the
     513              :     /// first parameter.
     514            0 :     pub fn print_tree_with_depth(&self, depth: u32) -> String {
     515            0 :         self.ptr.print_tree_with_depth(depth).to_string()
     516            0 :     }
     517              : }
     518              : 
     519              : /// Represents a PE icon resource
     520              : pub struct Icon<'a> {
     521              :     ptr: cxx::UniquePtr<ffi::PE_ResourceIcon>,
     522              :     _owner: PhantomData<&'a ffi::PE_ResourcesManager>,
     523              : }
     524              : 
     525              : impl Icon<'_> {
     526              :     /// ID of the icon
     527            0 :     pub fn id(&self) -> u32 {
     528            0 :         self.ptr.id()
     529            0 :     }
     530              : 
     531              :     /// Language of the icon
     532            0 :     pub fn lang(&self) -> u32 {
     533            0 :         self.ptr.lang()
     534            0 :     }
     535              : 
     536              :     /// Sublanguage of the icon
     537            0 :     pub fn sublang(&self) -> u32 {
     538            0 :         self.ptr.sublang()
     539            0 :     }
     540              : 
     541              :     /// Width in pixels
     542            0 :     pub fn width(&self) -> u8 {
     543            0 :         self.ptr.width()
     544            0 :     }
     545              : 
     546              :     /// Height in pixels
     547            0 :     pub fn height(&self) -> u8 {
     548            0 :         self.ptr.height()
     549            0 :     }
     550              : 
     551              :     /// Number of colors in the palette (0 if more than 256)
     552            0 :     pub fn color_count(&self) -> u8 {
     553            0 :         self.ptr.color_count()
     554            0 :     }
     555              : 
     556              :     /// Reserved (should be 0)
     557            0 :     pub fn reserved(&self) -> u8 {
     558            0 :         self.ptr.reserved()
     559            0 :     }
     560              : 
     561              :     /// Number of color planes
     562            0 :     pub fn planes(&self) -> u16 {
     563            0 :         self.ptr.planes()
     564            0 :     }
     565              : 
     566              :     /// Bits per pixel
     567            0 :     pub fn bit_count(&self) -> u16 {
     568            0 :         self.ptr.bit_count()
     569            0 :     }
     570              : 
     571              :     /// Size of the icon pixel data
     572            0 :     pub fn size(&self) -> u32 {
     573            0 :         self.ptr.size()
     574            0 :     }
     575              : 
     576              :     /// Raw pixel data of the icon
     577            0 :     pub fn pixels(&self) -> &[u8] {
     578            0 :         to_slice!(self.ptr.pixels());
     579            0 :     }
     580              : }
     581              : 
     582              : impl fmt::Debug for Icon<'_> {
     583            0 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     584            0 :         f.debug_struct("Icon")
     585            0 :             .field("id", &self.id())
     586            0 :             .field("width", &self.width())
     587            0 :             .field("height", &self.height())
     588            0 :             .field("color_count", &self.color_count())
     589            0 :             .field("bit_count", &self.bit_count())
     590            0 :             .finish()
     591            0 :     }
     592              : }
     593              : 
     594              : impl<'a> FromFFI<ffi::PE_ResourceIcon> for Icon<'a> {
     595            0 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourceIcon>) -> Self {
     596            0 :         Self {
     597            0 :             ptr,
     598            0 :             _owner: PhantomData,
     599            0 :         }
     600            0 :     }
     601              : }
     602              : 
     603              : /// Represents fixed file information from a version resource
     604            0 : #[derive(Debug, Clone)]
     605              : pub struct FixedFileInfo {
     606              :     /// Contains the value `0xFEEF04BD`. This is used with the `szKey` member of
     607              :     /// the `VS_VERSIONINFO` structure when searching a file for the
     608              :     /// `VS_FIXEDFILEINFO` structure.
     609              :     pub signature: u32,
     610              : 
     611              :     /// The binary version number of this structure. The high-order word of
     612              :     /// this member contains the major version number, and the low-order word
     613              :     /// contains the minor version number.
     614              :     pub struct_version: u32,
     615              : 
     616              :     /// The most significant 32 bits of the file's binary version number.
     617              :     /// This member is used with file_version_ls to form a 64-bit value used
     618              :     /// for numeric comparisons.
     619              :     pub file_version_ms: u32,
     620              : 
     621              :     /// The least significant 32 bits of the file's binary version number.
     622              :     /// This member is used with file_version_ms to form a 64-bit value used for
     623              :     /// numeric comparisons.
     624              :     pub file_version_ls: u32,
     625              : 
     626              :     /// The most significant 32 bits of the binary version number of the product
     627              :     /// with which this file was distributed. This member is used with
     628              :     /// product_version_ls to form a 64-bit value used for numeric comparisons.
     629              :     pub product_version_ms: u32,
     630              : 
     631              :     /// The least significant 32 bits of the binary version number of the product
     632              :     /// with which this file was distributed. This member is used with
     633              :     /// product_version_ms to form a 64-bit value used for numeric comparisons.
     634              :     pub product_version_ls: u32,
     635              : 
     636              :     /// Contains a bitmask that specifies the valid bits in file_flags.
     637              :     /// A bit is valid only if it was defined when the file was created.
     638              :     pub file_flags_mask: u32,
     639              : 
     640              :     /// Contains a bitmask that specifies the Boolean attributes of the file.
     641              :     /// This member can include one or more of the values specified in FILE_FLAGS
     642              :     pub file_flags: u32,
     643              : 
     644              :     /// The operating system for which this file was designed. This member can
     645              :     /// be one of the values specified in VERSION_OS.
     646              :     pub file_os: u32,
     647              : 
     648              :     /// The general type of file. This member can be one of the values specified
     649              :     /// in FILE_TYPE. All other values are reserved.
     650              :     pub file_type: u32,
     651              : 
     652              :     /// The function of the file. The possible values depend on the value of
     653              :     /// file_type.
     654              :     pub file_subtype: u32,
     655              : 
     656              :     /// The most significant 32 bits of the file's 64-bit binary creation date
     657              :     /// and time stamp.
     658              :     pub file_date_ms: u32,
     659              : 
     660              :     /// The least significant 32 bits of the file's 64-bit binary creation date
     661              :     /// and time stamp.
     662              :     pub file_date_ls: u32,
     663              : }
     664              : 
     665              : /// Represents a string table entry (key/value) from a StringFileInfo
     666            0 : #[derive(Debug, Clone)]
     667              : pub struct VersionStringTableEntry {
     668              :     /// Key of the entry
     669              :     pub key: String,
     670              :     /// Value of the entry
     671              :     pub value: String,
     672              : }
     673              : 
     674              : impl FromFFI<ffi::PE_ResourceStringTable_entry_t> for VersionStringTableEntry {
     675            0 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourceStringTable_entry_t>) -> Self {
     676            0 :         Self {
     677            0 :             key: ptr.key().to_string(),
     678            0 :             value: ptr.value().to_string(),
     679            0 :         }
     680            0 :     }
     681              : }
     682              : 
     683              : /// Represents a string table within a StringFileInfo
     684              : pub struct VersionStringTable<'a> {
     685              :     ptr: cxx::UniquePtr<ffi::PE_ResourceStringTable>,
     686              :     _owner: PhantomData<&'a ffi::PE_ResourceVersion>,
     687              : }
     688              : 
     689              : impl VersionStringTable<'_> {
     690              :     /// Type of the string table
     691            0 :     pub fn get_type(&self) -> u16 {
     692            0 :         self.ptr.get_type()
     693            0 :     }
     694              : 
     695              :     /// Key identifying the string table (typically a language/codepage pair)
     696            0 :     pub fn key(&self) -> String {
     697            0 :         self.ptr.key().to_string()
     698            0 :     }
     699              : 
     700              :     /// Return an iterator over the key/value entries
     701            0 :     pub fn entries(&self) -> VersionStringTableEntries<'_> {
     702            0 :         VersionStringTableEntries::new(self.ptr.entries())
     703            0 :     }
     704              : }
     705              : 
     706              : impl fmt::Debug for VersionStringTable<'_> {
     707            0 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     708            0 :         f.debug_struct("VersionStringTable")
     709            0 :             .field("key", &self.key())
     710            0 :             .finish()
     711            0 :     }
     712              : }
     713              : 
     714              : impl<'a> FromFFI<ffi::PE_ResourceStringTable> for VersionStringTable<'a> {
     715            0 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourceStringTable>) -> Self {
     716            0 :         Self {
     717            0 :             ptr,
     718            0 :             _owner: PhantomData,
     719            0 :         }
     720            0 :     }
     721              : }
     722              : 
     723              : /// Represents a Var entry within VarFileInfo
     724              : pub struct ResourceVar<'a> {
     725              :     ptr: cxx::UniquePtr<ffi::PE_ResourceVar>,
     726              :     _owner: PhantomData<&'a ffi::PE_ResourceVersion>,
     727              : }
     728              : 
     729              : impl ResourceVar<'_> {
     730              :     /// Type of the var entry
     731            0 :     pub fn get_type(&self) -> u16 {
     732            0 :         self.ptr.get_type()
     733            0 :     }
     734              : 
     735              :     /// Key of the var entry
     736            0 :     pub fn key(&self) -> String {
     737            0 :         self.ptr.key().to_string()
     738            0 :     }
     739              : 
     740              :     /// Values of the var entry (language/codepage pairs)
     741            0 :     pub fn values(&self) -> Vec<u32> {
     742            0 :         self.ptr.values().iter().map(|&v| v as u32).collect()
     743            0 :     }
     744              : }
     745              : 
     746              : impl fmt::Debug for ResourceVar<'_> {
     747            0 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     748            0 :         f.debug_struct("ResourceVar")
     749            0 :             .field("key", &self.key())
     750            0 :             .field("values", &self.values())
     751            0 :             .finish()
     752            0 :     }
     753              : }
     754              : 
     755              : impl<'a> FromFFI<ffi::PE_ResourceVar> for ResourceVar<'a> {
     756            0 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourceVar>) -> Self {
     757            0 :         Self {
     758            0 :             ptr,
     759            0 :             _owner: PhantomData,
     760            0 :         }
     761            0 :     }
     762              : }
     763              : 
     764              : /// Represents a StringFileInfo structure from a version resource
     765              : pub struct StringFileInfo<'a> {
     766              :     ptr: cxx::UniquePtr<ffi::PE_ResourceStringFileInfo>,
     767              :     _owner: PhantomData<&'a ffi::PE_ResourceVersion>,
     768              : }
     769              : 
     770              : impl StringFileInfo<'_> {
     771              :     /// Type of the StringFileInfo
     772            0 :     pub fn get_type(&self) -> u16 {
     773            0 :         self.ptr.get_type()
     774            0 :     }
     775              : 
     776              :     /// Key of the StringFileInfo
     777            0 :     pub fn key(&self) -> String {
     778            0 :         self.ptr.key().to_string()
     779            0 :     }
     780              : 
     781              :     /// Return an iterator over the child string tables
     782            0 :     pub fn children(&self) -> StringFileInfoChildren<'_> {
     783            0 :         StringFileInfoChildren::new(self.ptr.children())
     784            0 :     }
     785              : }
     786              : 
     787              : impl fmt::Debug for StringFileInfo<'_> {
     788            0 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     789            0 :         f.debug_struct("StringFileInfo")
     790            0 :             .field("key", &self.key())
     791            0 :             .finish()
     792            0 :     }
     793              : }
     794              : 
     795              : impl<'a> FromFFI<ffi::PE_ResourceStringFileInfo> for StringFileInfo<'a> {
     796            0 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourceStringFileInfo>) -> Self {
     797            0 :         Self {
     798            0 :             ptr,
     799            0 :             _owner: PhantomData,
     800            0 :         }
     801            0 :     }
     802              : }
     803              : 
     804              : /// Represents a VarFileInfo structure from a version resource
     805              : pub struct VarFileInfo<'a> {
     806              :     ptr: cxx::UniquePtr<ffi::PE_ResourceVarFileInfo>,
     807              :     _owner: PhantomData<&'a ffi::PE_ResourceVersion>,
     808              : }
     809              : 
     810              : impl VarFileInfo<'_> {
     811              :     /// Type of the VarFileInfo
     812            0 :     pub fn get_type(&self) -> u16 {
     813            0 :         self.ptr.get_type()
     814            0 :     }
     815              : 
     816              :     /// Key of the VarFileInfo
     817            0 :     pub fn key(&self) -> String {
     818            0 :         self.ptr.key().to_string()
     819            0 :     }
     820              : 
     821              :     /// Return an iterator over the Var entries
     822            0 :     pub fn vars(&self) -> VarFileInfoVars<'_> {
     823            0 :         VarFileInfoVars::new(self.ptr.vars())
     824            0 :     }
     825              : }
     826              : 
     827              : impl fmt::Debug for VarFileInfo<'_> {
     828            0 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     829            0 :         f.debug_struct("VarFileInfo")
     830            0 :             .field("key", &self.key())
     831            0 :             .finish()
     832            0 :     }
     833              : }
     834              : 
     835              : impl<'a> FromFFI<ffi::PE_ResourceVarFileInfo> for VarFileInfo<'a> {
     836            0 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourceVarFileInfo>) -> Self {
     837            0 :         Self {
     838            0 :             ptr,
     839            0 :             _owner: PhantomData,
     840            0 :         }
     841            0 :     }
     842              : }
     843              : 
     844              : /// Represents a PE version resource
     845              : pub struct Version<'a> {
     846              :     ptr: cxx::UniquePtr<ffi::PE_ResourceVersion>,
     847              :     _owner: PhantomData<&'a ffi::PE_ResourcesManager>,
     848              : }
     849              : 
     850              : impl Version<'_> {
     851              :     /// Type of the version resource
     852            0 :     pub fn get_type(&self) -> u16 {
     853            0 :         self.ptr.get_type()
     854            0 :     }
     855              : 
     856              :     /// Key of the version resource
     857            0 :     pub fn key(&self) -> String {
     858            0 :         self.ptr.key().to_string()
     859            0 :     }
     860              : 
     861              :     /// Return the fixed file information if present
     862            0 :     pub fn file_info(&self) -> FixedFileInfo {
     863            0 :         FixedFileInfo {
     864            0 :             signature: self.ptr.file_info_signature(),
     865            0 :             struct_version: self.ptr.file_info_struct_version(),
     866            0 :             file_version_ms: self.ptr.file_info_file_version_ms(),
     867            0 :             file_version_ls: self.ptr.file_info_file_version_ls(),
     868            0 :             product_version_ms: self.ptr.file_info_product_version_ms(),
     869            0 :             product_version_ls: self.ptr.file_info_product_version_ls(),
     870            0 :             file_flags_mask: self.ptr.file_info_file_flags_mask(),
     871            0 :             file_flags: self.ptr.file_info_file_flags(),
     872            0 :             file_os: self.ptr.file_info_file_os(),
     873            0 :             file_type: self.ptr.file_info_file_type(),
     874            0 :             file_subtype: self.ptr.file_info_file_subtype(),
     875            0 :             file_date_ms: self.ptr.file_info_file_date_ms(),
     876            0 :             file_date_ls: self.ptr.file_info_file_date_ls(),
     877            0 :         }
     878            0 :     }
     879              : 
     880              :     /// Return the StringFileInfo if present
     881            0 :     pub fn string_file_info(&self) -> Option<StringFileInfo<'_>> {
     882            0 :         into_optional(self.ptr.string_file_info())
     883            0 :     }
     884              : 
     885              :     /// Return the VarFileInfo if present
     886            0 :     pub fn var_file_info(&self) -> Option<VarFileInfo<'_>> {
     887            0 :         into_optional(self.ptr.var_file_info())
     888            0 :     }
     889              : }
     890              : 
     891              : impl fmt::Debug for Version<'_> {
     892            0 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     893            0 :         f.debug_struct("Version").field("key", &self.key()).finish()
     894            0 :     }
     895              : }
     896              : 
     897              : impl<'a> FromFFI<ffi::PE_ResourceVersion> for Version<'a> {
     898            0 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourceVersion>) -> Self {
     899            0 :         Self {
     900            0 :             ptr,
     901            0 :             _owner: PhantomData,
     902            0 :         }
     903            0 :     }
     904              : }
     905              : 
     906              : /// Represents a PE accelerator resource entry
     907              : pub struct Accelerator<'a> {
     908              :     ptr: cxx::UniquePtr<ffi::PE_ResourceAccelerator>,
     909              :     _owner: PhantomData<&'a ffi::PE_ResourcesManager>,
     910              : }
     911              : 
     912              : impl Accelerator<'_> {
     913              :     /// Flags for the accelerator
     914            0 :     pub fn flags(&self) -> i16 {
     915            0 :         self.ptr.flags()
     916            0 :     }
     917              : 
     918              :     /// ANSI code of the accelerator key
     919            0 :     pub fn ansi(&self) -> i16 {
     920            0 :         self.ptr.ansi()
     921            0 :     }
     922              : 
     923              :     /// ID of the accelerator
     924            0 :     pub fn id(&self) -> u16 {
     925            0 :         self.ptr.id()
     926            0 :     }
     927              : 
     928              :     /// Padding value
     929            0 :     pub fn padding(&self) -> i16 {
     930            0 :         self.ptr.padding()
     931            0 :     }
     932              : 
     933              :     /// Return the ANSI string representation of the accelerator key
     934            0 :     pub fn ansi_str(&self) -> String {
     935            0 :         self.ptr.ansi_str().to_string()
     936            0 :     }
     937              : }
     938              : 
     939              : impl fmt::Debug for Accelerator<'_> {
     940            0 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     941            0 :         f.debug_struct("Accelerator")
     942            0 :             .field("id", &self.id())
     943            0 :             .field("flags", &self.flags())
     944            0 :             .field("ansi", &self.ansi())
     945            0 :             .finish()
     946            0 :     }
     947              : }
     948              : 
     949              : impl<'a> FromFFI<ffi::PE_ResourceAccelerator> for Accelerator<'a> {
     950            0 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourceAccelerator>) -> Self {
     951            0 :         Self {
     952            0 :             ptr,
     953            0 :             _owner: PhantomData,
     954            0 :         }
     955            0 :     }
     956              : }
     957              : 
     958              : /// Represents a string table entry from the ResourcesManager
     959              : pub struct StringEntry<'a> {
     960              :     ptr: cxx::UniquePtr<ffi::PE_ResourcesManager_string_entry_t>,
     961              :     _owner: PhantomData<&'a ffi::PE_ResourcesManager>,
     962              : }
     963              : 
     964              : impl StringEntry<'_> {
     965              :     /// The string value
     966            0 :     pub fn string(&self) -> String {
     967            0 :         self.ptr.string().to_string()
     968            0 :     }
     969              : 
     970              :     /// The ID associated with this string
     971            0 :     pub fn id(&self) -> u32 {
     972            0 :         self.ptr.id()
     973            0 :     }
     974              : }
     975              : 
     976              : impl fmt::Debug for StringEntry<'_> {
     977            0 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     978            0 :         f.debug_struct("StringEntry")
     979            0 :             .field("id", &self.id())
     980            0 :             .field("string", &self.string())
     981            0 :             .finish()
     982            0 :     }
     983              : }
     984              : 
     985              : impl<'a> FromFFI<ffi::PE_ResourcesManager_string_entry_t> for StringEntry<'a> {
     986            0 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourcesManager_string_entry_t>) -> Self {
     987            0 :         Self {
     988            0 :             ptr,
     989            0 :             _owner: PhantomData,
     990            0 :         }
     991            0 :     }
     992              : }
     993              : 
     994         4914 : declare_iterator!(
     995         4914 :     Children,
     996         4914 :     Node<'a>,
     997         4914 :     ffi::PE_ResourceNode,
     998         4914 :     ffi::PE_Binary,
     999         4914 :     ffi::PE_ResourceNode_it_childs
    1000         4914 : );
    1001              : 
    1002            0 : declare_iterator!(
    1003            0 :     Icons,
    1004            0 :     Icon<'a>,
    1005            0 :     ffi::PE_ResourceIcon,
    1006            0 :     ffi::PE_ResourcesManager,
    1007            0 :     ffi::PE_ResourcesManager_it_icons
    1008            0 : );
    1009              : 
    1010            0 : declare_iterator!(
    1011            0 :     Versions,
    1012            0 :     Version<'a>,
    1013            0 :     ffi::PE_ResourceVersion,
    1014            0 :     ffi::PE_ResourcesManager,
    1015            0 :     ffi::PE_ResourcesManager_it_version
    1016            0 : );
    1017              : 
    1018            0 : declare_iterator!(
    1019            0 :     Accelerators,
    1020            0 :     Accelerator<'a>,
    1021            0 :     ffi::PE_ResourceAccelerator,
    1022            0 :     ffi::PE_ResourcesManager,
    1023            0 :     ffi::PE_ResourcesManager_it_accelerator
    1024            0 : );
    1025              : 
    1026            0 : declare_iterator!(
    1027            0 :     StringTableEntries,
    1028            0 :     StringEntry<'a>,
    1029            0 :     ffi::PE_ResourcesManager_string_entry_t,
    1030            0 :     ffi::PE_ResourcesManager,
    1031            0 :     ffi::PE_ResourcesManager_it_string_table_entry
    1032            0 : );
    1033              : 
    1034            0 : declare_iterator!(
    1035            0 :     VersionStringTableEntries,
    1036            0 :     VersionStringTableEntry,
    1037            0 :     ffi::PE_ResourceStringTable_entry_t,
    1038            0 :     ffi::PE_ResourceStringTable,
    1039            0 :     ffi::PE_ResourceStringTable_it_entries
    1040            0 : );
    1041              : 
    1042            0 : declare_iterator!(
    1043            0 :     StringFileInfoChildren,
    1044            0 :     VersionStringTable<'a>,
    1045            0 :     ffi::PE_ResourceStringTable,
    1046            0 :     ffi::PE_ResourceStringFileInfo,
    1047            0 :     ffi::PE_ResourceStringFileInfo_it_children
    1048            0 : );
    1049              : 
    1050            0 : declare_iterator!(
    1051            0 :     VarFileInfoVars,
    1052            0 :     ResourceVar<'a>,
    1053            0 :     ffi::PE_ResourceVar,
    1054            0 :     ffi::PE_ResourceVarFileInfo,
    1055            0 :     ffi::PE_ResourceVarFileInfo_it_vars
    1056            0 : );
        

Generated by: LCOV version 2.1-1