use std::sync::atomic::{AtomicU64, Ordering};
use crate::windows::constants::*;
use crate::emu::Emu;
static NEXT_FAKE_SYNC_HANDLE: AtomicU64 = AtomicU64::new(0x1000);
pub fn next_handle() -> u64 {
NEXT_FAKE_SYNC_HANDLE.fetch_add(4, Ordering::Relaxed)
}
pub fn nt_create_event(emu: &mut Emu) {
let handle_out = emu.regs().rcx;
let desired_access = emu.regs().rdx;
let object_attributes = emu.regs().r8;
let event_type = emu.regs().r9;
let rsp = emu.regs().rsp;
let initial_state = emu.maps.read_byte(rsp + 0x28).unwrap_or(0);
log_orange!(
emu,
"syscall 0x{:x}: NtCreateEvent out: 0x{:x}, access: 0x{:x}, obj_attr: 0x{:x}, type: 0x{:x}, initial: {}",
WIN64_NTCREATEEVENT,
handle_out,
desired_access,
object_attributes,
event_type,
initial_state
);
if handle_out == 0 {
emu.regs_mut().rax = STATUS_INVALID_PARAMETER;
return;
}
if !emu.maps.is_mapped(handle_out) {
emu.regs_mut().rax = STATUS_ACCESS_VIOLATION;
return;
}
let h = next_handle();
if !emu.maps.write_qword(handle_out, h) {
emu.regs_mut().rax = STATUS_ACCESS_VIOLATION;
return;
}
emu.regs_mut().rax = STATUS_SUCCESS;
}
pub fn nt_set_event(emu: &mut Emu) {
let handle = emu.regs().rcx;
let previous_state = emu.regs().rdx;
log_orange!(
emu,
"syscall 0x{:x}: NtSetEvent handle: 0x{:x}, prev_state: 0x{:x}",
WIN64_NTSETEVENT,
handle,
previous_state
);
if previous_state != 0 && emu.maps.is_mapped(previous_state) {
emu.maps.write_dword(previous_state, 0);
}
emu.regs_mut().rax = STATUS_SUCCESS;
}
pub fn nt_wait_for_alert_by_thread_id(emu: &mut Emu) {
let unique_thread_id = emu.regs().rcx;
let timeout = emu.regs().rdx;
log_orange!(
emu,
"syscall 0x{:x}: NtWaitForAlertByThreadId thread_id: 0x{:x}, timeout_ptr: 0x{:x}",
WIN64_NTWAITFORALERTBYTHREADID,
unique_thread_id,
timeout
);
emu.regs_mut().rax = STATUS_SUCCESS;
}
pub fn nt_alpc_accept_connect_port(emu: &mut Emu) {
let handle_out = emu.regs().rcx;
let conn_port = emu.regs().rdx;
log_orange!(
emu,
"syscall 0x{:x}: NtAlpcAcceptConnectPort out: 0x{:x}, conn: 0x{:x}",
WIN64_NTALPCACCEPTCONNECTPORT,
handle_out,
conn_port,
);
if handle_out != 0 && emu.maps.is_mapped(handle_out) {
let h = next_handle();
let _ = emu.maps.write_qword(handle_out, h);
}
emu.regs_mut().rax = STATUS_SUCCESS;
}
pub fn nt_wait_for_single_object(emu: &mut Emu) {
let handle = emu.regs().rcx;
let alertable = emu.regs().rdx;
let timeout = emu.regs().r8;
log_orange!(
emu,
"syscall 0x{:x}: NtWaitForSingleObject handle: 0x{:x}, alertable: {}, timeout: 0x{:x}",
WIN64_NTWAITFORSINGLEOBJECT,
handle,
alertable,
timeout,
);
emu.regs_mut().rax = STATUS_SUCCESS; }
pub fn nt_open_event(emu: &mut Emu) {
let handle_out = emu.regs().rcx;
let desired_access = emu.regs().rdx;
let object_attr = emu.regs().r8;
log_orange!(
emu,
"syscall 0x{:x}: NtOpenEvent out: 0x{:x}, access: 0x{:x}, obj: 0x{:x}",
WIN64_NTOPENEVENT,
handle_out,
desired_access,
object_attr,
);
if handle_out == 0 || !emu.maps.is_mapped(handle_out) {
emu.regs_mut().rax = STATUS_INVALID_PARAMETER;
return;
}
let h = next_handle();
let _ = emu.maps.write_qword(handle_out, h);
emu.regs_mut().rax = STATUS_SUCCESS;
}
pub fn nt_create_timer2(emu: &mut Emu) {
let handle_out = emu.regs().rcx;
let desired_access = emu.regs().rdx;
let timer_type = emu.regs().r9;
log_orange!(
emu,
"syscall 0x{:x}: NtCreateTimer2 out: 0x{:x}, access: 0x{:x}, type: {}",
WIN64_NTCREATETIMER2,
handle_out,
desired_access,
timer_type,
);
if handle_out == 0 || !emu.maps.is_mapped(handle_out) {
emu.regs_mut().rax = STATUS_INVALID_PARAMETER;
return;
}
let h = next_handle();
let _ = emu.maps.write_qword(handle_out, h);
emu.regs_mut().rax = STATUS_SUCCESS;
}
pub fn nt_close(emu: &mut Emu) {
let handle = emu.regs().rcx;
log_orange!(
emu,
"syscall 0x{:x}: NtClose handle: 0x{:x}",
WIN64_NTCLOSE,
handle
);
emu.regs_mut().rax = STATUS_SUCCESS;
}