use std::io;
use std::os::windows::io::AsRawHandle;
use windows_sys::Win32::Foundation::ERROR_SUCCESS;
use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FwpmTransactionAbort0;
use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FwpmTransactionBegin0;
use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FwpmTransactionCommit0;
use crate::engine::FilterEngine;
pub struct Transaction<'a> {
pub(crate) engine: &'a mut FilterEngine,
}
unsafe impl Send for Transaction<'_> {}
impl<'a> Transaction<'a> {
pub fn new(engine: &'a mut FilterEngine) -> io::Result<Self> {
let status = unsafe { FwpmTransactionBegin0(engine.as_raw_handle(), 0) };
if status != ERROR_SUCCESS {
return Err(io::Error::from_raw_os_error(status as i32));
}
Ok(Self { engine })
}
pub fn commit(self) -> io::Result<()> {
let status = unsafe { FwpmTransactionCommit0(self.engine.as_raw_handle()) };
if status != ERROR_SUCCESS {
return Err(io::Error::from_raw_os_error(status as i32));
}
Ok(())
}
pub fn abort(self) -> io::Result<()> {
self.abort_inner()
}
fn abort_inner(&self) -> io::Result<()> {
let status = unsafe { FwpmTransactionAbort0(self.engine.as_raw_handle()) };
if status != ERROR_SUCCESS {
return Err(io::Error::from_raw_os_error(status as i32));
}
Ok(())
}
}
impl<'a> Drop for Transaction<'a> {
fn drop(&mut self) {
if let Err(err) = self.abort_inner() {
log::error!("Failed to abort dropped transaction: {err}");
}
}
}