Skip to main content

windows_wfp/
errors.rs

1//! WFP error types
2//!
3//! Error types for Windows Filtering Platform operations.
4
5use thiserror::Error;
6use windows::Win32::Foundation::WIN32_ERROR;
7
8/// WFP operation errors
9#[derive(Error, Debug)]
10pub enum WfpError {
11    /// Failed to open WFP engine session
12    #[error("Failed to open WFP engine session")]
13    EngineOpenFailed,
14
15    /// Failed to close WFP engine session
16    #[error("Failed to close WFP engine session")]
17    EngineCloseFailed,
18
19    /// Failed to add filter
20    #[error("Failed to add filter: {0}")]
21    FilterAddFailed(String),
22
23    /// Failed to delete filter
24    #[error("Failed to delete filter: {0}")]
25    FilterDeleteFailed(String),
26
27    /// Failed to begin transaction
28    #[error("Failed to begin WFP transaction")]
29    TransactionBeginFailed,
30
31    /// Failed to commit transaction
32    #[error("Failed to commit WFP transaction")]
33    TransactionCommitFailed,
34
35    /// Failed to abort transaction
36    #[error("Failed to abort WFP transaction")]
37    TransactionAbortFailed,
38
39    /// Insufficient permissions (must run as administrator)
40    #[error("Insufficient permissions - administrator privileges required")]
41    InsufficientPermissions,
42
43    /// WFP service not available
44    #[error("Windows Filtering Platform service not available")]
45    ServiceNotAvailable,
46
47    /// Win32 API error with code and message
48    #[error("Win32 error {code}: {message}")]
49    Win32Error { code: u32, message: String },
50
51    /// Generic error with description
52    #[error("{0}")]
53    Other(String),
54}
55
56impl From<WIN32_ERROR> for WfpError {
57    fn from(error: WIN32_ERROR) -> Self {
58        let code = error.0;
59        let message = match code {
60            5 => "Access denied".to_string(),
61            1062 => "Service not started".to_string(),
62            1075 => "Service dependency does not exist".to_string(),
63            _ => format!("Unknown Win32 error: {}", code),
64        };
65
66        WfpError::Win32Error { code, message }
67    }
68}
69
70pub type WfpResult<T> = std::result::Result<T, WfpError>;
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    #[test]
77    fn test_error_display_messages() {
78        assert_eq!(
79            WfpError::EngineOpenFailed.to_string(),
80            "Failed to open WFP engine session"
81        );
82        assert_eq!(
83            WfpError::InsufficientPermissions.to_string(),
84            "Insufficient permissions - administrator privileges required"
85        );
86        assert_eq!(
87            WfpError::ServiceNotAvailable.to_string(),
88            "Windows Filtering Platform service not available"
89        );
90        assert_eq!(
91            WfpError::TransactionBeginFailed.to_string(),
92            "Failed to begin WFP transaction"
93        );
94        assert_eq!(
95            WfpError::TransactionCommitFailed.to_string(),
96            "Failed to commit WFP transaction"
97        );
98        assert_eq!(
99            WfpError::TransactionAbortFailed.to_string(),
100            "Failed to abort WFP transaction"
101        );
102    }
103
104    #[test]
105    fn test_error_display_with_details() {
106        let err = WfpError::FilterAddFailed("test error".into());
107        assert_eq!(err.to_string(), "Failed to add filter: test error");
108
109        let err = WfpError::FilterDeleteFailed("filter 42".into());
110        assert_eq!(err.to_string(), "Failed to delete filter: filter 42");
111
112        let err = WfpError::Other("something happened".into());
113        assert_eq!(err.to_string(), "something happened");
114    }
115
116    #[test]
117    fn test_win32_error_display() {
118        let err = WfpError::Win32Error {
119            code: 5,
120            message: "Access denied".into(),
121        };
122        assert_eq!(err.to_string(), "Win32 error 5: Access denied");
123    }
124
125    #[test]
126    fn test_win32_error_conversion_access_denied() {
127        let err: WfpError = WIN32_ERROR(5).into();
128        match err {
129            WfpError::Win32Error { code, message } => {
130                assert_eq!(code, 5);
131                assert_eq!(message, "Access denied");
132            }
133            _ => panic!("Expected Win32Error"),
134        }
135    }
136
137    #[test]
138    fn test_win32_error_conversion_service_not_started() {
139        let err: WfpError = WIN32_ERROR(1062).into();
140        match err {
141            WfpError::Win32Error { code, message } => {
142                assert_eq!(code, 1062);
143                assert_eq!(message, "Service not started");
144            }
145            _ => panic!("Expected Win32Error"),
146        }
147    }
148
149    #[test]
150    fn test_win32_error_conversion_dependency_missing() {
151        let err: WfpError = WIN32_ERROR(1075).into();
152        match err {
153            WfpError::Win32Error { code, message } => {
154                assert_eq!(code, 1075);
155                assert_eq!(message, "Service dependency does not exist");
156            }
157            _ => panic!("Expected Win32Error"),
158        }
159    }
160
161    #[test]
162    fn test_win32_error_conversion_unknown() {
163        let err: WfpError = WIN32_ERROR(9999).into();
164        match err {
165            WfpError::Win32Error { code, message } => {
166                assert_eq!(code, 9999);
167                assert!(message.contains("Unknown"));
168            }
169            _ => panic!("Expected Win32Error"),
170        }
171    }
172}