81 lines
2.1 KiB
Rust
81 lines
2.1 KiB
Rust
use crate::util::{
|
|
consts::game::{EXE_ENHANCED, EXE_LEGACY},
|
|
countdown::Countdown,
|
|
system_info::SystemInfo,
|
|
};
|
|
use std::time::{Duration, Instant};
|
|
use windows::Win32::{
|
|
Foundation::{HANDLE, NTSTATUS},
|
|
System::Threading::{OpenProcess, PROCESS_SUSPEND_RESUME},
|
|
};
|
|
|
|
const INTERVAL: Duration = Duration::from_secs(10);
|
|
|
|
#[derive(Debug)]
|
|
pub struct EmptySession {
|
|
pub disabled: bool,
|
|
pub interval: Instant,
|
|
pub countdown: Countdown,
|
|
}
|
|
|
|
impl Default for EmptySession {
|
|
fn default() -> Self {
|
|
Self {
|
|
disabled: false,
|
|
interval: Instant::now(),
|
|
countdown: Countdown::new(INTERVAL.as_secs()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl EmptySession {
|
|
pub fn run_timers(&mut self, game_handle: &mut HANDLE) {
|
|
if self.disabled {
|
|
self.countdown.count();
|
|
} else {
|
|
self.countdown.reset();
|
|
}
|
|
if self.interval.elapsed() >= INTERVAL {
|
|
deactivate(game_handle);
|
|
self.disabled = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
#[link(name = "ntdll")]
|
|
unsafe extern "system" {
|
|
unsafe fn NtSuspendProcess(ProcessHandle: HANDLE) -> NTSTATUS;
|
|
unsafe fn NtResumeProcess(ProcessHandle: HANDLE) -> NTSTATUS;
|
|
}
|
|
|
|
fn get_gta_pid(system_info: &mut SystemInfo) -> Option<u32> {
|
|
system_info.refresh();
|
|
system_info
|
|
.processes()
|
|
.iter()
|
|
.find(|p| p.name() == EXE_ENHANCED || p.name() == EXE_LEGACY)
|
|
.map(|p| p.pid())
|
|
}
|
|
|
|
pub fn activate(game_handle: &mut HANDLE, system_info: &mut SystemInfo) -> bool {
|
|
let Some(pid) = get_gta_pid(system_info) else {
|
|
return false;
|
|
};
|
|
match unsafe { OpenProcess(PROCESS_SUSPEND_RESUME, false, pid) } {
|
|
Ok(handle) => *game_handle = handle,
|
|
Err(why) => {
|
|
log::error!("failed to suspend game for empty session:\n{why}");
|
|
return false;
|
|
}
|
|
}
|
|
unsafe { NtSuspendProcess(*game_handle) }.unwrap();
|
|
true
|
|
}
|
|
|
|
pub fn deactivate(game_handle: &mut HANDLE) {
|
|
if !game_handle.is_invalid() {
|
|
// ignoring the return because this function behaves very weirdly
|
|
let _ = unsafe { NtResumeProcess(*game_handle) };
|
|
}
|
|
}
|