use std::ffi::OsStr;
use std::io;
use std::iter;
use std::os::windows::ffi::OsStrExt;
use std::os::windows::io::AsRawHandle;
use std::ptr;
use windows_sys::Win32::Foundation::ERROR_SUCCESS;
use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_FILTER_CONDITION0;
use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_FILTER0;
use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FwpmFilterAdd0;
use windows_sys::core::GUID;
use crate::action::ActionType;
use crate::condition::Condition;
use crate::layer::Layer;
use crate::transaction::Transaction;
#[derive(Clone)]
pub struct FilterBuilder<Name, Action> {
filter: FWPM_FILTER0,
display_data_name_buffer: Vec<u16>,
display_data_desc_buffer: Vec<u16>,
conditions: Vec<Condition>,
_pd: std::marker::PhantomData<(Name, Action)>,
}
#[doc(hidden)]
#[derive(Default)]
pub struct FilterBuilderMissingName;
#[doc(hidden)]
pub struct FilterBuilderHasName;
#[doc(hidden)]
#[derive(Default)]
pub struct FilterBuilderMissingAction;
#[doc(hidden)]
pub struct FilterBuilderHasAction;
impl Default for FilterBuilder<FilterBuilderMissingName, FilterBuilderMissingAction> {
fn default() -> Self {
FilterBuilder {
filter: Default::default(),
display_data_name_buffer: Default::default(),
display_data_desc_buffer: Default::default(),
conditions: Default::default(),
_pd: Default::default(),
}
}
}
impl<Name, Action> FilterBuilder<Name, Action> {
pub fn name(mut self, name: impl AsRef<OsStr>) -> FilterBuilder<FilterBuilderHasName, Action> {
self.display_data_name_buffer = name
.as_ref()
.encode_wide()
.chain(iter::once(0u16))
.collect();
self.filter.displayData.name = self.display_data_name_buffer.as_mut_ptr();
FilterBuilder {
filter: self.filter,
display_data_name_buffer: self.display_data_name_buffer,
display_data_desc_buffer: self.display_data_desc_buffer,
conditions: self.conditions,
_pd: std::marker::PhantomData,
}
}
pub fn description(mut self, desc: impl AsRef<OsStr>) -> FilterBuilder<Name, Action> {
self.display_data_desc_buffer = desc
.as_ref()
.encode_wide()
.chain(iter::once(0u16))
.collect();
self.filter.displayData.description = self.display_data_desc_buffer.as_mut_ptr();
FilterBuilder {
filter: self.filter,
display_data_name_buffer: self.display_data_name_buffer,
display_data_desc_buffer: self.display_data_desc_buffer,
conditions: self.conditions,
_pd: std::marker::PhantomData,
}
}
pub fn action(mut self, action: ActionType) -> FilterBuilder<Name, FilterBuilderHasAction> {
self.filter.action.r#type = action as u32;
FilterBuilder {
filter: self.filter,
display_data_name_buffer: self.display_data_name_buffer,
display_data_desc_buffer: self.display_data_desc_buffer,
conditions: self.conditions,
_pd: std::marker::PhantomData,
}
}
pub fn layer(mut self, layer: Layer) -> FilterBuilder<Name, Action> {
self.filter.layerKey = *layer.guid();
self
}
pub fn sublayer(mut self, sublayer: GUID) -> FilterBuilder<Name, Action> {
self.filter.subLayerKey = sublayer;
self
}
pub fn condition(mut self, condition: Condition) -> FilterBuilder<Name, Action> {
self.conditions.push(condition);
self
}
}
impl FilterBuilder<FilterBuilderHasName, FilterBuilderHasAction> {
pub fn add<'a>(&self, transaction: &Transaction<'a>) -> io::Result<()> {
let fwpm_conditions: Vec<FWPM_FILTER_CONDITION0> = self
.conditions
.iter()
.map(|condition| *condition.raw_condition())
.collect();
let mut filter = self.filter;
if !fwpm_conditions.is_empty() {
filter.numFilterConditions = u32::try_from(fwpm_conditions.len()).unwrap();
filter.filterCondition = fwpm_conditions.as_ptr() as *mut _;
}
let status = unsafe {
FwpmFilterAdd0(
transaction.engine.as_raw_handle(),
&filter,
ptr::null_mut(),
ptr::null_mut(),
)
};
if status != ERROR_SUCCESS {
return Err(io::Error::from_raw_os_error(status as i32));
}
Ok(())
}
}