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-10-27: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          272 : #[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         1456 :     fn id(&self) -> u32 {
      26         1456 :         self.get_base().id()
      27         1456 :     }
      28              : 
      29              :     /// Current depth of the Node in the resource tree
      30          224 :     fn depth(&self) -> u32 {
      31          224 :         self.get_base().depth()
      32          224 :     }
      33              : 
      34              :     /// Iterator on node's children
      35         1456 :     fn children(&self) -> Children {
      36         1456 :         Children::new(self.get_base().childs())
      37         1456 :     }
      38              : }
      39              : 
      40              : impl std::fmt::Debug for &dyn NodeBase {
      41         1456 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      42         1456 :         f.debug_struct("NodeBase").field("id", &self.id()).finish()
      43         1456 :     }
      44              : }
      45              : 
      46              : impl<'a> FromFFI<ffi::PE_ResourceNode> for Node<'a> {
      47         2864 :     fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::PE_ResourceNode>) -> Self {
      48         2864 :         unsafe {
      49         2864 :             let cmd_ref = ffi_entry.as_ref().unwrap();
      50         2864 : 
      51         2864 :             if ffi::PE_ResourceDirectory::classof(cmd_ref) {
      52         1680 :                 let raw = {
      53         1680 :                     type From = cxx::UniquePtr<ffi::PE_ResourceNode>;
      54         1680 :                     type To = cxx::UniquePtr<ffi::PE_ResourceDirectory>;
      55         1680 :                     std::mem::transmute::<From, To>(ffi_entry)
      56         1680 :                 };
      57         1680 :                 Node::Directory(Directory::from_ffi(raw))
      58              :             } else {
      59         1184 :                 assert!(
      60         1184 :                     ffi::PE_ResourceData::classof(cmd_ref),
      61            0 :                     "Must be a ResourceData node"
      62              :                 );
      63              : 
      64         1184 :                 let raw = {
      65         1184 :                     type From = cxx::UniquePtr<ffi::PE_ResourceNode>;
      66         1184 :                     type To = cxx::UniquePtr<ffi::PE_ResourceData>;
      67         1184 :                     std::mem::transmute::<From, To>(ffi_entry)
      68         1184 :                 };
      69         1184 :                 Node::Data(Data::from_ffi(raw))
      70              :             }
      71              :         }
      72         2864 :     }
      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         1184 :     pub fn code_page(&self) -> u32 {
      84         1184 :         self.ptr.code_page()
      85         1184 :     }
      86              : 
      87              :     /// Reserved value. Should be `0`
      88         1184 :     pub fn reserved(&self) -> u32 {
      89         1184 :         self.ptr.reserved()
      90         1184 :     }
      91              : 
      92              :     /// Offset of the content within the resource
      93              :     ///
      94              :     /// <div class="warning">this value may change when rebuilding resource table</div>
      95         1184 :     pub fn offset(&self) -> u32 {
      96         1184 :         self.ptr.offset()
      97         1184 :     }
      98              : 
      99              :     /// Resource content
     100         1184 :     pub fn content(&self) -> &[u8] {
     101         1184 :         to_slice!(self.ptr.content());
     102         1184 :     }
     103              : }
     104              : 
     105              : impl NodeBase for Data<'_> {
     106         1184 :     fn get_base(&self) -> &ffi::PE_ResourceNode {
     107         1184 :         self.ptr.as_ref().unwrap().as_ref()
     108         1184 :     }
     109              : }
     110              : 
     111              : impl fmt::Debug for Data<'_> {
     112         1184 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     113         1184 :         let base = self as &dyn NodeBase;
     114         1184 :         f.debug_struct("Data")
     115         1184 :             .field("base", &base)
     116         1184 :             .field("code_page", &self.code_page())
     117         1184 :             .field("reserved", &self.reserved())
     118         1184 :             .field("offset", &self.offset())
     119         1184 :             .finish()
     120         1184 :     }
     121              : }
     122              : 
     123              : impl<'a> FromFFI<ffi::PE_ResourceData> for Data<'a> {
     124         1184 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourceData>) -> Self {
     125         1184 :         Self {
     126         1184 :             ptr,
     127         1184 :             _owner: PhantomData,
     128         1184 :         }
     129         1184 :     }
     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          272 :     pub fn characteristics(&self) -> u32 {
     142          272 :         self.ptr.characteristics()
     143          272 :     }
     144              : 
     145              :     /// The time that the resource data was created by the
     146              :     /// resource compiler.
     147          272 :     pub fn time_date_stamp(&self) -> u32 {
     148          272 :         self.ptr.time_date_stamp()
     149          272 :     }
     150              : 
     151              :     /// The major version number, set by the user.
     152          272 :     pub fn major_version(&self) -> u32 {
     153          272 :         self.ptr.major_version()
     154          272 :     }
     155              : 
     156              :     /// The minor version number, set by the user.
     157          272 :     pub fn minor_version(&self) -> u32 {
     158          272 :         self.ptr.minor_version()
     159          272 :     }
     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          272 :     pub fn numberof_name_entries(&self) -> u32 {
     165          272 :         self.ptr.numberof_name_entries()
     166          272 :     }
     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          272 :     pub fn numberof_id_entries(&self) -> u32 {
     173          272 :         self.ptr.numberof_id_entries()
     174          272 :     }
     175              : }
     176              : 
     177              : impl NodeBase for Directory<'_> {
     178         1952 :     fn get_base(&self) -> &ffi::PE_ResourceNode {
     179         1952 :         self.ptr.as_ref().unwrap().as_ref()
     180         1952 :     }
     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          272 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     198          272 :         let base = self as &dyn NodeBase;
     199          272 :         f.debug_struct("Directory")
     200          272 :             .field("base", &base)
     201          272 :             .field("characteristics", &self.characteristics())
     202          272 :             .field("time_date_stamp", &self.time_date_stamp())
     203          272 :             .field("major_version", &self.major_version())
     204          272 :             .field("minor_version", &self.minor_version())
     205          272 :             .field("numberof_name_entries", &self.numberof_name_entries())
     206          272 :             .field("numberof_id_entries", &self.numberof_id_entries())
     207          272 :             .finish()
     208          272 :     }
     209              : }
     210              : 
     211              : impl<'a> FromFFI<ffi::PE_ResourceDirectory> for Directory<'a> {
     212         1680 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourceDirectory>) -> Self {
     213         1680 :         Self {
     214         1680 :             ptr,
     215         1680 :             _owner: PhantomData,
     216         1680 :         }
     217         1680 :     }
     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           48 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourcesManager>) -> Self {
     227           48 :         Self {
     228           48 :             ptr,
     229           48 :             _owner: PhantomData,
     230           48 :         }
     231           48 :     }
     232              : }
     233              : 
     234         2768 : declare_iterator!(
     235         2768 :     Children,
     236         2768 :     Node<'a>,
     237         2768 :     ffi::PE_ResourceNode,
     238         2768 :     ffi::PE_Binary,
     239         2768 :     ffi::PE_ResourceNode_it_childs
     240         2768 : );
        

Generated by: LCOV version 2.1-1