Skip to content

Commit

Permalink
implement kernel32 SizeofResource
Browse files Browse the repository at this point in the history
  • Loading branch information
LinusU committed Sep 11, 2024
1 parent d782637 commit 8225a59
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 16 deletions.
Binary file modified win32/dll/kernel32.dll
Binary file not shown.
21 changes: 17 additions & 4 deletions win32/src/winapi/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2765,8 +2765,8 @@ pub mod kernel32 {
}
pub unsafe fn LoadResource(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let hModule = <u32>::from_stack(mem, esp + 4u32);
let hResInfo = <u32>::from_stack(mem, esp + 8u32);
let hModule = <HMODULE>::from_stack(mem, esp + 4u32);
let hResInfo = <HRSRC>::from_stack(mem, esp + 8u32);
winapi::kernel32::LoadResource(machine, hModule, hResInfo).to_raw()
}
pub unsafe fn LocalAlloc(machine: &mut Machine, esp: u32) -> u32 {
Expand All @@ -2782,7 +2782,7 @@ pub mod kernel32 {
}
pub unsafe fn LockResource(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let hResData = <u32>::from_stack(mem, esp + 4u32);
let hResData = <HRSRC>::from_stack(mem, esp + 4u32);
winapi::kernel32::LockResource(machine, hResData).to_raw()
}
pub unsafe fn MulDiv(machine: &mut Machine, esp: u32) -> u32 {
Expand Down Expand Up @@ -2949,6 +2949,12 @@ pub mod kernel32 {
winapi::kernel32::SetUnhandledExceptionFilter(machine, _lpTopLevelExceptionFilter)
.to_raw()
}
pub unsafe fn SizeofResource(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let hModule = <HMODULE>::from_stack(mem, esp + 4u32);
let hResInfo = <HRSRC>::from_stack(mem, esp + 8u32);
winapi::kernel32::SizeofResource(machine, hModule, hResInfo).to_raw()
}
pub unsafe fn Sleep(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let dwMilliseconds = <u32>::from_stack(mem, esp + 4u32);
Expand Down Expand Up @@ -3946,6 +3952,12 @@ pub mod kernel32 {
stack_consumed: 4u32,
is_async: false,
};
pub const SizeofResource: Shim = Shim {
name: "SizeofResource",
func: impls::SizeofResource,
stack_consumed: 8u32,
is_async: false,
};
pub const Sleep: Shim = Shim {
name: "Sleep",
func: impls::Sleep,
Expand Down Expand Up @@ -4085,7 +4097,7 @@ pub mod kernel32 {
is_async: true,
};
}
const SHIMS: [Shim; 148usize] = [
const SHIMS: [Shim; 149usize] = [
shims::AcquireSRWLockExclusive,
shims::AcquireSRWLockShared,
shims::AddVectoredExceptionHandler,
Expand Down Expand Up @@ -4211,6 +4223,7 @@ pub mod kernel32 {
shims::SetThreadPriority,
shims::SetThreadStackGuarantee,
shims::SetUnhandledExceptionFilter,
shims::SizeofResource,
shims::Sleep,
shims::SystemTimeToFileTime,
shims::TlsAlloc,
Expand Down
4 changes: 3 additions & 1 deletion win32/src/winapi/kernel32/init.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Process initialization and startup.
use super::{FindHandle, Mappings, DLL, HMODULE, STDERR_HFILE, STDOUT_HFILE};
use super::{FindHandle, Mappings, ResourceHandle, DLL, HMODULE, STDERR_HFILE, STDOUT_HFILE};
use crate::{
machine::MemImpl,
pe,
Expand Down Expand Up @@ -209,6 +209,7 @@ pub struct State {
pub dlls: HashMap<HMODULE, DLL>,

pub resources: pe::IMAGE_DATA_DIRECTORY,
pub resource_handles: Handles<HRSRC, ResourceHandle>,

pub files: Handles<HFILE, Box<dyn crate::host::File>>,

Expand Down Expand Up @@ -248,6 +249,7 @@ impl State {
env: env_addr,
cmdline,
resources: Default::default(),
resource_handles: Default::default(),
}
}

Expand Down
48 changes: 37 additions & 11 deletions win32/src/winapi/kernel32/resource.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![allow(non_snake_case)]

use crate::winapi::kernel32::HMODULE;
use crate::winapi::types::HRSRC;
use crate::winapi::user32::HINSTANCE;
use crate::{
pe,
Expand All @@ -12,13 +13,16 @@ use crate::{
Machine,
};
use memory::Mem;
use std::ops::Range;

const TRACE_CONTEXT: &'static str = "kernel32/resource";

fn IS_INTRESOURCE(x: u32) -> bool {
x >> 16 == 0
}

pub struct ResourceHandle(HMODULE, Range<usize>);

/// ResourceKey is the type of queries into the Windows resources system, including
/// e.g. LoadResource() as well as LoadBitmap() etc.
/// It's parameterized over the type of name to handle both A() and W() variants.
Expand Down Expand Up @@ -77,18 +81,18 @@ pub fn find_resource<'a>(
hInstance: HINSTANCE,
typ: ResourceKey<&Str16>,
name: ResourceKey<&Str16>,
) -> Option<&'a [u8]> {
) -> Option<Range<usize>> {
let image = mem.slice(hInstance..);
if hInstance == kernel32.image_base {
let section = kernel32.resources.as_slice(image)?;
Some(&image[pe::find_resource(section, typ.into_pe(), name.into_pe())?])
pe::find_resource(section, typ.into_pe(), name.into_pe())
} else {
let dll = kernel32.dlls.get(&HMODULE::from_raw(hInstance))?;
match dll.dll.resources.clone() {
None => return None,
Some(resources) => {
let section = resources.as_slice(image)?;
Some(&image[pe::find_resource(section, typ.into_pe(), name.into_pe())?])
pe::find_resource(section, typ.into_pe(), name.into_pe())
}
}
}
Expand All @@ -100,7 +104,7 @@ pub fn FindResourceA(
hModule: HMODULE,
lpName: ResourceKey<&str>,
lpType: ResourceKey<&str>,
) -> u32 {
) -> HRSRC {
let name = lpName.to_string16();
let type_ = lpType.to_string16();
FindResourceW(machine, hModule, name.as_ref(), type_.as_ref())
Expand All @@ -112,25 +116,47 @@ pub fn FindResourceW(
hModule: HMODULE,
lpName: ResourceKey<&Str16>,
lpType: ResourceKey<&Str16>,
) -> u32 {
) -> HRSRC {
match find_resource(
&machine.state.kernel32,
machine.mem(),
hModule.to_raw(),
lpType,
lpName,
) {
None => 0,
Some(mem) => machine.mem().offset_of(mem.as_ptr()),
None => HRSRC::null(),
Some(mem) => {
let handle = ResourceHandle(hModule.clone(), mem);
machine.state.kernel32.resource_handles.add(handle)
},
}
}

#[win32_derive::dllexport]
pub fn LoadResource(_machine: &mut Machine, hModule: u32, hResInfo: u32) -> u32 {
hResInfo
pub fn LoadResource(machine: &mut Machine, hModule: HMODULE, hResInfo: HRSRC) -> u32 {
hResInfo.to_raw()
}

#[win32_derive::dllexport]
pub fn LockResource(_machine: &mut Machine, hResData: u32) -> u32 {
hResData
pub fn LockResource(machine: &mut Machine, hResData: HRSRC) -> u32 {
let handle = match machine.state.kernel32.resource_handles.get(hResData) {
None => return 0,
Some(handle) => handle,
};

let mem = machine.mem();
let hInstance = handle.0.to_raw();
let image = mem.slice(hInstance..);

let resource = &image[handle.1.clone()];

machine.mem().offset_of(resource.as_ptr())
}

#[win32_derive::dllexport]
pub fn SizeofResource(machine: &mut Machine, hModule: HMODULE, hResInfo: HRSRC) -> u32 {
match machine.state.kernel32.resource_handles.get(hResInfo) {
None => 0,
Some(handle) => handle.1.len() as u32,
}
}
4 changes: 4 additions & 0 deletions win32/src/winapi/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ pub type HFILE = HANDLE<HFILET>;
pub struct HFINDT;
pub type HFIND = HANDLE<HFINDT>;

#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct HRSRCT;
pub type HRSRC = HANDLE<HRSRCT>;

#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct HWNDT;
pub type HWND = HANDLE<HWNDT>;
Expand Down
4 changes: 4 additions & 0 deletions win32/src/winapi/user32/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ fn load_bitmap(
ResourceKey::Id(pe::RT::BITMAP as u32),
name,
)?;
let image = machine.mem().slice(hInstance..);
let buf = &image[buf];
let bmp = BitmapRGBA32::parse(buf, None);
Some(
machine
Expand Down Expand Up @@ -166,6 +168,8 @@ fn find_string(machine: &Machine, hInstance: HINSTANCE, uID: u32) -> Option<&[u8
ResourceKey::Id(pe::RT::STRING as u32),
ResourceKey::Id(resource_id),
)?;
let image = machine.mem().slice(hInstance..);
let block = &image[block];

// Each block is a sequence of two byte length-prefixed strings.
// Iterate through them to find the requested index.
Expand Down

0 comments on commit 8225a59

Please sign in to comment.