1use crate::constants::{WFP_PROVIDER_GUID, WFP_SUBLAYER_GUID};
6use crate::engine::WfpEngine;
7use crate::errors::{WfpError, WfpResult};
8use crate::transaction::WfpTransaction;
9use std::ptr;
10use windows::core::PWSTR;
11use windows::Win32::Foundation::ERROR_SUCCESS;
12use windows::Win32::NetworkManagement::WindowsFilteringPlatform::{
13 FwpmProviderAdd0, FwpmSubLayerAdd0, FWPM_PROVIDER0, FWPM_SUBLAYER0,
14};
15
16pub struct WfpProvider;
21
22impl WfpProvider {
23 pub fn register(engine: &WfpEngine) -> WfpResult<()> {
42 let name_wide: Vec<u16> = "windows-wfp"
44 .encode_utf16()
45 .chain(std::iter::once(0))
46 .collect();
47 let desc_wide: Vec<u16> = "windows-wfp Firewall Provider"
48 .encode_utf16()
49 .chain(std::iter::once(0))
50 .collect();
51
52 let provider = FWPM_PROVIDER0 {
53 providerKey: WFP_PROVIDER_GUID,
54 displayData:
55 windows::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_DISPLAY_DATA0 {
56 name: PWSTR(name_wide.as_ptr() as *mut u16),
57 description: PWSTR(desc_wide.as_ptr() as *mut u16),
58 },
59 flags: 0,
60 providerData:
61 windows::Win32::NetworkManagement::WindowsFilteringPlatform::FWP_BYTE_BLOB {
62 size: 0,
63 data: ptr::null_mut(),
64 },
65 serviceName: PWSTR::null(),
66 };
67
68 unsafe {
69 let result = FwpmProviderAdd0(engine.handle(), &provider, None);
70
71 if result != ERROR_SUCCESS.0 {
72 if result != 0x80320009 {
74 return Err(WfpError::Other(format!(
75 "Failed to register provider: error code {}",
76 result
77 )));
78 }
79 }
80 }
81
82 Ok(())
83 }
84}
85
86pub struct WfpSublayer;
91
92impl WfpSublayer {
93 pub fn register(engine: &WfpEngine) -> WfpResult<()> {
113 let name_wide: Vec<u16> = "windows-wfp Filters"
115 .encode_utf16()
116 .chain(std::iter::once(0))
117 .collect();
118 let desc_wide: Vec<u16> = "Sublayer for windows-wfp firewall exception filters"
119 .encode_utf16()
120 .chain(std::iter::once(0))
121 .collect();
122
123 let sublayer = FWPM_SUBLAYER0 {
124 subLayerKey: WFP_SUBLAYER_GUID,
125 displayData:
126 windows::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_DISPLAY_DATA0 {
127 name: PWSTR(name_wide.as_ptr() as *mut u16),
128 description: PWSTR(desc_wide.as_ptr() as *mut u16),
129 },
130 flags: 0,
131 providerKey: &WFP_PROVIDER_GUID as *const _ as *mut _,
132 providerData:
133 windows::Win32::NetworkManagement::WindowsFilteringPlatform::FWP_BYTE_BLOB {
134 size: 0,
135 data: ptr::null_mut(),
136 },
137 weight: 0xFFFF, };
139
140 unsafe {
141 let result = FwpmSubLayerAdd0(engine.handle(), &sublayer, None);
142
143 if result != ERROR_SUCCESS.0 {
144 if result != 0x80320009 {
146 return Err(WfpError::Other(format!(
147 "Failed to register sublayer: error code {}",
148 result
149 )));
150 }
151 }
152 }
153
154 Ok(())
155 }
156}
157
158pub fn initialize_wfp(engine: &WfpEngine) -> WfpResult<()> {
178 let txn = WfpTransaction::begin(engine)?;
179
180 WfpProvider::register(engine)?;
181 WfpSublayer::register(engine)?;
182
183 txn.commit()?;
184
185 Ok(())
186}
187
188#[cfg(test)]
189mod tests {
190 use super::*;
191
192 #[test]
193 #[ignore] fn test_provider_registration() {
195 let engine = WfpEngine::new().expect("Failed to create engine");
196 let result = WfpProvider::register(&engine);
197
198 assert!(result.is_ok(), "Failed to register provider: {:?}", result);
200 }
201
202 #[test]
203 #[ignore] fn test_sublayer_registration() {
205 let engine = WfpEngine::new().expect("Failed to create engine");
206
207 WfpProvider::register(&engine).expect("Failed to register provider");
209
210 let result = WfpSublayer::register(&engine);
211 assert!(result.is_ok(), "Failed to register sublayer: {:?}", result);
212 }
213
214 #[test]
215 #[ignore] fn test_initialize_wfp() {
217 let engine = WfpEngine::new().expect("Failed to create engine");
218 let result = initialize_wfp(&engine);
219
220 assert!(result.is_ok(), "Failed to initialize WFP: {:?}", result);
221 }
222
223 #[test]
224 #[ignore] fn test_double_registration_is_idempotent() {
226 let engine = WfpEngine::new().expect("Failed to create engine");
227
228 initialize_wfp(&engine).expect("First registration failed");
230
231 let result = initialize_wfp(&engine);
233 assert!(result.is_ok(), "Double registration should be idempotent");
234 }
235}