slightly tweak features::game_networking design & add visual indicator for blocking failing due to game being closed

This commit is contained in:
2025-04-20 01:25:25 +01:00
parent 10168e84d1
commit ccc27b1944
3 changed files with 86 additions and 20 deletions
+77 -15
View File
@@ -1,5 +1,11 @@
use crate::util::consts::game::{EXE_ENHANCED, EXE_LEGACY};
use std::path::Path;
use crate::util::consts::{
colours,
game::{EXE_ENHANCED, EXE_LEGACY},
};
use std::{
path::Path,
time::{Duration, Instant},
};
use sysinfo::System;
use windows::{
Win32::{
@@ -13,28 +19,63 @@ use windows::{
CoUninitialize,
},
},
core::{BSTR, HRESULT},
core::BSTR,
};
const FILTER_NAME_IN: &str = "[GTA Tools] Block all inbound traffic for GTA V";
const FILTER_NAME_OUT: &str = "[GTA Tools] Block all outbound traffic for GTA V";
const INTERVAL: Duration = Duration::from_secs(3);
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum BlockedStatus {
Blocked,
Failed,
Unblocked,
}
impl From<bool> for BlockedStatus {
fn from(value: bool) -> Self {
match value {
true => Self::Blocked,
false => Self::Unblocked,
}
}
}
impl From<BlockedStatus> for eframe::egui::Color32 {
fn from(value: BlockedStatus) -> Self {
match value {
BlockedStatus::Blocked => colours::RED,
BlockedStatus::Failed => colours::YELLOW,
BlockedStatus::Unblocked => colours::GREEN,
}
}
}
impl BlockedStatus {
pub fn to_color32(&self) -> eframe::egui::Color32 {
(*self).into()
}
}
#[derive(Debug)]
pub struct GameNetworking {
pub is_blocked: bool,
com_initialized: bool,
policy: INetFwPolicy2,
pub blocked_status: BlockedStatus,
timer: Instant,
counting: bool,
}
impl Default for GameNetworking {
fn default() -> Self {
let result = unsafe { CoInitializeEx(None, COINIT_MULTITHREADED) };
let mut gn = Self {
is_blocked: false,
com_initialized: result != HRESULT(0x80010106u32 as i32),
policy: unsafe { CoCreateInstance(&NetFwPolicy2, None, CLSCTX_INPROC_SERVER).unwrap() },
blocked_status: BlockedStatus::Unblocked,
com_initialized: unsafe { CoInitializeEx(None, COINIT_MULTITHREADED) }.is_ok(),
timer: Instant::now(),
counting: false,
};
gn.is_blocked = gn.is_blocked();
gn.blocked_status = gn.is_blocked().into();
gn
}
}
@@ -52,9 +93,12 @@ impl Drop for GameNetworking {
impl GameNetworking {
pub fn block_all(&mut self, sysinfo: &mut System) {
let Some(exe_path) = get_game_exe_path(sysinfo) else {
self.blocked_status = BlockedStatus::Failed;
return;
};
let rules = unsafe { self.policy.Rules().unwrap() };
let policy: INetFwPolicy2 =
unsafe { CoCreateInstance(&NetFwPolicy2, None, CLSCTX_INPROC_SERVER).unwrap() };
let rules = unsafe { policy.Rules().unwrap() };
let filter_name_in = BSTR::from(FILTER_NAME_IN);
let filter_name_out = BSTR::from(FILTER_NAME_OUT);
unsafe {
@@ -84,11 +128,13 @@ impl GameNetworking {
outbound_rule.SetProtocol(NET_FW_IP_PROTOCOL_ANY.0).unwrap();
rules.Add(&outbound_rule).unwrap();
}
self.is_blocked = self.is_blocked();
self.blocked_status = self.is_blocked().into();
}
pub fn unblock_all(&mut self) {
let rules = unsafe { self.policy.Rules().unwrap() };
let policy: INetFwPolicy2 =
unsafe { CoCreateInstance(&NetFwPolicy2, None, CLSCTX_INPROC_SERVER).unwrap() };
let rules = unsafe { policy.Rules().unwrap() };
unsafe {
let result = rules.Remove(&BSTR::from(FILTER_NAME_IN));
if let Err(ref why) = result {
@@ -103,15 +149,31 @@ impl GameNetworking {
}
}
}
self.is_blocked = self.is_blocked();
self.blocked_status = self.is_blocked().into();
}
fn is_blocked(&self) -> bool {
let rules = unsafe { self.policy.Rules().unwrap() };
let policy: INetFwPolicy2 =
unsafe { CoCreateInstance(&NetFwPolicy2, None, CLSCTX_INPROC_SERVER).unwrap() };
let rules = unsafe { policy.Rules().unwrap() };
let in_rule_exists = unsafe { rules.Item(&BSTR::from(FILTER_NAME_IN)).is_ok() };
let out_rule_exists = unsafe { rules.Item(&BSTR::from(FILTER_NAME_OUT)).is_ok() };
in_rule_exists || out_rule_exists
}
pub fn if_failed_return_to_unblocked(&mut self) {
if self.blocked_status == BlockedStatus::Failed && !self.counting {
self.counting = true;
self.timer = Instant::now();
}
if self.blocked_status == BlockedStatus::Failed
&& self.counting
&& self.timer.elapsed() >= INTERVAL
{
self.counting = false;
self.blocked_status = BlockedStatus::Unblocked;
};
}
}
fn get_game_exe_path(sysinfo: &mut System) -> Option<&Path> {