Skip to content

Commit

Permalink
iterator for messages
Browse files Browse the repository at this point in the history
  • Loading branch information
Jan Starke committed Jun 29, 2021
1 parent ffcc88d commit 312b151
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 31 deletions.
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod pefile;
#[allow(non_camel_case_types)]
mod winnt;
mod utils;
mod msg;

use argparse::{ArgumentParser, Store};
use std::path::PathBuf;
Expand Down
111 changes: 111 additions & 0 deletions src/msg/iterator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
use crate::msg::Message;
use crate::pefile::*;
use crate::winnt::*;
use encoding_rs::*;
use from_bytes::StructFromBytes;
use packed_size::*;

pub struct MessagesIterator<'pefile> {
pefile: &'pefile PEFile,

remaining_blocks: u32,

low_id: u32,
high_id: u32,
current_id: u32,

rde_offset: usize,
block_offset: usize,
entry_offset: usize,

error_handler: Option<fn(std::io::Error) -> ()>,
lang_id: u32,
encodings: [&'static Encoding; 2],
}

impl<'pefile> MessagesIterator<'pefile> {
pub fn new(
pefile: &'pefile PEFile,
lang_id: u32,
resource_entry: &IMAGE_RESOURCE_DATA_ENTRY,
error_handler: Option<fn(std::io::Error) -> ()>,
) -> std::io::Result<Self> {
let rde_offset = pefile
.get_raw_address(resource_entry.OffsetToData as usize)
.unwrap();
let mrd = MESSAGE_RESOURCE_DATA::from_bytes(pefile.full_image(), rde_offset)?;

// go one step back, because we go one blocksize forward before the first result is returned
let block_offset = rde_offset + MESSAGE_RESOURCE_DATA::packed_size() - MESSAGE_RESOURCE_BLOCK::packed_size();

Ok(Self {
pefile,
current_id: u32::MAX,
remaining_blocks: mrd.NumberOfBlocks,
rde_offset,
block_offset,
entry_offset: usize::MAX,
low_id: 0,
high_id: 0,
error_handler,
lang_id,
encodings: [WINDOWS_1252, UTF_16LE]
})
}

fn handle_error(&self, why: std::io::Error) {
if let Some(error_handler) = &self.error_handler {
error_handler(why);
}
}

pub fn do_next(&mut self) -> std::io::Result<Option<Message>> {

let blocksize = MESSAGE_RESOURCE_BLOCK::packed_size();

// find for next block
if self.current_id >= self.high_id {
if self.remaining_blocks == 0 {
return Ok(None);
}
self.remaining_blocks -= 1;
self.block_offset += blocksize;
let block = MESSAGE_RESOURCE_BLOCK::from_bytes(
self.pefile.full_image(),
self.block_offset,
)?;

self.entry_offset = self.rde_offset + block.OffsetToEntries as usize;
self.low_id = block.LowId;
self.current_id = block.LowId;
self.high_id = block.HighId;
} else {
self.current_id += 1;
}

let entry = MESSAGE_RESOURCE_ENTRY::from_bytes(self.pefile.full_image(), self.entry_offset)?;
let text_offset = self.entry_offset + MESSAGE_RESOURCE_ENTRY::packed_size();
let message_length = entry.Length as usize - MESSAGE_RESOURCE_ENTRY::packed_size();

let message = self.encodings[entry.Flags as usize]
.decode(&self.pefile.full_image()[text_offset..text_offset + message_length])
.0
.to_string();
self.entry_offset += entry.Length as usize;

Ok(Some(Message::new(self.current_id, self.lang_id, message)))
}
}

impl<'pefile> Iterator for MessagesIterator<'pefile> {
type Item = Message;
fn next(&mut self) -> Option<Self::Item> {
match self.do_next() {
Ok(v) => v,
Err(why) => {
self.handle_error(why);
None
}
}
}
}
18 changes: 18 additions & 0 deletions src/msg/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
pub mod iterator;
pub use iterator::*;

pub struct Message {
pub msg_id: u32,
pub lang_id: u32,
pub text: String,
}

impl Message {
pub fn new(msg_id: u32, lang_id: u32, text: String) -> Self {
Message {
msg_id,
lang_id,
text,
}
}
}
39 changes: 9 additions & 30 deletions src/pefile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::str;

use crate::winnt::IMAGE_OPTIONAL_HEADER::*;
use crate::winnt::*;
use crate::utils::*;
use crate::msg::*;
use from_bytes::StructFromBytes;
use packed_size::*;
use encoding_rs::*;
Expand Down Expand Up @@ -247,6 +247,12 @@ impl PEFile {
self.visit_resource_tree(&mut visitor).unwrap();
}


pub fn messages_iter(&self, lang_id: u32,
resource_entry: &IMAGE_RESOURCE_DATA_ENTRY) -> std::io::Result<MessagesIterator> {
MessagesIterator::new(self, lang_id, resource_entry, None)
}

pub fn visit_resource_tree<V: ResourceDirectoryVisitor>(
&self,
visitor: &mut V,
Expand Down Expand Up @@ -362,35 +368,8 @@ impl ConsoleVisitor {
pefile: &PEFile,
entry: &IMAGE_RESOURCE_DATA_ENTRY,
) -> std::io::Result<()> {
let offset = pefile.get_raw_address(entry.OffsetToData as usize).unwrap();
let mrd = MESSAGE_RESOURCE_DATA::from_bytes(pefile.full_image(), offset)?;
println!("Blocks: {}", mrd.NumberOfBlocks);

let blocksize = MESSAGE_RESOURCE_BLOCK::packed_size();
let first_block_offset = offset + MESSAGE_RESOURCE_DATA::packed_size();
for i in 0..mrd.NumberOfBlocks {
let block_offset = first_block_offset + blocksize * i as usize;
let block = MESSAGE_RESOURCE_BLOCK::from_bytes(pefile.full_image(), block_offset)?;

let mut entry_offset = offset + block.OffsetToEntries as usize;
for id in block.LowId .. block.HighId + 1 {
let entry = MESSAGE_RESOURCE_ENTRY::from_bytes(pefile.full_image(), entry_offset)?;
let text_offset = entry_offset + MESSAGE_RESOURCE_ENTRY::packed_size();
let message_length = entry.Length as usize - MESSAGE_RESOURCE_ENTRY::packed_size();

let message =
if entry.Flags == 0x0001 {
utf16_from_slice(pefile.full_image(), text_offset, message_length/2)
} else if entry.Flags == 0x0000 {
let message_length = message_length;
WINDOWS_1252.decode(&pefile.full_image()[text_offset .. text_offset + message_length]).0.to_string()
} else {
panic!("illegal flags value: 0x{:04x}", entry.Flags);
};
println!("{}{}: '{}'", self.indent(), id, message);

entry_offset += entry.Length as usize;
}
for msg in pefile.messages_iter(0, entry)? {
println!("{}{}: '{}'", self.indent(), msg.msg_id, msg.text);
}
Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ pub fn utf16_from_slice(slice: &[u8], mut offset: usize, characters: usize) -> S
offset += 2;
}
String::from_utf16_lossy(&name_chars[..])
}
}

0 comments on commit 312b151

Please sign in to comment.