Skip to content

Commit

Permalink
guessing at kernel32 functions
Browse files Browse the repository at this point in the history
  • Loading branch information
brandonros committed Dec 30, 2024
1 parent 77f2f6c commit 24672ea
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 4 deletions.
5 changes: 5 additions & 0 deletions libmwemu/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ pub const STATUS_ACCESS_VIOLATION: u64 = 0xC0000005;
pub const STATUS_INVALID_PARAMETER: u64 = 0xC000000D;

pub const ERROR_SUCCESS: u64 = 0;
pub const ERROR_INVALID_PARAMETER: u64 = 0x57;
pub const ERROR_INSUFFICIENT_BUFFER: u64 = 122;

pub const CP_UTF7: u64 = 65000;
pub const CP_UTF8: u64 = 65001;

pub const NUM_BYTES_TRACE: usize = 16;
pub const VERSION: u64 = 0x1db10106;
Expand Down
59 changes: 55 additions & 4 deletions libmwemu/src/winapi64/kernel32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3164,10 +3164,10 @@ int WideCharToMultiByte(
);
*/
fn WideCharToMultiByte(emu: &mut emu::Emu) {
let code_page = emu.regs.rcx as usize;
let code_page = emu.regs.rcx as u64;
let dw_flags = emu.regs.rdx as usize;
let lp_wide_char_str = emu.regs.r8 as usize;
let cch_wide_char = emu.regs.r9 as usize;
let cch_wide_char = emu.regs.r9 as isize;
let lp_multi_byte_str = emu
.maps
.read_qword(emu.regs.rsp)
Expand Down Expand Up @@ -3197,11 +3197,62 @@ fn WideCharToMultiByte(emu: &mut emu::Emu) {
lp_used_default_char
);

// 1. Input validation
if lp_wide_char_str == 0 {
emu.regs.rax = 0;
return;
}

// 2. Handle special code pages
if code_page == constants::CP_UTF7 || code_page == constants::CP_UTF8 {
if lp_default_char != 0 || lp_used_default_char != 0 {
// Set last error to ERROR_INVALID_PARAMETER
let mut err = LAST_ERROR.lock().unwrap();
*err = constants::ERROR_INVALID_PARAMETER;
emu.regs.rax = 0;
return;
}
}

// 3. Read input string and get its length
let s = emu.maps.read_wide_string(lp_wide_char_str as u64);
if lp_multi_byte_str > 0 && s.len() > 0 {
let input_len = if cch_wide_char == -1 {
s.len()
} else {
cch_wide_char as usize
};

// 4. If this is just a size query
if cb_multi_byte == 0 {
emu.regs.rax = input_len as u64;
return;
}

// 5. Check output buffer size
if cb_multi_byte < input_len as u64 {
// Set last error to ERROR_INSUFFICIENT_BUFFER
let mut err = LAST_ERROR.lock().unwrap();
*err = constants::ERROR_INSUFFICIENT_BUFFER;
emu.regs.rax = 0;
return;
}

// 6. Perform the actual conversion
if lp_multi_byte_str > 0 && !s.is_empty() {
emu.maps.write_string(lp_multi_byte_str, &s);

// Set used default char flag if requested
if lp_used_default_char != 0 {
emu.maps.write_byte(lp_used_default_char, 0); // For this simple implementation, assume no defaults needed
}
}
emu.regs.rax = s.len() as u64 + 2;

// 7. Return number of bytes written
emu.regs.rax = if cch_wide_char == -1 {
(s.len() + 1) as u64 // Include null terminator
} else {
s.len() as u64
};
}

/*
Expand Down

0 comments on commit 24672ea

Please sign in to comment.