use std::ffi::OsStr;
use std::io;
use std::os::windows::io::AsRawHandle;
use std::ptr;
use std::sync::Arc;
use windows_sys::Win32::Foundation::ERROR_SUCCESS;
use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_SUBLAYER0;
use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FwpmSubLayerAdd0;
use windows_sys::core::GUID;
use crate::transaction::Transaction;
use crate::util::string_to_null_terminated_utf16;
#[derive(Clone)]
pub struct SubLayerBuilder<Name> {
sublayer: FWPM_SUBLAYER0,
display_data_name_buffer: Arc<[u16]>,
display_data_desc_buffer: Arc<[u16]>,
provider_key: Option<Arc<GUID>>,
_pd: std::marker::PhantomData<Name>,
}
#[doc(hidden)]
pub struct SubLayerBuilderMissingName;
#[doc(hidden)]
pub struct SubLayerBuilderHasName;
impl Default for SubLayerBuilder<SubLayerBuilderMissingName> {
fn default() -> SubLayerBuilder<SubLayerBuilderMissingName> {
SubLayerBuilder {
sublayer: Default::default(),
display_data_name_buffer: Default::default(),
display_data_desc_buffer: Default::default(),
provider_key: None,
_pd: Default::default(),
}
}
}
impl<Name> SubLayerBuilder<Name> {
pub fn name(mut self, name: impl AsRef<OsStr>) -> SubLayerBuilder<SubLayerBuilderHasName> {
self.display_data_name_buffer = string_to_null_terminated_utf16(name);
self.sublayer.displayData.name = self.display_data_name_buffer.as_ptr() as *mut _;
SubLayerBuilder {
sublayer: self.sublayer,
display_data_name_buffer: self.display_data_name_buffer,
display_data_desc_buffer: self.display_data_desc_buffer,
provider_key: self.provider_key,
_pd: std::marker::PhantomData,
}
}
pub fn description(mut self, desc: impl AsRef<OsStr>) -> SubLayerBuilder<Name> {
self.display_data_desc_buffer = string_to_null_terminated_utf16(desc);
self.sublayer.displayData.description = self.display_data_desc_buffer.as_ptr() as *mut _;
SubLayerBuilder {
sublayer: self.sublayer,
display_data_name_buffer: self.display_data_name_buffer,
display_data_desc_buffer: self.display_data_desc_buffer,
provider_key: self.provider_key,
_pd: std::marker::PhantomData,
}
}
pub fn weight(mut self, weight: u16) -> SubLayerBuilder<Name> {
self.sublayer.weight = weight;
self
}
pub fn guid(mut self, guid: GUID) -> SubLayerBuilder<Name> {
self.sublayer.subLayerKey = guid;
self
}
pub fn provider(mut self, guid: GUID) -> SubLayerBuilder<Name> {
let key = Arc::new(guid);
self.sublayer.providerKey = Arc::as_ptr(&key) as *mut _;
self.provider_key = Some(key);
self
}
}
impl SubLayerBuilder<SubLayerBuilderHasName> {
pub fn add<'a>(&self, transaction: &Transaction<'a>) -> io::Result<()> {
let status = unsafe {
FwpmSubLayerAdd0(
transaction.engine.as_raw_handle(),
&self.sublayer,
ptr::null_mut(),
)
};
if status != ERROR_SUCCESS {
return Err(io::Error::from_raw_os_error(status as i32));
}
Ok(())
}
}