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_PROVIDER_FLAG_PERSISTENT, FWPM_PROVIDER0, FwpmProviderAdd0, FwpmProviderDeleteByKey0,
};
use windows_sys::core::GUID;
use crate::transaction::Transaction;
use crate::util::string_to_null_terminated_utf16;
#[derive(Clone)]
pub struct ProviderBuilder<Name> {
provider: FWPM_PROVIDER0,
display_data_name_buffer: Arc<[u16]>,
display_data_desc_buffer: Arc<[u16]>,
service_name_buffer: Option<Arc<[u16]>>,
_pd: std::marker::PhantomData<Name>,
}
#[doc(hidden)]
pub struct ProviderBuilderMissingName;
#[doc(hidden)]
pub struct ProviderBuilderHasName;
impl Default for ProviderBuilder<ProviderBuilderMissingName> {
fn default() -> ProviderBuilder<ProviderBuilderMissingName> {
ProviderBuilder {
provider: Default::default(),
display_data_name_buffer: Default::default(),
display_data_desc_buffer: Default::default(),
service_name_buffer: None,
_pd: Default::default(),
}
}
}
impl<Name> ProviderBuilder<Name> {
pub fn name(mut self, name: impl AsRef<OsStr>) -> ProviderBuilder<ProviderBuilderHasName> {
self.display_data_name_buffer = string_to_null_terminated_utf16(name);
self.provider.displayData.name = self.display_data_name_buffer.as_ptr() as *mut _;
ProviderBuilder {
provider: self.provider,
display_data_name_buffer: self.display_data_name_buffer,
display_data_desc_buffer: self.display_data_desc_buffer,
service_name_buffer: self.service_name_buffer,
_pd: std::marker::PhantomData,
}
}
pub fn description(mut self, desc: impl AsRef<OsStr>) -> ProviderBuilder<Name> {
self.display_data_desc_buffer = string_to_null_terminated_utf16(desc);
self.provider.displayData.description = self.display_data_desc_buffer.as_ptr() as *mut _;
self
}
pub fn guid(mut self, guid: GUID) -> ProviderBuilder<Name> {
self.provider.providerKey = guid;
self
}
pub fn persistent(mut self) -> ProviderBuilder<Name> {
self.provider.flags |= FWPM_PROVIDER_FLAG_PERSISTENT;
self
}
pub fn service_name(mut self, service: impl AsRef<OsStr>) -> ProviderBuilder<Name> {
let buf: Arc<[u16]> = string_to_null_terminated_utf16(service);
self.provider.serviceName = buf.as_ptr() as *mut _;
self.service_name_buffer = Some(buf);
self
}
}
impl ProviderBuilder<ProviderBuilderHasName> {
pub fn add<'a>(&self, transaction: &Transaction<'a>) -> io::Result<()> {
let status = unsafe {
FwpmProviderAdd0(
transaction.engine.as_raw_handle(),
&self.provider,
ptr::null_mut(),
)
};
if status != ERROR_SUCCESS {
return Err(io::Error::from_raw_os_error(status as i32));
}
Ok(())
}
}
pub fn delete_provider<'a>(transaction: &Transaction<'a>, guid: &GUID) -> io::Result<()> {
let status = unsafe { FwpmProviderDeleteByKey0(transaction.engine.as_raw_handle(), guid) };
if status != ERROR_SUCCESS {
return Err(io::Error::from_raw_os_error(status as i32));
}
Ok(())
}