use crate::winapi::winapi64::kernel32::{clear_last_error, LAST_ERROR};
use crate::{windows::constants, emu};
pub fn WideCharToMultiByte(emu: &mut emu::Emu) {
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 isize;
let lp_multi_byte_str = emu
.maps
.read_qword(emu.regs().rsp + 0x20)
.expect("kernel32!WideCharToMultiByte error reading param");
let cb_multi_byte = emu
.maps
.read_qword(emu.regs().rsp + 0x28)
.expect("kernel32!WideCharToMultiByte error reading param");
let lp_default_char = emu
.maps
.read_qword(emu.regs().rsp + 0x30)
.expect("kernel32!WideCharToMultiByte error reading param");
let lp_used_default_char = emu
.maps
.read_qword(emu.regs().rsp + 0x38)
.expect("kernel32!WideCharToMultiByte error reading param");
log_red!(emu, "** {}:{:x} kernel32!WideCharToMultiByte code_page: {} dw_flags: {} lp_wide_char_str: 0x{:x} cch_wide_char: {} lp_multi_byte_str: 0x{:x} cb_multi_byte: {} lp_default_char: 0x{:x} lp_used_default_char: 0x{:x}",
emu.pos,
emu.regs().rip,
code_page,
dw_flags,
lp_wide_char_str,
cch_wide_char,
lp_multi_byte_str,
cb_multi_byte,
lp_default_char,
lp_used_default_char
);
if lp_wide_char_str == 0 {
log::warn!("{} kernel32!WideCharToMultiByte invalid parameter", emu.pos);
let mut err = LAST_ERROR.lock().unwrap();
*err = constants::ERROR_INVALID_PARAMETER;
emu.regs_mut().rax = 0;
return;
}
if code_page == constants::CP_UTF7 || code_page == constants::CP_UTF8 {
if lp_default_char != 0 || lp_used_default_char != 0 {
log::warn!("{} kernel32!WideCharToMultiByte invalid parameter", emu.pos);
let mut err = LAST_ERROR.lock().unwrap();
*err = constants::ERROR_INVALID_PARAMETER;
emu.regs_mut().rax = 0;
return;
}
}
let s = emu.maps.read_wide_string(lp_wide_char_str as u64);
let input_len = if cch_wide_char == -1 {
s.len()
} else {
cch_wide_char as usize
};
if cb_multi_byte == 0 {
emu.regs_mut().rax = input_len as u64;
clear_last_error(emu);
return;
}
if cb_multi_byte < input_len as u64 {
log::warn!(
"{} buffer too small for result cb_multi_byte: {} input_len: {}",
emu.pos,
cb_multi_byte,
input_len
);
let mut err = LAST_ERROR.lock().unwrap();
*err = constants::ERROR_INSUFFICIENT_BUFFER;
emu.regs_mut().rax = 0;
return;
}
if lp_multi_byte_str > 0 && !s.is_empty() {
if lp_multi_byte_str < emu.cfg.stack_addr
|| lp_multi_byte_str > emu.cfg.stack_addr + 0x030000
{
emu.maps.write_string(lp_multi_byte_str, &s);
}
if lp_used_default_char != 0 {
emu.maps.write_byte(lp_used_default_char, 0); }
}
emu.regs_mut().rax = if cch_wide_char == -1 {
(s.len() + 1) as u64 } else {
s.len() as u64
};
clear_last_error(emu);
if lp_wide_char_str > 0 && !s.is_empty() {
log_red!(
emu,
"Input wide string: \"{}\" (length: {} characters)",
s.escape_debug(),
input_len
);
}
}