LCOV - code coverage report
Current view: top level - src/pe - resources.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 93.5 % 123 115
Test Date: 2024-11-30:00:00:00 Functions: 80.6 % 31 25

            Line data    Source code
       1              : //! This module contains the different structures involved in the PE's resource tree
       2              : 
       3              : use lief_ffi as ffi;
       4              : 
       5              : use std::{fmt, marker::PhantomData};
       6              : 
       7              : use crate::to_slice;
       8              : use crate::{common::FromFFI, declare_iterator};
       9              : 
      10          340 : #[derive(Debug)]
      11              : pub enum Node<'a> {
      12              :     /// A *data* node (i.e. a leaf)
      13              :     Data(Data<'a>),
      14              :     /// A directory node
      15              :     Directory(Directory<'a>),
      16              : }
      17              : 
      18              : /// Trait that is shared by both [`Node::Data`] and [`Node::Directory`].
      19              : pub trait NodeBase {
      20              :     #[doc(hidden)]
      21              :     fn get_base(&self) -> &ffi::PE_ResourceNode;
      22              : 
      23              :     /// Integer that identifies the Type, Name, or Language ID of the entry
      24              :     /// depending on its [`NodeBase::depth`] in the tree
      25         1820 :     fn id(&self) -> u32 {
      26         1820 :         self.get_base().id()
      27         1820 :     }
      28              : 
      29              :     /// Current depth of the Node in the resource tree
      30          280 :     fn depth(&self) -> u32 {
      31          280 :         self.get_base().depth()
      32          280 :     }
      33              : 
      34              :     /// Iterator on node's children
      35         1820 :     fn children(&self) -> Children {
      36         1820 :         Children::new(self.get_base().childs())
      37         1820 :     }
      38              : }
      39              : 
      40              : impl std::fmt::Debug for &dyn NodeBase {
      41         1820 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      42         1820 :         f.debug_struct("NodeBase").field("id", &self.id()).finish()
      43         1820 :     }
      44              : }
      45              : 
      46              : impl<'a> FromFFI<ffi::PE_ResourceNode> for Node<'a> {
      47         3580 :     fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::PE_ResourceNode>) -> Self {
      48         3580 :         unsafe {
      49         3580 :             let cmd_ref = ffi_entry.as_ref().unwrap();
      50         3580 : 
      51         3580 :             if ffi::PE_ResourceDirectory::classof(cmd_ref) {
      52         2100 :                 let raw = {
      53         2100 :                     type From = cxx::UniquePtr<ffi::PE_ResourceNode>;
      54         2100 :                     type To = cxx::UniquePtr<ffi::PE_ResourceDirectory>;
      55         2100 :                     std::mem::transmute::<From, To>(ffi_entry)
      56         2100 :                 };
      57         2100 :                 Node::Directory(Directory::from_ffi(raw))
      58              :             } else {
      59         1480 :                 assert!(
      60         1480 :                     ffi::PE_ResourceData::classof(cmd_ref),
      61            0 :                     "Must be a ResourceData node"
      62              :                 );
      63              : 
      64         1480 :                 let raw = {
      65         1480 :                     type From = cxx::UniquePtr<ffi::PE_ResourceNode>;
      66         1480 :                     type To = cxx::UniquePtr<ffi::PE_ResourceData>;
      67         1480 :                     std::mem::transmute::<From, To>(ffi_entry)
      68         1480 :                 };
      69         1480 :                 Node::Data(Data::from_ffi(raw))
      70              :             }
      71              :         }
      72         3580 :     }
      73              : }
      74              : 
      75              : pub struct Data<'a> {
      76              :     ptr: cxx::UniquePtr<ffi::PE_ResourceData>,
      77              :     _owner: PhantomData<&'a Node<'a>>,
      78              : }
      79              : 
      80              : impl Data<'_> {
      81              :     /// Return the code page that is used to decode code point
      82              :     /// values within the resource data. Typically, the code page is the unicode code page.
      83         1480 :     pub fn code_page(&self) -> u32 {
      84         1480 :         self.ptr.code_page()
      85         1480 :     }
      86              : 
      87              :     /// Reserved value. Should be `0`
      88         1480 :     pub fn reserved(&self) -> u32 {
      89         1480 :         self.ptr.reserved()
      90         1480 :     }
      91              : 
      92              :     /// Offset of the content within the resource
      93              :     ///
      94              :     /// <div class="warning">this value may change when rebuilding resource table</div>
      95         1480 :     pub fn offset(&self) -> u32 {
      96         1480 :         self.ptr.offset()
      97         1480 :     }
      98              : 
      99              :     /// Resource content
     100         1480 :     pub fn content(&self) -> &[u8] {
     101         1480 :         to_slice!(self.ptr.content());
     102         1480 :     }
     103              : }
     104              : 
     105              : impl NodeBase for Data<'_> {
     106         1480 :     fn get_base(&self) -> &ffi::PE_ResourceNode {
     107         1480 :         self.ptr.as_ref().unwrap().as_ref()
     108         1480 :     }
     109              : }
     110              : 
     111              : impl fmt::Debug for Data<'_> {
     112         1480 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     113         1480 :         let base = self as &dyn NodeBase;
     114         1480 :         f.debug_struct("Data")
     115         1480 :             .field("base", &base)
     116         1480 :             .field("code_page", &self.code_page())
     117         1480 :             .field("reserved", &self.reserved())
     118         1480 :             .field("offset", &self.offset())
     119         1480 :             .finish()
     120         1480 :     }
     121              : }
     122              : 
     123              : impl<'a> FromFFI<ffi::PE_ResourceData> for Data<'a> {
     124         1480 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourceData>) -> Self {
     125         1480 :         Self {
     126         1480 :             ptr,
     127         1480 :             _owner: PhantomData,
     128         1480 :         }
     129         1480 :     }
     130              : }
     131              : 
     132              : pub struct Directory<'a> {
     133              :     ptr: cxx::UniquePtr<ffi::PE_ResourceDirectory>,
     134              :     _owner: PhantomData<&'a Node<'a>>,
     135              : }
     136              : 
     137              : impl Directory<'_> {
     138              : 
     139              :     /// Resource characteristics. This field is reserved for future use.
     140              :     /// It is currently set to zero.
     141          340 :     pub fn characteristics(&self) -> u32 {
     142          340 :         self.ptr.characteristics()
     143          340 :     }
     144              : 
     145              :     /// The time that the resource data was created by the
     146              :     /// resource compiler.
     147          340 :     pub fn time_date_stamp(&self) -> u32 {
     148          340 :         self.ptr.time_date_stamp()
     149          340 :     }
     150              : 
     151              :     /// The major version number, set by the user.
     152          340 :     pub fn major_version(&self) -> u32 {
     153          340 :         self.ptr.major_version()
     154          340 :     }
     155              : 
     156              :     /// The minor version number, set by the user.
     157          340 :     pub fn minor_version(&self) -> u32 {
     158          340 :         self.ptr.minor_version()
     159          340 :     }
     160              : 
     161              :     /// The number of directory entries immediately
     162              :     /// following the table that use strings to identify Type,
     163              :     /// Name, or Language entries (depending on the level of the table).
     164          340 :     pub fn numberof_name_entries(&self) -> u32 {
     165          340 :         self.ptr.numberof_name_entries()
     166          340 :     }
     167              : 
     168              : 
     169              :     /// The number of directory entries immediately
     170              :     /// following the Name entries that use numeric IDs for
     171              :     /// Type, Name, or Language entries.
     172          340 :     pub fn numberof_id_entries(&self) -> u32 {
     173          340 :         self.ptr.numberof_id_entries()
     174          340 :     }
     175              : }
     176              : 
     177              : impl NodeBase for Directory<'_> {
     178         2440 :     fn get_base(&self) -> &ffi::PE_ResourceNode {
     179         2440 :         self.ptr.as_ref().unwrap().as_ref()
     180         2440 :     }
     181              : }
     182              : 
     183              : impl NodeBase for Node<'_> {
     184            0 :     fn get_base(&self) -> &ffi::PE_ResourceNode {
     185            0 :         match &self {
     186            0 :             Node::Data(n) => {
     187            0 :                 n.get_base()
     188              :             }
     189            0 :             Node::Directory(n) => {
     190            0 :                 n.get_base()
     191              :             }
     192              :         }
     193            0 :     }
     194              : }
     195              : 
     196              : impl fmt::Debug for Directory<'_> {
     197          340 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     198          340 :         let base = self as &dyn NodeBase;
     199          340 :         f.debug_struct("Directory")
     200          340 :             .field("base", &base)
     201          340 :             .field("characteristics", &self.characteristics())
     202          340 :             .field("time_date_stamp", &self.time_date_stamp())
     203          340 :             .field("major_version", &self.major_version())
     204          340 :             .field("minor_version", &self.minor_version())
     205          340 :             .field("numberof_name_entries", &self.numberof_name_entries())
     206          340 :             .field("numberof_id_entries", &self.numberof_id_entries())
     207          340 :             .finish()
     208          340 :     }
     209              : }
     210              : 
     211              : impl<'a> FromFFI<ffi::PE_ResourceDirectory> for Directory<'a> {
     212         2100 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourceDirectory>) -> Self {
     213         2100 :         Self {
     214         2100 :             ptr,
     215         2100 :             _owner: PhantomData,
     216         2100 :         }
     217         2100 :     }
     218              : }
     219              : 
     220              : pub struct Manager<'a> {
     221              :     ptr: cxx::UniquePtr<ffi::PE_ResourcesManager>,
     222              :     _owner: PhantomData<&'a Node<'a>>,
     223              : }
     224              : 
     225              : impl<'a> FromFFI<ffi::PE_ResourcesManager> for Manager<'a> {
     226           60 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourcesManager>) -> Self {
     227           60 :         Self {
     228           60 :             ptr,
     229           60 :             _owner: PhantomData,
     230           60 :         }
     231           60 :     }
     232              : }
     233              : 
     234         3460 : declare_iterator!(
     235         3460 :     Children,
     236         3460 :     Node<'a>,
     237         3460 :     ffi::PE_ResourceNode,
     238         3460 :     ffi::PE_Binary,
     239         3460 :     ffi::PE_ResourceNode_it_childs
     240         3460 : );
        

Generated by: LCOV version 2.1-1