Skip to main content

windows_erg/
error.rs

1//! Error types for the windows-erg crate.
2
3use std::borrow::Cow;
4use std::fmt;
5
6/// Result type for windows-erg operations.
7pub type Result<T> = std::result::Result<T, Error>;
8
9/// Main error type for windows-erg.
10#[derive(Debug)]
11pub enum Error {
12    /// A Windows API error occurred.
13    WindowsApi(WindowsApiError),
14
15    /// Access was denied (insufficient permissions).
16    AccessDenied(AccessDeniedError),
17
18    /// The requested resource was not found.
19    NotFound(NotFoundError),
20
21    /// An invalid parameter was provided.
22    InvalidParameter(InvalidParameterError),
23
24    /// A registry-specific error.
25    Registry(RegistryError),
26
27    /// A process-specific error.
28    Process(ProcessError),
29
30    /// A service-specific error.
31    Service(ServiceError),
32
33    /// A thread-specific error.
34    Thread(ThreadError),
35
36    /// An event log-specific error.
37    EventLog(EventLogError),
38
39    /// An ETW-specific error.
40    Etw(EtwError),
41
42    /// A mitigation-specific error.
43    Mitigation(MitigationError),
44
45    /// A proxy-specific error.
46    Proxy(ProxyError),
47
48    /// A security/permissions-specific error.
49    Security(SecurityError),
50
51    /// A file operation error.
52    FileOperation(FileOperationError),
53
54    /// A pipe operation error.
55    Pipe(PipeError),
56
57    /// A desktop/windowing operation error.
58    Desktop(DesktopError),
59
60    /// A generic error with a message.
61    Other(OtherError),
62}
63
64impl fmt::Display for Error {
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        match self {
67            Error::WindowsApi(e) => write!(f, "{}", e),
68            Error::AccessDenied(e) => write!(f, "{}", e),
69            Error::NotFound(e) => write!(f, "{}", e),
70            Error::InvalidParameter(e) => write!(f, "{}", e),
71            Error::Registry(e) => write!(f, "{}", e),
72            Error::Process(e) => write!(f, "{}", e),
73            Error::Service(e) => write!(f, "{}", e),
74            Error::Thread(e) => write!(f, "{}", e),
75            Error::EventLog(e) => write!(f, "{}", e),
76            Error::Etw(e) => write!(f, "{}", e),
77            Error::Mitigation(e) => write!(f, "{}", e),
78            Error::Proxy(e) => write!(f, "{}", e),
79            Error::Security(e) => write!(f, "{}", e),
80            Error::FileOperation(e) => write!(f, "{}", e),
81            Error::Pipe(e) => write!(f, "{}", e),
82            Error::Desktop(e) => write!(f, "{}", e),
83            Error::Other(e) => write!(f, "{}", e),
84        }
85    }
86}
87
88impl std::error::Error for Error {}
89
90impl From<windows::core::Error> for Error {
91    fn from(err: windows::core::Error) -> Self {
92        Error::WindowsApi(WindowsApiError {
93            inner: err,
94            context: None,
95        })
96    }
97}
98
99// ============================================================================
100// Structured Error Types
101// ============================================================================
102
103/// Windows API error with optional context.
104#[derive(Debug)]
105pub struct WindowsApiError {
106    /// The underlying Windows error.
107    pub inner: windows::core::Error,
108    /// Optional context about what operation failed.
109    pub context: Option<Cow<'static, str>>,
110}
111
112impl WindowsApiError {
113    /// Create a new Windows API error.
114    pub fn new(inner: windows::core::Error) -> Self {
115        WindowsApiError {
116            inner,
117            context: None,
118        }
119    }
120
121    /// Create a Windows API error with context.
122    pub fn with_context(
123        inner: windows::core::Error,
124        context: impl Into<Cow<'static, str>>,
125    ) -> Self {
126        WindowsApiError {
127            inner,
128            context: Some(context.into()),
129        }
130    }
131
132    /// Get the Windows error code.
133    pub fn code(&self) -> i32 {
134        self.inner.code().0
135    }
136}
137
138impl fmt::Display for WindowsApiError {
139    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140        if let Some(context) = &self.context {
141            write!(f, "Windows API error in {}: {}", context, self.inner)
142        } else {
143            write!(f, "Windows API error: {}", self.inner)
144        }
145    }
146}
147
148impl std::error::Error for WindowsApiError {}
149
150/// Access denied error.
151#[derive(Debug)]
152pub struct AccessDeniedError {
153    /// What resource was being accessed.
154    pub resource: Cow<'static, str>,
155    /// What operation was attempted.
156    pub operation: Cow<'static, str>,
157    /// Optional additional context.
158    pub reason: Option<Cow<'static, str>>,
159}
160
161impl AccessDeniedError {
162    /// Create a new access denied error.
163    pub fn new(
164        resource: impl Into<Cow<'static, str>>,
165        operation: impl Into<Cow<'static, str>>,
166    ) -> Self {
167        AccessDeniedError {
168            resource: resource.into(),
169            operation: operation.into(),
170            reason: None,
171        }
172    }
173
174    /// Create an access denied error with a reason.
175    pub fn with_reason(
176        resource: impl Into<Cow<'static, str>>,
177        operation: impl Into<Cow<'static, str>>,
178        reason: impl Into<Cow<'static, str>>,
179    ) -> Self {
180        AccessDeniedError {
181            resource: resource.into(),
182            operation: operation.into(),
183            reason: Some(reason.into()),
184        }
185    }
186}
187
188impl fmt::Display for AccessDeniedError {
189    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190        if let Some(reason) = &self.reason {
191            write!(
192                f,
193                "Access denied: cannot {} '{}' ({})",
194                self.operation, self.resource, reason
195            )
196        } else {
197            write!(
198                f,
199                "Access denied: cannot {} '{}'",
200                self.operation, self.resource
201            )
202        }
203    }
204}
205
206impl std::error::Error for AccessDeniedError {}
207
208/// Resource not found error.
209#[derive(Debug)]
210pub struct NotFoundError {
211    /// Type of resource that was not found.
212    pub resource_type: Cow<'static, str>,
213    /// Identifier of the resource.
214    pub identifier: Cow<'static, str>,
215}
216
217impl NotFoundError {
218    /// Create a new not found error.
219    pub fn new(
220        resource_type: impl Into<Cow<'static, str>>,
221        identifier: impl Into<Cow<'static, str>>,
222    ) -> Self {
223        NotFoundError {
224            resource_type: resource_type.into(),
225            identifier: identifier.into(),
226        }
227    }
228}
229
230impl fmt::Display for NotFoundError {
231    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
232        write!(f, "{} not found: {}", self.resource_type, self.identifier)
233    }
234}
235
236impl std::error::Error for NotFoundError {}
237
238/// Invalid parameter error.
239#[derive(Debug)]
240pub struct InvalidParameterError {
241    /// Name of the parameter.
242    pub parameter: Cow<'static, str>,
243    /// Why the parameter is invalid.
244    pub reason: Cow<'static, str>,
245}
246
247impl InvalidParameterError {
248    /// Create a new invalid parameter error.
249    pub fn new(
250        parameter: impl Into<Cow<'static, str>>,
251        reason: impl Into<Cow<'static, str>>,
252    ) -> Self {
253        InvalidParameterError {
254            parameter: parameter.into(),
255            reason: reason.into(),
256        }
257    }
258}
259
260impl fmt::Display for InvalidParameterError {
261    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262        write!(f, "Invalid parameter '{}': {}", self.parameter, self.reason)
263    }
264}
265
266impl std::error::Error for InvalidParameterError {}
267
268/// File operation error.
269#[derive(Debug)]
270pub struct FileOperationError {
271    /// The file path.
272    pub path: Cow<'static, str>,
273    /// The operation that failed.
274    pub operation: Cow<'static, str>,
275    /// Windows error code if available.
276    pub error_code: Option<i32>,
277}
278
279impl FileOperationError {
280    /// Create a new file operation error.
281    pub fn new(
282        path: impl Into<Cow<'static, str>>,
283        operation: impl Into<Cow<'static, str>>,
284    ) -> Self {
285        FileOperationError {
286            path: path.into(),
287            operation: operation.into(),
288            error_code: None,
289        }
290    }
291
292    /// Create a file operation error with an error code.
293    pub fn with_code(
294        path: impl Into<Cow<'static, str>>,
295        operation: impl Into<Cow<'static, str>>,
296        error_code: i32,
297    ) -> Self {
298        FileOperationError {
299            path: path.into(),
300            operation: operation.into(),
301            error_code: Some(error_code),
302        }
303    }
304}
305
306impl fmt::Display for FileOperationError {
307    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
308        if let Some(code) = self.error_code {
309            write!(
310                f,
311                "File operation '{}' failed on '{}' (error code: 0x{:08X})",
312                self.operation, self.path, code
313            )
314        } else {
315            write!(
316                f,
317                "File operation '{}' failed on '{}'",
318                self.operation, self.path
319            )
320        }
321    }
322}
323
324impl std::error::Error for FileOperationError {}
325
326// ============================================================================
327// Pipe Errors
328// ============================================================================
329
330/// Pipe-specific errors.
331#[derive(Debug)]
332pub enum PipeError {
333    /// Pipe creation failed.
334    Create(PipeCreateError),
335
336    /// Pipe connection failed.
337    Connect(PipeConnectError),
338
339    /// Pipe I/O operation failed.
340    Io(PipeIoError),
341
342    /// Pipe reached timeout.
343    Timeout(PipeTimeoutError),
344
345    /// Pipe is in an invalid state for the operation.
346    InvalidState(PipeInvalidStateError),
347}
348
349impl fmt::Display for PipeError {
350    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
351        match self {
352            PipeError::Create(e) => write!(f, "{}", e),
353            PipeError::Connect(e) => write!(f, "{}", e),
354            PipeError::Io(e) => write!(f, "{}", e),
355            PipeError::Timeout(e) => write!(f, "{}", e),
356            PipeError::InvalidState(e) => write!(f, "{}", e),
357        }
358    }
359}
360
361impl std::error::Error for PipeError {}
362
363/// Pipe creation error.
364#[derive(Debug)]
365pub struct PipeCreateError {
366    /// Pipe name used during creation.
367    pub pipe_name: Cow<'static, str>,
368    /// Operation description.
369    pub operation: Cow<'static, str>,
370    /// Optional Windows error code.
371    pub error_code: Option<i32>,
372}
373
374impl PipeCreateError {
375    /// Create a new pipe creation error.
376    pub fn new(
377        pipe_name: impl Into<Cow<'static, str>>,
378        operation: impl Into<Cow<'static, str>>,
379    ) -> Self {
380        PipeCreateError {
381            pipe_name: pipe_name.into(),
382            operation: operation.into(),
383            error_code: None,
384        }
385    }
386
387    /// Create a new pipe creation error with an error code.
388    pub fn with_code(
389        pipe_name: impl Into<Cow<'static, str>>,
390        operation: impl Into<Cow<'static, str>>,
391        error_code: i32,
392    ) -> Self {
393        PipeCreateError {
394            pipe_name: pipe_name.into(),
395            operation: operation.into(),
396            error_code: Some(error_code),
397        }
398    }
399}
400
401impl fmt::Display for PipeCreateError {
402    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
403        if let Some(code) = self.error_code {
404            write!(
405                f,
406                "Pipe creation '{}' failed for '{}' (error code: 0x{:08X})",
407                self.operation, self.pipe_name, code
408            )
409        } else {
410            write!(
411                f,
412                "Pipe creation '{}' failed for '{}'",
413                self.operation, self.pipe_name
414            )
415        }
416    }
417}
418
419impl std::error::Error for PipeCreateError {}
420
421/// Pipe connection error.
422#[derive(Debug)]
423pub struct PipeConnectError {
424    /// Pipe name used during connection.
425    pub pipe_name: Cow<'static, str>,
426    /// Optional connection context.
427    pub context: Option<Cow<'static, str>>,
428    /// Optional Windows error code.
429    pub error_code: Option<i32>,
430}
431
432impl PipeConnectError {
433    /// Create a new pipe connection error.
434    pub fn new(pipe_name: impl Into<Cow<'static, str>>) -> Self {
435        PipeConnectError {
436            pipe_name: pipe_name.into(),
437            context: None,
438            error_code: None,
439        }
440    }
441
442    /// Add context to a pipe connection error.
443    pub fn with_context(mut self, context: impl Into<Cow<'static, str>>) -> Self {
444        self.context = Some(context.into());
445        self
446    }
447
448    /// Add a Windows error code to a pipe connection error.
449    pub fn with_code(mut self, error_code: i32) -> Self {
450        self.error_code = Some(error_code);
451        self
452    }
453}
454
455impl fmt::Display for PipeConnectError {
456    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
457        match (&self.context, self.error_code) {
458            (Some(context), Some(code)) => write!(
459                f,
460                "Pipe connect failed for '{}' ({}, error code: 0x{:08X})",
461                self.pipe_name, context, code
462            ),
463            (Some(context), None) => {
464                write!(
465                    f,
466                    "Pipe connect failed for '{}' ({})",
467                    self.pipe_name, context
468                )
469            }
470            (None, Some(code)) => write!(
471                f,
472                "Pipe connect failed for '{}' (error code: 0x{:08X})",
473                self.pipe_name, code
474            ),
475            (None, None) => write!(f, "Pipe connect failed for '{}'", self.pipe_name),
476        }
477    }
478}
479
480impl std::error::Error for PipeConnectError {}
481
482/// Pipe I/O error.
483#[derive(Debug)]
484pub struct PipeIoError {
485    /// Pipe name involved in I/O.
486    pub pipe_name: Cow<'static, str>,
487    /// I/O operation that failed.
488    pub operation: Cow<'static, str>,
489    /// Optional Windows error code.
490    pub error_code: Option<i32>,
491}
492
493impl PipeIoError {
494    /// Create a new pipe I/O error.
495    pub fn new(
496        pipe_name: impl Into<Cow<'static, str>>,
497        operation: impl Into<Cow<'static, str>>,
498    ) -> Self {
499        PipeIoError {
500            pipe_name: pipe_name.into(),
501            operation: operation.into(),
502            error_code: None,
503        }
504    }
505
506    /// Create a new pipe I/O error with an error code.
507    pub fn with_code(
508        pipe_name: impl Into<Cow<'static, str>>,
509        operation: impl Into<Cow<'static, str>>,
510        error_code: i32,
511    ) -> Self {
512        PipeIoError {
513            pipe_name: pipe_name.into(),
514            operation: operation.into(),
515            error_code: Some(error_code),
516        }
517    }
518}
519
520impl fmt::Display for PipeIoError {
521    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
522        if let Some(code) = self.error_code {
523            write!(
524                f,
525                "Pipe I/O '{}' failed for '{}' (error code: 0x{:08X})",
526                self.operation, self.pipe_name, code
527            )
528        } else {
529            write!(
530                f,
531                "Pipe I/O '{}' failed for '{}'",
532                self.operation, self.pipe_name
533            )
534        }
535    }
536}
537
538impl std::error::Error for PipeIoError {}
539
540/// Pipe timeout error.
541#[derive(Debug)]
542pub struct PipeTimeoutError {
543    /// Pipe name that timed out.
544    pub pipe_name: Cow<'static, str>,
545    /// Timeout operation.
546    pub operation: Cow<'static, str>,
547}
548
549impl PipeTimeoutError {
550    /// Create a new pipe timeout error.
551    pub fn new(
552        pipe_name: impl Into<Cow<'static, str>>,
553        operation: impl Into<Cow<'static, str>>,
554    ) -> Self {
555        PipeTimeoutError {
556            pipe_name: pipe_name.into(),
557            operation: operation.into(),
558        }
559    }
560}
561
562impl fmt::Display for PipeTimeoutError {
563    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
564        write!(
565            f,
566            "Pipe operation '{}' timed out for '{}'",
567            self.operation, self.pipe_name
568        )
569    }
570}
571
572impl std::error::Error for PipeTimeoutError {}
573
574/// Pipe invalid-state error.
575#[derive(Debug)]
576pub struct PipeInvalidStateError {
577    /// Operation attempted.
578    pub operation: Cow<'static, str>,
579    /// Why state is invalid.
580    pub reason: Cow<'static, str>,
581}
582
583impl PipeInvalidStateError {
584    /// Create a new invalid-state error for a pipe operation.
585    pub fn new(
586        operation: impl Into<Cow<'static, str>>,
587        reason: impl Into<Cow<'static, str>>,
588    ) -> Self {
589        PipeInvalidStateError {
590            operation: operation.into(),
591            reason: reason.into(),
592        }
593    }
594}
595
596impl fmt::Display for PipeInvalidStateError {
597    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
598        write!(
599            f,
600            "Pipe operation '{}' is invalid in current state: {}",
601            self.operation, self.reason
602        )
603    }
604}
605
606impl std::error::Error for PipeInvalidStateError {}
607
608/// Generic error with a message.
609#[derive(Debug)]
610pub struct OtherError {
611    /// Error message.
612    pub message: Cow<'static, str>,
613}
614
615impl OtherError {
616    /// Create a new generic error.
617    pub fn new(message: impl Into<Cow<'static, str>>) -> Self {
618        OtherError {
619            message: message.into(),
620        }
621    }
622}
623
624impl fmt::Display for OtherError {
625    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
626        write!(f, "{}", self.message)
627    }
628}
629
630impl std::error::Error for OtherError {}
631
632// ============================================================================
633// Desktop Errors
634// ============================================================================
635
636/// Desktop and windowing errors.
637#[derive(Debug)]
638pub enum DesktopError {
639    /// Desktop operation failed.
640    OperationFailed(DesktopOperationError),
641
642    /// Window not found.
643    WindowNotFound(WindowNotFoundError),
644}
645
646impl fmt::Display for DesktopError {
647    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
648        match self {
649            DesktopError::OperationFailed(e) => write!(f, "{}", e),
650            DesktopError::WindowNotFound(e) => write!(f, "{}", e),
651        }
652    }
653}
654
655impl std::error::Error for DesktopError {}
656
657/// Desktop operation failure details.
658#[derive(Debug)]
659pub struct DesktopOperationError {
660    /// Operation that failed.
661    pub operation: Cow<'static, str>,
662    /// Target resource involved in the operation.
663    pub target: Cow<'static, str>,
664    /// Optional Windows error code.
665    pub error_code: Option<i32>,
666}
667
668impl DesktopOperationError {
669    /// Create a new desktop operation error.
670    pub fn new(
671        operation: impl Into<Cow<'static, str>>,
672        target: impl Into<Cow<'static, str>>,
673    ) -> Self {
674        DesktopOperationError {
675            operation: operation.into(),
676            target: target.into(),
677            error_code: None,
678        }
679    }
680
681    /// Create a desktop operation error with a Windows error code.
682    pub fn with_code(
683        operation: impl Into<Cow<'static, str>>,
684        target: impl Into<Cow<'static, str>>,
685        error_code: i32,
686    ) -> Self {
687        DesktopOperationError {
688            operation: operation.into(),
689            target: target.into(),
690            error_code: Some(error_code),
691        }
692    }
693}
694
695impl fmt::Display for DesktopOperationError {
696    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
697        if let Some(code) = self.error_code {
698            write!(
699                f,
700                "Desktop operation '{}' failed for '{}' (error code: 0x{:08X})",
701                self.operation, self.target, code
702            )
703        } else {
704            write!(
705                f,
706                "Desktop operation '{}' failed for '{}'",
707                self.operation, self.target
708            )
709        }
710    }
711}
712
713impl std::error::Error for DesktopOperationError {}
714
715/// Window not found details.
716#[derive(Debug)]
717pub struct WindowNotFoundError {
718    /// The window identifier that was not found.
719    pub identifier: Cow<'static, str>,
720}
721
722impl WindowNotFoundError {
723    /// Create a new window not found error.
724    pub fn new(identifier: impl Into<Cow<'static, str>>) -> Self {
725        WindowNotFoundError {
726            identifier: identifier.into(),
727        }
728    }
729}
730
731impl fmt::Display for WindowNotFoundError {
732    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
733        write!(f, "Window not found: {}", self.identifier)
734    }
735}
736
737impl std::error::Error for WindowNotFoundError {}
738
739// ============================================================================
740// Security Errors
741// ============================================================================
742
743/// Security and permissions errors.
744#[derive(Debug)]
745pub enum SecurityError {
746    /// SID parsing or encoding failed.
747    SidParse(SidParseError),
748
749    /// Permission edit validation or execution failed.
750    PermissionEdit(PermissionEditError),
751
752    /// Operation is not supported by the current backend/target.
753    Unsupported(SecurityUnsupportedError),
754}
755
756impl fmt::Display for SecurityError {
757    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
758        match self {
759            SecurityError::SidParse(e) => write!(f, "{}", e),
760            SecurityError::PermissionEdit(e) => write!(f, "{}", e),
761            SecurityError::Unsupported(e) => write!(f, "{}", e),
762        }
763    }
764}
765
766impl std::error::Error for SecurityError {}
767
768/// SID parsing error.
769#[derive(Debug)]
770pub struct SidParseError {
771    /// Input SID representation that failed.
772    pub input: Cow<'static, str>,
773    /// Why parsing failed.
774    pub reason: Cow<'static, str>,
775}
776
777impl SidParseError {
778    /// Create a new SID parse error.
779    pub fn new(input: impl Into<Cow<'static, str>>, reason: impl Into<Cow<'static, str>>) -> Self {
780        SidParseError {
781            input: input.into(),
782            reason: reason.into(),
783        }
784    }
785}
786
787impl fmt::Display for SidParseError {
788    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
789        write!(f, "SID parse error for '{}': {}", self.input, self.reason)
790    }
791}
792
793impl std::error::Error for SidParseError {}
794
795/// Permission edit error.
796#[derive(Debug)]
797pub struct PermissionEditError {
798    /// Operation that failed.
799    pub operation: Cow<'static, str>,
800    /// Why it failed.
801    pub reason: Cow<'static, str>,
802}
803
804impl PermissionEditError {
805    /// Create a new permission edit error.
806    pub fn new(
807        operation: impl Into<Cow<'static, str>>,
808        reason: impl Into<Cow<'static, str>>,
809    ) -> Self {
810        PermissionEditError {
811            operation: operation.into(),
812            reason: reason.into(),
813        }
814    }
815}
816
817impl fmt::Display for PermissionEditError {
818    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
819        write!(
820            f,
821            "Permission edit '{}' failed: {}",
822            self.operation, self.reason
823        )
824    }
825}
826
827impl std::error::Error for PermissionEditError {}
828
829/// Unsupported security operation.
830#[derive(Debug)]
831pub struct SecurityUnsupportedError {
832    /// The target/backend where operation was attempted.
833    pub target: Cow<'static, str>,
834    /// The unsupported operation.
835    pub operation: Cow<'static, str>,
836    /// Optional additional reason.
837    pub reason: Option<Cow<'static, str>>,
838}
839
840impl SecurityUnsupportedError {
841    /// Create a new unsupported security operation error.
842    pub fn new(
843        target: impl Into<Cow<'static, str>>,
844        operation: impl Into<Cow<'static, str>>,
845    ) -> Self {
846        SecurityUnsupportedError {
847            target: target.into(),
848            operation: operation.into(),
849            reason: None,
850        }
851    }
852
853    /// Create a new unsupported security operation error with reason.
854    pub fn with_reason(
855        target: impl Into<Cow<'static, str>>,
856        operation: impl Into<Cow<'static, str>>,
857        reason: impl Into<Cow<'static, str>>,
858    ) -> Self {
859        SecurityUnsupportedError {
860            target: target.into(),
861            operation: operation.into(),
862            reason: Some(reason.into()),
863        }
864    }
865}
866
867impl fmt::Display for SecurityUnsupportedError {
868    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
869        if let Some(reason) = &self.reason {
870            write!(
871                f,
872                "Security operation '{}' is not supported for '{}': {}",
873                self.operation, self.target, reason
874            )
875        } else {
876            write!(
877                f,
878                "Security operation '{}' is not supported for '{}'",
879                self.operation, self.target
880            )
881        }
882    }
883}
884
885impl std::error::Error for SecurityUnsupportedError {}
886
887// ============================================================================
888// Proxy Errors
889// ============================================================================
890
891/// Proxy-specific errors.
892#[derive(Debug)]
893pub enum ProxyError {
894    /// Proxy configuration is invalid.
895    InvalidConfig(ProxyConfigError),
896
897    /// Proxy discovery operation failed.
898    DiscoveryFailed(ProxyConfigError),
899
900    /// Proxy URL resolution failed.
901    ResolutionFailed(ProxyResolutionError),
902}
903
904impl fmt::Display for ProxyError {
905    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
906        match self {
907            ProxyError::InvalidConfig(e) => write!(f, "{}", e),
908            ProxyError::DiscoveryFailed(e) => write!(f, "{}", e),
909            ProxyError::ResolutionFailed(e) => write!(f, "{}", e),
910        }
911    }
912}
913
914impl std::error::Error for ProxyError {}
915
916/// Invalid or unavailable proxy configuration.
917#[derive(Debug)]
918pub struct ProxyConfigError {
919    /// Name of the relevant setting.
920    pub setting: Cow<'static, str>,
921    /// Reason the setting is invalid or unavailable.
922    pub reason: Cow<'static, str>,
923}
924
925impl ProxyConfigError {
926    /// Create a new proxy configuration error.
927    pub fn new(
928        setting: impl Into<Cow<'static, str>>,
929        reason: impl Into<Cow<'static, str>>,
930    ) -> Self {
931        ProxyConfigError {
932            setting: setting.into(),
933            reason: reason.into(),
934        }
935    }
936}
937
938impl fmt::Display for ProxyConfigError {
939    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
940        write!(
941            f,
942            "Proxy configuration error for '{}': {}",
943            self.setting, self.reason
944        )
945    }
946}
947
948impl std::error::Error for ProxyConfigError {}
949
950/// URL-specific proxy resolution error.
951#[derive(Debug)]
952pub struct ProxyResolutionError {
953    /// URL that was being resolved.
954    pub url: Cow<'static, str>,
955    /// Why resolution failed.
956    pub reason: Cow<'static, str>,
957}
958
959impl ProxyResolutionError {
960    /// Create a new proxy resolution error.
961    pub fn new(url: impl Into<Cow<'static, str>>, reason: impl Into<Cow<'static, str>>) -> Self {
962        ProxyResolutionError {
963            url: url.into(),
964            reason: reason.into(),
965        }
966    }
967}
968
969impl fmt::Display for ProxyResolutionError {
970    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
971        write!(
972            f,
973            "Proxy resolution failed for '{}': {}",
974            self.url, self.reason
975        )
976    }
977}
978
979impl std::error::Error for ProxyResolutionError {}
980
981// ============================================================================
982// Registry Errors
983// ============================================================================
984
985/// Registry-specific errors.
986#[derive(Debug)]
987pub enum RegistryError {
988    /// Registry key not found.
989    KeyNotFound(RegistryKeyNotFoundError),
990
991    /// Registry value not found.
992    ValueNotFound(RegistryValueNotFoundError),
993
994    /// Invalid value type.
995    InvalidType(RegistryInvalidTypeError),
996
997    /// Error converting value.
998    ConversionError(RegistryConversionError),
999}
1000
1001impl fmt::Display for RegistryError {
1002    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1003        match self {
1004            RegistryError::KeyNotFound(e) => write!(f, "{}", e),
1005            RegistryError::ValueNotFound(e) => write!(f, "{}", e),
1006            RegistryError::InvalidType(e) => write!(f, "{}", e),
1007            RegistryError::ConversionError(e) => write!(f, "{}", e),
1008        }
1009    }
1010}
1011
1012impl std::error::Error for RegistryError {}
1013
1014/// Registry key not found.
1015#[derive(Debug)]
1016pub struct RegistryKeyNotFoundError {
1017    /// The key path that was not found.
1018    pub key_path: Cow<'static, str>,
1019    /// Windows error code.
1020    pub error_code: Option<i32>,
1021}
1022
1023impl RegistryKeyNotFoundError {
1024    /// Create a new key not found error.
1025    pub fn new(key_path: impl Into<Cow<'static, str>>) -> Self {
1026        RegistryKeyNotFoundError {
1027            key_path: key_path.into(),
1028            error_code: None,
1029        }
1030    }
1031
1032    /// Create a key not found error with error code.
1033    pub fn with_code(key_path: impl Into<Cow<'static, str>>, error_code: i32) -> Self {
1034        RegistryKeyNotFoundError {
1035            key_path: key_path.into(),
1036            error_code: Some(error_code),
1037        }
1038    }
1039}
1040
1041impl fmt::Display for RegistryKeyNotFoundError {
1042    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1043        if let Some(code) = self.error_code {
1044            write!(
1045                f,
1046                "Registry key not found: {} (error code: 0x{:08X})",
1047                self.key_path, code
1048            )
1049        } else {
1050            write!(f, "Registry key not found: {}", self.key_path)
1051        }
1052    }
1053}
1054
1055impl std::error::Error for RegistryKeyNotFoundError {}
1056
1057/// Registry value not found.
1058#[derive(Debug)]
1059pub struct RegistryValueNotFoundError {
1060    /// The value name that was not found.
1061    pub value_name: Cow<'static, str>,
1062    /// Optional key path for context.
1063    pub key_path: Option<Cow<'static, str>>,
1064}
1065
1066impl RegistryValueNotFoundError {
1067    /// Create a new value not found error.
1068    pub fn new(value_name: impl Into<Cow<'static, str>>) -> Self {
1069        RegistryValueNotFoundError {
1070            value_name: value_name.into(),
1071            key_path: None,
1072        }
1073    }
1074
1075    /// Create a value not found error with key path.
1076    pub fn with_key(
1077        value_name: impl Into<Cow<'static, str>>,
1078        key_path: impl Into<Cow<'static, str>>,
1079    ) -> Self {
1080        RegistryValueNotFoundError {
1081            value_name: value_name.into(),
1082            key_path: Some(key_path.into()),
1083        }
1084    }
1085}
1086
1087impl fmt::Display for RegistryValueNotFoundError {
1088    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1089        if let Some(key) = &self.key_path {
1090            write!(
1091                f,
1092                "Registry value '{}' not found in key '{}'",
1093                self.value_name, key
1094            )
1095        } else {
1096            write!(f, "Registry value not found: {}", self.value_name)
1097        }
1098    }
1099}
1100
1101impl std::error::Error for RegistryValueNotFoundError {}
1102
1103/// Invalid registry value type.
1104#[derive(Debug)]
1105pub struct RegistryInvalidTypeError {
1106    /// The expected type.
1107    pub expected: Cow<'static, str>,
1108    /// The actual type found.
1109    pub found: Cow<'static, str>,
1110    /// The value name.
1111    pub value_name: Option<Cow<'static, str>>,
1112}
1113
1114impl RegistryInvalidTypeError {
1115    /// Create a new invalid type error.
1116    pub fn new(
1117        expected: impl Into<Cow<'static, str>>,
1118        found: impl Into<Cow<'static, str>>,
1119    ) -> Self {
1120        RegistryInvalidTypeError {
1121            expected: expected.into(),
1122            found: found.into(),
1123            value_name: None,
1124        }
1125    }
1126
1127    /// Create an invalid type error with value name.
1128    pub fn with_name(
1129        expected: impl Into<Cow<'static, str>>,
1130        found: impl Into<Cow<'static, str>>,
1131        value_name: impl Into<Cow<'static, str>>,
1132    ) -> Self {
1133        RegistryInvalidTypeError {
1134            expected: expected.into(),
1135            found: found.into(),
1136            value_name: Some(value_name.into()),
1137        }
1138    }
1139}
1140
1141impl fmt::Display for RegistryInvalidTypeError {
1142    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1143        if let Some(name) = &self.value_name {
1144            write!(
1145                f,
1146                "Invalid registry type for '{}': expected {}, found {}",
1147                name, self.expected, self.found
1148            )
1149        } else {
1150            write!(
1151                f,
1152                "Invalid registry type: expected {}, found {}",
1153                self.expected, self.found
1154            )
1155        }
1156    }
1157}
1158
1159impl std::error::Error for RegistryInvalidTypeError {}
1160
1161/// Registry value conversion error.
1162#[derive(Debug)]
1163pub struct RegistryConversionError {
1164    /// What conversion was being attempted.
1165    pub conversion: Cow<'static, str>,
1166    /// Why it failed.
1167    pub reason: Cow<'static, str>,
1168}
1169
1170impl RegistryConversionError {
1171    /// Create a new conversion error.
1172    pub fn new(
1173        conversion: impl Into<Cow<'static, str>>,
1174        reason: impl Into<Cow<'static, str>>,
1175    ) -> Self {
1176        RegistryConversionError {
1177            conversion: conversion.into(),
1178            reason: reason.into(),
1179        }
1180    }
1181}
1182
1183impl fmt::Display for RegistryConversionError {
1184    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1185        write!(
1186            f,
1187            "Registry conversion error ({}): {}",
1188            self.conversion, self.reason
1189        )
1190    }
1191}
1192
1193impl std::error::Error for RegistryConversionError {}
1194
1195// ============================================================================
1196// Service Errors
1197// ============================================================================
1198
1199/// Service-specific errors.
1200#[derive(Debug)]
1201pub enum ServiceError {
1202    /// Failed to open or use the Service Control Manager.
1203    ManagerError(ServiceManagerError),
1204
1205    /// Service not found.
1206    NotFound(ServiceNotFoundError),
1207
1208    /// Service operation failed.
1209    OperationFailed(ServiceOperationError),
1210
1211    /// Service is in an invalid state for the requested operation.
1212    InvalidState(ServiceInvalidStateError),
1213}
1214
1215impl fmt::Display for ServiceError {
1216    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1217        match self {
1218            ServiceError::ManagerError(e) => write!(f, "{}", e),
1219            ServiceError::NotFound(e) => write!(f, "{}", e),
1220            ServiceError::OperationFailed(e) => write!(f, "{}", e),
1221            ServiceError::InvalidState(e) => write!(f, "{}", e),
1222        }
1223    }
1224}
1225
1226impl std::error::Error for ServiceError {}
1227
1228/// Service Control Manager failure details.
1229#[derive(Debug)]
1230pub struct ServiceManagerError {
1231    /// Operation that failed.
1232    pub operation: Cow<'static, str>,
1233    /// Failure reason.
1234    pub reason: Cow<'static, str>,
1235    /// Optional Windows error code.
1236    pub error_code: Option<i32>,
1237}
1238
1239impl ServiceManagerError {
1240    /// Create a new service manager error.
1241    pub fn new(
1242        operation: impl Into<Cow<'static, str>>,
1243        reason: impl Into<Cow<'static, str>>,
1244    ) -> Self {
1245        ServiceManagerError {
1246            operation: operation.into(),
1247            reason: reason.into(),
1248            error_code: None,
1249        }
1250    }
1251
1252    /// Create a service manager error with error code.
1253    pub fn with_code(
1254        operation: impl Into<Cow<'static, str>>,
1255        reason: impl Into<Cow<'static, str>>,
1256        error_code: i32,
1257    ) -> Self {
1258        ServiceManagerError {
1259            operation: operation.into(),
1260            reason: reason.into(),
1261            error_code: Some(error_code),
1262        }
1263    }
1264}
1265
1266impl fmt::Display for ServiceManagerError {
1267    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1268        if let Some(code) = self.error_code {
1269            write!(
1270                f,
1271                "Service manager operation '{}' failed: {} (error code: 0x{:08X})",
1272                self.operation, self.reason, code
1273            )
1274        } else {
1275            write!(
1276                f,
1277                "Service manager operation '{}' failed: {}",
1278                self.operation, self.reason
1279            )
1280        }
1281    }
1282}
1283
1284impl std::error::Error for ServiceManagerError {}
1285
1286/// Service not found details.
1287#[derive(Debug)]
1288pub struct ServiceNotFoundError {
1289    /// Service key name.
1290    pub name: Cow<'static, str>,
1291    /// Optional Windows error code.
1292    pub error_code: Option<i32>,
1293}
1294
1295impl ServiceNotFoundError {
1296    /// Create a new service not found error.
1297    pub fn new(name: impl Into<Cow<'static, str>>) -> Self {
1298        ServiceNotFoundError {
1299            name: name.into(),
1300            error_code: None,
1301        }
1302    }
1303
1304    /// Create a service not found error with error code.
1305    pub fn with_code(name: impl Into<Cow<'static, str>>, error_code: i32) -> Self {
1306        ServiceNotFoundError {
1307            name: name.into(),
1308            error_code: Some(error_code),
1309        }
1310    }
1311}
1312
1313impl fmt::Display for ServiceNotFoundError {
1314    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1315        if let Some(code) = self.error_code {
1316            write!(
1317                f,
1318                "Service '{}' not found (error code: 0x{:08X})",
1319                self.name, code
1320            )
1321        } else {
1322            write!(f, "Service '{}' not found", self.name)
1323        }
1324    }
1325}
1326
1327impl std::error::Error for ServiceNotFoundError {}
1328
1329/// Service operation failure details.
1330#[derive(Debug)]
1331pub struct ServiceOperationError {
1332    /// Service key name.
1333    pub name: Cow<'static, str>,
1334    /// Operation that failed.
1335    pub operation: Cow<'static, str>,
1336    /// Failure reason.
1337    pub reason: Cow<'static, str>,
1338    /// Optional Windows error code.
1339    pub error_code: Option<i32>,
1340}
1341
1342impl ServiceOperationError {
1343    /// Create a new service operation error.
1344    pub fn new(
1345        name: impl Into<Cow<'static, str>>,
1346        operation: impl Into<Cow<'static, str>>,
1347        reason: impl Into<Cow<'static, str>>,
1348    ) -> Self {
1349        ServiceOperationError {
1350            name: name.into(),
1351            operation: operation.into(),
1352            reason: reason.into(),
1353            error_code: None,
1354        }
1355    }
1356
1357    /// Create a service operation error with error code.
1358    pub fn with_code(
1359        name: impl Into<Cow<'static, str>>,
1360        operation: impl Into<Cow<'static, str>>,
1361        reason: impl Into<Cow<'static, str>>,
1362        error_code: i32,
1363    ) -> Self {
1364        ServiceOperationError {
1365            name: name.into(),
1366            operation: operation.into(),
1367            reason: reason.into(),
1368            error_code: Some(error_code),
1369        }
1370    }
1371}
1372
1373impl fmt::Display for ServiceOperationError {
1374    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1375        if let Some(code) = self.error_code {
1376            write!(
1377                f,
1378                "Service '{}' operation '{}' failed: {} (error code: 0x{:08X})",
1379                self.name, self.operation, self.reason, code
1380            )
1381        } else {
1382            write!(
1383                f,
1384                "Service '{}' operation '{}' failed: {}",
1385                self.name, self.operation, self.reason
1386            )
1387        }
1388    }
1389}
1390
1391impl std::error::Error for ServiceOperationError {}
1392
1393/// Service invalid-state error details.
1394#[derive(Debug)]
1395pub struct ServiceInvalidStateError {
1396    /// Service key name.
1397    pub name: Cow<'static, str>,
1398    /// Expected state or condition.
1399    pub expected: Cow<'static, str>,
1400    /// Why the state is invalid.
1401    pub reason: Cow<'static, str>,
1402}
1403
1404impl ServiceInvalidStateError {
1405    /// Create a new service invalid-state error.
1406    pub fn new(
1407        name: impl Into<Cow<'static, str>>,
1408        expected: impl Into<Cow<'static, str>>,
1409        reason: impl Into<Cow<'static, str>>,
1410    ) -> Self {
1411        ServiceInvalidStateError {
1412            name: name.into(),
1413            expected: expected.into(),
1414            reason: reason.into(),
1415        }
1416    }
1417}
1418
1419impl fmt::Display for ServiceInvalidStateError {
1420    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1421        write!(
1422            f,
1423            "Service '{}' is not in expected state '{}': {}",
1424            self.name, self.expected, self.reason
1425        )
1426    }
1427}
1428
1429impl std::error::Error for ServiceInvalidStateError {}
1430
1431// ============================================================================
1432// Process Errors
1433// ============================================================================
1434
1435/// Process-specific errors.
1436#[derive(Debug)]
1437pub enum ProcessError {
1438    /// Process not found.
1439    NotFound(ProcessNotFoundError),
1440
1441    /// Process already terminated.
1442    AlreadyTerminated(ProcessTerminatedError),
1443
1444    /// Failed to open process.
1445    OpenFailed(ProcessOpenError),
1446
1447    /// Failed to spawn process.
1448    SpawnFailed(ProcessSpawnError),
1449
1450    /// Invalid process ID.
1451    InvalidProcessId,
1452
1453    /// DLL injection failed.
1454    InjectionFailed(InjectionFailedError),
1455
1456    /// DLL is already injected into the target process.
1457    AlreadyInjected(AlreadyInjectedError),
1458}
1459
1460impl fmt::Display for ProcessError {
1461    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1462        match self {
1463            ProcessError::NotFound(e) => write!(f, "{}", e),
1464            ProcessError::AlreadyTerminated(e) => write!(f, "{}", e),
1465            ProcessError::OpenFailed(e) => write!(f, "{}", e),
1466            ProcessError::SpawnFailed(e) => write!(f, "{}", e),
1467            ProcessError::InvalidProcessId => write!(f, "Invalid process ID"),
1468            ProcessError::InjectionFailed(e) => write!(f, "{}", e),
1469            ProcessError::AlreadyInjected(e) => write!(f, "{}", e),
1470        }
1471    }
1472}
1473
1474impl std::error::Error for ProcessError {}
1475
1476/// Process not found error.
1477#[derive(Debug)]
1478pub struct ProcessNotFoundError {
1479    /// The process ID that was not found.
1480    pub pid: u32,
1481}
1482
1483impl ProcessNotFoundError {
1484    /// Create a new process not found error.
1485    pub fn new(pid: u32) -> Self {
1486        ProcessNotFoundError { pid }
1487    }
1488}
1489
1490impl fmt::Display for ProcessNotFoundError {
1491    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1492        write!(f, "Process {} not found", self.pid)
1493    }
1494}
1495
1496impl std::error::Error for ProcessNotFoundError {}
1497
1498/// Process already terminated error.
1499#[derive(Debug)]
1500pub struct ProcessTerminatedError {
1501    /// The process ID.
1502    pub pid: u32,
1503    /// Optional exit code.
1504    pub exit_code: Option<u32>,
1505}
1506
1507impl ProcessTerminatedError {
1508    /// Create a new process terminated error.
1509    pub fn new(pid: u32) -> Self {
1510        ProcessTerminatedError {
1511            pid,
1512            exit_code: None,
1513        }
1514    }
1515
1516    /// Create a process terminated error with exit code.
1517    pub fn with_exit_code(pid: u32, exit_code: u32) -> Self {
1518        ProcessTerminatedError {
1519            pid,
1520            exit_code: Some(exit_code),
1521        }
1522    }
1523}
1524
1525impl fmt::Display for ProcessTerminatedError {
1526    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1527        if let Some(code) = self.exit_code {
1528            write!(
1529                f,
1530                "Process {} already terminated (exit code: {})",
1531                self.pid, code
1532            )
1533        } else {
1534            write!(f, "Process {} already terminated", self.pid)
1535        }
1536    }
1537}
1538
1539impl std::error::Error for ProcessTerminatedError {}
1540
1541/// Failed to open process error.
1542#[derive(Debug)]
1543pub struct ProcessOpenError {
1544    /// The process ID.
1545    pub pid: u32,
1546    /// Reason for failure.
1547    pub reason: Cow<'static, str>,
1548    /// Windows error code if available.
1549    pub error_code: Option<i32>,
1550}
1551
1552impl ProcessOpenError {
1553    /// Create a new process open error.
1554    pub fn new(pid: u32, reason: impl Into<Cow<'static, str>>) -> Self {
1555        ProcessOpenError {
1556            pid,
1557            reason: reason.into(),
1558            error_code: None,
1559        }
1560    }
1561
1562    /// Create a process open error with error code.
1563    pub fn with_code(pid: u32, reason: impl Into<Cow<'static, str>>, error_code: i32) -> Self {
1564        ProcessOpenError {
1565            pid,
1566            reason: reason.into(),
1567            error_code: Some(error_code),
1568        }
1569    }
1570}
1571
1572impl fmt::Display for ProcessOpenError {
1573    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1574        if let Some(code) = self.error_code {
1575            write!(
1576                f,
1577                "Failed to open process {}: {} (error code: 0x{:08X})",
1578                self.pid, self.reason, code
1579            )
1580        } else {
1581            write!(f, "Failed to open process {}: {}", self.pid, self.reason)
1582        }
1583    }
1584}
1585
1586impl std::error::Error for ProcessOpenError {}
1587
1588/// Failed to spawn process error.
1589#[derive(Debug)]
1590pub struct ProcessSpawnError {
1591    /// The command that was attempted.
1592    pub command: Cow<'static, str>,
1593    /// Reason for failure.
1594    pub reason: Cow<'static, str>,
1595    /// Windows error code if available.
1596    pub error_code: Option<i32>,
1597}
1598
1599impl ProcessSpawnError {
1600    /// Create a new process spawn error.
1601    pub fn new(
1602        command: impl Into<Cow<'static, str>>,
1603        reason: impl Into<Cow<'static, str>>,
1604    ) -> Self {
1605        ProcessSpawnError {
1606            command: command.into(),
1607            reason: reason.into(),
1608            error_code: None,
1609        }
1610    }
1611
1612    /// Create a process spawn error with error code.
1613    pub fn with_code(
1614        command: impl Into<Cow<'static, str>>,
1615        reason: impl Into<Cow<'static, str>>,
1616        error_code: i32,
1617    ) -> Self {
1618        ProcessSpawnError {
1619            command: command.into(),
1620            reason: reason.into(),
1621            error_code: Some(error_code),
1622        }
1623    }
1624}
1625
1626impl fmt::Display for ProcessSpawnError {
1627    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1628        if let Some(code) = self.error_code {
1629            write!(
1630                f,
1631                "Failed to spawn process '{}': {} (error code: 0x{:08X})",
1632                self.command, self.reason, code
1633            )
1634        } else {
1635            write!(
1636                f,
1637                "Failed to spawn process '{}': {}",
1638                self.command, self.reason
1639            )
1640        }
1641    }
1642}
1643
1644impl std::error::Error for ProcessSpawnError {}
1645
1646/// DLL injection failed error.
1647#[derive(Debug)]
1648pub struct InjectionFailedError {
1649    /// The target process ID.
1650    pub pid: u32,
1651    /// Reason for failure.
1652    pub reason: Cow<'static, str>,
1653    /// Windows error code if available.
1654    pub error_code: Option<i32>,
1655}
1656
1657impl InjectionFailedError {
1658    /// Create a new injection failed error.
1659    pub fn new(pid: u32, reason: impl Into<Cow<'static, str>>) -> Self {
1660        InjectionFailedError {
1661            pid,
1662            reason: reason.into(),
1663            error_code: None,
1664        }
1665    }
1666
1667    /// Create an injection failed error with a Windows error code.
1668    pub fn with_code(pid: u32, reason: impl Into<Cow<'static, str>>, error_code: i32) -> Self {
1669        InjectionFailedError {
1670            pid,
1671            reason: reason.into(),
1672            error_code: Some(error_code),
1673        }
1674    }
1675}
1676
1677impl fmt::Display for InjectionFailedError {
1678    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1679        if let Some(code) = self.error_code {
1680            write!(
1681                f,
1682                "DLL injection into process {} failed: {} (error code: 0x{:08X})",
1683                self.pid, self.reason, code
1684            )
1685        } else {
1686            write!(
1687                f,
1688                "DLL injection into process {} failed: {}",
1689                self.pid, self.reason
1690            )
1691        }
1692    }
1693}
1694
1695impl std::error::Error for InjectionFailedError {}
1696
1697/// DLL already injected into target process error.
1698#[derive(Debug)]
1699pub struct AlreadyInjectedError {
1700    /// The target process ID.
1701    pub pid: u32,
1702    /// The DLL name or path that is already loaded.
1703    pub dll_name: Cow<'static, str>,
1704}
1705
1706impl AlreadyInjectedError {
1707    /// Create a new already-injected error.
1708    pub fn new(pid: u32, dll_name: impl Into<Cow<'static, str>>) -> Self {
1709        AlreadyInjectedError {
1710            pid,
1711            dll_name: dll_name.into(),
1712        }
1713    }
1714}
1715
1716impl fmt::Display for AlreadyInjectedError {
1717    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1718        write!(
1719            f,
1720            "DLL '{}' is already loaded in process {}",
1721            self.dll_name, self.pid
1722        )
1723    }
1724}
1725
1726impl std::error::Error for AlreadyInjectedError {}
1727
1728// ============================================================================
1729// Thread Errors
1730// ============================================================================
1731
1732/// Thread-specific errors.
1733#[derive(Debug)]
1734pub enum ThreadError {
1735    /// Thread not found.
1736    NotFound(ThreadNotFoundError),
1737
1738    /// Failed to open thread.
1739    OpenFailed(ThreadOpenError),
1740}
1741
1742impl fmt::Display for ThreadError {
1743    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1744        match self {
1745            ThreadError::NotFound(e) => write!(f, "{}", e),
1746            ThreadError::OpenFailed(e) => write!(f, "{}", e),
1747        }
1748    }
1749}
1750
1751impl std::error::Error for ThreadError {}
1752
1753/// Thread not found error.
1754#[derive(Debug)]
1755pub struct ThreadNotFoundError {
1756    /// The thread ID that was not found.
1757    pub tid: u32,
1758}
1759
1760impl ThreadNotFoundError {
1761    /// Create a new thread not found error.
1762    pub fn new(tid: u32) -> Self {
1763        ThreadNotFoundError { tid }
1764    }
1765}
1766
1767impl fmt::Display for ThreadNotFoundError {
1768    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1769        write!(f, "Thread {} not found", self.tid)
1770    }
1771}
1772
1773impl std::error::Error for ThreadNotFoundError {}
1774
1775/// Failed to open thread error.
1776#[derive(Debug)]
1777pub struct ThreadOpenError {
1778    /// The thread ID.
1779    pub tid: u32,
1780    /// Reason for failure.
1781    pub reason: Cow<'static, str>,
1782    /// Windows error code if available.
1783    pub error_code: Option<i32>,
1784}
1785
1786impl ThreadOpenError {
1787    /// Create a new thread open error.
1788    pub fn new(tid: u32, reason: impl Into<Cow<'static, str>>) -> Self {
1789        ThreadOpenError {
1790            tid,
1791            reason: reason.into(),
1792            error_code: None,
1793        }
1794    }
1795
1796    /// Create a thread open error with error code.
1797    pub fn with_code(tid: u32, reason: impl Into<Cow<'static, str>>, error_code: i32) -> Self {
1798        ThreadOpenError {
1799            tid,
1800            reason: reason.into(),
1801            error_code: Some(error_code),
1802        }
1803    }
1804}
1805
1806impl fmt::Display for ThreadOpenError {
1807    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1808        if let Some(code) = self.error_code {
1809            write!(
1810                f,
1811                "Failed to open thread {}: {} (error code: 0x{:08X})",
1812                self.tid, self.reason, code
1813            )
1814        } else {
1815            write!(f, "Failed to open thread {}: {}", self.tid, self.reason)
1816        }
1817    }
1818}
1819
1820impl std::error::Error for ThreadOpenError {}
1821
1822// ============================================================================
1823// Event Log Errors
1824// ============================================================================
1825
1826/// Event log-specific errors.
1827#[derive(Debug)]
1828pub enum EventLogError {
1829    /// Event log not found.
1830    LogNotFound(EventLogNotFoundError),
1831
1832    /// Failed to query events.
1833    QueryFailed(EventLogQueryError),
1834
1835    /// Failed to parse event.
1836    ParseFailed(EventLogParseError),
1837}
1838
1839impl fmt::Display for EventLogError {
1840    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1841        match self {
1842            EventLogError::LogNotFound(e) => write!(f, "{}", e),
1843            EventLogError::QueryFailed(e) => write!(f, "{}", e),
1844            EventLogError::ParseFailed(e) => write!(f, "{}", e),
1845        }
1846    }
1847}
1848
1849impl std::error::Error for EventLogError {}
1850
1851/// Event log not found error.
1852#[derive(Debug)]
1853pub struct EventLogNotFoundError {
1854    /// The name of the log that was not found.
1855    pub log_name: Cow<'static, str>,
1856}
1857
1858impl EventLogNotFoundError {
1859    /// Create a new event log not found error.
1860    pub fn new(log_name: impl Into<Cow<'static, str>>) -> Self {
1861        EventLogNotFoundError {
1862            log_name: log_name.into(),
1863        }
1864    }
1865}
1866
1867impl fmt::Display for EventLogNotFoundError {
1868    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1869        write!(f, "Event log not found: {}", self.log_name)
1870    }
1871}
1872
1873impl std::error::Error for EventLogNotFoundError {}
1874
1875/// Event log query error.
1876#[derive(Debug)]
1877pub struct EventLogQueryError {
1878    /// The log name.
1879    pub log_name: Cow<'static, str>,
1880    /// Reason for failure.
1881    pub reason: Cow<'static, str>,
1882    /// Windows error code if available.
1883    pub error_code: Option<i32>,
1884}
1885
1886impl EventLogQueryError {
1887    /// Create a new query error.
1888    pub fn new(
1889        log_name: impl Into<Cow<'static, str>>,
1890        reason: impl Into<Cow<'static, str>>,
1891    ) -> Self {
1892        EventLogQueryError {
1893            log_name: log_name.into(),
1894            reason: reason.into(),
1895            error_code: None,
1896        }
1897    }
1898
1899    /// Create a query error with error code.
1900    pub fn with_code(
1901        log_name: impl Into<Cow<'static, str>>,
1902        reason: impl Into<Cow<'static, str>>,
1903        error_code: i32,
1904    ) -> Self {
1905        EventLogQueryError {
1906            log_name: log_name.into(),
1907            reason: reason.into(),
1908            error_code: Some(error_code),
1909        }
1910    }
1911}
1912
1913impl fmt::Display for EventLogQueryError {
1914    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1915        if let Some(code) = self.error_code {
1916            write!(
1917                f,
1918                "Failed to query event log '{}': {} (error code: 0x{:08X})",
1919                self.log_name, self.reason, code
1920            )
1921        } else {
1922            write!(
1923                f,
1924                "Failed to query event log '{}': {}",
1925                self.log_name, self.reason
1926            )
1927        }
1928    }
1929}
1930
1931impl std::error::Error for EventLogQueryError {}
1932
1933/// Event log parse error.
1934#[derive(Debug)]
1935pub struct EventLogParseError {
1936    /// What failed to parse.
1937    pub component: Cow<'static, str>,
1938    /// Reason for failure.
1939    pub reason: Cow<'static, str>,
1940}
1941
1942impl EventLogParseError {
1943    /// Create a new parse error.
1944    pub fn new(
1945        component: impl Into<Cow<'static, str>>,
1946        reason: impl Into<Cow<'static, str>>,
1947    ) -> Self {
1948        EventLogParseError {
1949            component: component.into(),
1950            reason: reason.into(),
1951        }
1952    }
1953}
1954
1955impl fmt::Display for EventLogParseError {
1956    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1957        write!(f, "Failed to parse {}: {}", self.component, self.reason)
1958    }
1959}
1960
1961impl std::error::Error for EventLogParseError {}
1962
1963// ============================================================================
1964// ETW Errors
1965// ============================================================================
1966
1967/// ETW-specific errors.
1968#[derive(Debug)]
1969pub enum EtwError {
1970    /// Failed to start ETW session.
1971    SessionStartFailed(EtwSessionError),
1972
1973    /// Failed to enable provider.
1974    ProviderEnableFailed(EtwProviderError),
1975
1976    /// Failed to consume events.
1977    ConsumeFailed(EtwConsumeError),
1978}
1979
1980impl fmt::Display for EtwError {
1981    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1982        match self {
1983            EtwError::SessionStartFailed(e) => write!(f, "{}", e),
1984            EtwError::ProviderEnableFailed(e) => write!(f, "{}", e),
1985            EtwError::ConsumeFailed(e) => write!(f, "{}", e),
1986        }
1987    }
1988}
1989
1990impl std::error::Error for EtwError {}
1991
1992/// ETW session error.
1993#[derive(Debug)]
1994pub struct EtwSessionError {
1995    /// The session name.
1996    pub session_name: Cow<'static, str>,
1997    /// Reason for failure.
1998    pub reason: Cow<'static, str>,
1999    /// Windows error code if available.
2000    pub error_code: Option<i32>,
2001}
2002
2003impl EtwSessionError {
2004    /// Create a new session error.
2005    pub fn new(
2006        session_name: impl Into<Cow<'static, str>>,
2007        reason: impl Into<Cow<'static, str>>,
2008    ) -> Self {
2009        EtwSessionError {
2010            session_name: session_name.into(),
2011            reason: reason.into(),
2012            error_code: None,
2013        }
2014    }
2015
2016    /// Create a session error with error code.
2017    pub fn with_code(
2018        session_name: impl Into<Cow<'static, str>>,
2019        reason: impl Into<Cow<'static, str>>,
2020        error_code: i32,
2021    ) -> Self {
2022        EtwSessionError {
2023            session_name: session_name.into(),
2024            reason: reason.into(),
2025            error_code: Some(error_code),
2026        }
2027    }
2028
2029    /// Session already exists error (common case).
2030    pub fn already_exists(session_name: impl Into<Cow<'static, str>>) -> Self {
2031        EtwSessionError {
2032            session_name: session_name.into(),
2033            reason: Cow::Borrowed("Session already exists"),
2034            error_code: Some(-2147024713), // ERROR_ALREADY_EXISTS (0x800700B7)
2035        }
2036    }
2037
2038    /// Invalid configuration error.
2039    pub fn invalid_config(
2040        session_name: impl Into<Cow<'static, str>>,
2041        field: &'static str,
2042        issue: impl Into<Cow<'static, str>>,
2043    ) -> Self {
2044        EtwSessionError {
2045            session_name: session_name.into(),
2046            reason: Cow::Owned(format!("Invalid {}: {}", field, issue.into())),
2047            error_code: None,
2048        }
2049    }
2050}
2051
2052impl fmt::Display for EtwSessionError {
2053    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2054        if let Some(code) = self.error_code {
2055            write!(
2056                f,
2057                "Failed to start ETW session '{}': {} (error code: 0x{:08X})",
2058                self.session_name, self.reason, code
2059            )
2060        } else {
2061            write!(
2062                f,
2063                "Failed to start ETW session '{}': {}",
2064                self.session_name, self.reason
2065            )
2066        }
2067    }
2068}
2069
2070impl std::error::Error for EtwSessionError {}
2071
2072/// ETW provider error.
2073#[derive(Debug)]
2074pub struct EtwProviderError {
2075    /// The provider name or GUID.
2076    pub provider: Cow<'static, str>,
2077    /// Reason for failure.
2078    pub reason: Cow<'static, str>,
2079    /// Windows error code if available.
2080    pub error_code: Option<i32>,
2081}
2082
2083impl EtwProviderError {
2084    /// Create a new provider error.
2085    pub fn new(
2086        provider: impl Into<Cow<'static, str>>,
2087        reason: impl Into<Cow<'static, str>>,
2088    ) -> Self {
2089        EtwProviderError {
2090            provider: provider.into(),
2091            reason: reason.into(),
2092            error_code: None,
2093        }
2094    }
2095
2096    /// Create a provider error with error code.
2097    pub fn with_code(
2098        provider: impl Into<Cow<'static, str>>,
2099        reason: impl Into<Cow<'static, str>>,
2100        error_code: i32,
2101    ) -> Self {
2102        EtwProviderError {
2103            provider: provider.into(),
2104            reason: reason.into(),
2105            error_code: Some(error_code),
2106        }
2107    }
2108
2109    /// Provider not found/registered error (common case).
2110    pub fn not_found(provider: impl Into<Cow<'static, str>>) -> Self {
2111        EtwProviderError {
2112            provider: provider.into(),
2113            reason: Cow::Borrowed("Provider not registered"),
2114            error_code: Some(0x00000490), // ERROR_NOT_FOUND
2115        }
2116    }
2117}
2118
2119impl fmt::Display for EtwProviderError {
2120    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2121        if let Some(code) = self.error_code {
2122            write!(
2123                f,
2124                "Failed to enable ETW provider '{}': {} (error code: 0x{:08X})",
2125                self.provider, self.reason, code
2126            )
2127        } else {
2128            write!(
2129                f,
2130                "Failed to enable ETW provider '{}': {}",
2131                self.provider, self.reason
2132            )
2133        }
2134    }
2135}
2136
2137impl std::error::Error for EtwProviderError {}
2138
2139/// ETW consume error.
2140#[derive(Debug)]
2141pub struct EtwConsumeError {
2142    /// Reason for failure.
2143    pub reason: Cow<'static, str>,
2144    /// Windows error code if available.
2145    pub error_code: Option<i32>,
2146}
2147
2148impl EtwConsumeError {
2149    /// Create a new consume error.
2150    pub fn new(reason: impl Into<Cow<'static, str>>) -> Self {
2151        EtwConsumeError {
2152            reason: reason.into(),
2153            error_code: None,
2154        }
2155    }
2156
2157    /// Create a consume error with error code.
2158    pub fn with_code(reason: impl Into<Cow<'static, str>>, error_code: i32) -> Self {
2159        EtwConsumeError {
2160            reason: reason.into(),
2161            error_code: Some(error_code),
2162        }
2163    }
2164}
2165
2166impl fmt::Display for EtwConsumeError {
2167    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2168        if let Some(code) = self.error_code {
2169            write!(
2170                f,
2171                "Failed to consume ETW events: {} (error code: 0x{:08X})",
2172                self.reason, code
2173            )
2174        } else {
2175            write!(f, "Failed to consume ETW events: {}", self.reason)
2176        }
2177    }
2178}
2179
2180impl std::error::Error for EtwConsumeError {}
2181
2182// ============================================================================
2183// Mitigation Errors
2184// ============================================================================
2185
2186/// Mitigation-specific errors.
2187#[derive(Debug)]
2188pub enum MitigationError {
2189    /// Applying one mitigation policy failed.
2190    ApplyFailed(MitigationOperationError),
2191
2192    /// Querying one mitigation policy failed.
2193    QueryFailed(MitigationOperationError),
2194}
2195
2196impl fmt::Display for MitigationError {
2197    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2198        match self {
2199            MitigationError::ApplyFailed(e) => write!(f, "{}", e),
2200            MitigationError::QueryFailed(e) => write!(f, "{}", e),
2201        }
2202    }
2203}
2204
2205impl std::error::Error for MitigationError {}
2206
2207/// Mitigation operation error.
2208#[derive(Debug)]
2209pub struct MitigationOperationError {
2210    /// Operation that failed.
2211    pub operation: Cow<'static, str>,
2212    /// Policy name associated with the operation.
2213    pub policy: Cow<'static, str>,
2214    /// Optional process ID for process-specific operations.
2215    pub process_id: Option<u32>,
2216    /// Optional reason for failure.
2217    pub reason: Option<Cow<'static, str>>,
2218    /// Windows error code if available.
2219    pub error_code: Option<i32>,
2220}
2221
2222impl MitigationOperationError {
2223    /// Create a new mitigation operation error.
2224    pub fn new(
2225        operation: impl Into<Cow<'static, str>>,
2226        policy: impl Into<Cow<'static, str>>,
2227    ) -> Self {
2228        MitigationOperationError {
2229            operation: operation.into(),
2230            policy: policy.into(),
2231            process_id: None,
2232            reason: None,
2233            error_code: None,
2234        }
2235    }
2236
2237    /// Attach a process ID context.
2238    pub fn with_process_id(mut self, process_id: u32) -> Self {
2239        self.process_id = Some(process_id);
2240        self
2241    }
2242
2243    /// Attach a reason string.
2244    pub fn with_reason(mut self, reason: impl Into<Cow<'static, str>>) -> Self {
2245        self.reason = Some(reason.into());
2246        self
2247    }
2248
2249    /// Attach a Windows error code.
2250    pub fn with_code(mut self, error_code: i32) -> Self {
2251        self.error_code = Some(error_code);
2252        self
2253    }
2254}
2255
2256impl fmt::Display for MitigationOperationError {
2257    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2258        match (self.process_id, &self.reason, self.error_code) {
2259            (Some(pid), Some(reason), Some(code)) => write!(
2260                f,
2261                "Mitigation {} failed for policy '{}' on process {}: {} (error code: 0x{:08X})",
2262                self.operation, self.policy, pid, reason, code
2263            ),
2264            (Some(pid), Some(reason), None) => write!(
2265                f,
2266                "Mitigation {} failed for policy '{}' on process {}: {}",
2267                self.operation, self.policy, pid, reason
2268            ),
2269            (Some(pid), None, Some(code)) => write!(
2270                f,
2271                "Mitigation {} failed for policy '{}' on process {} (error code: 0x{:08X})",
2272                self.operation, self.policy, pid, code
2273            ),
2274            (Some(pid), None, None) => write!(
2275                f,
2276                "Mitigation {} failed for policy '{}' on process {}",
2277                self.operation, self.policy, pid
2278            ),
2279            (None, Some(reason), Some(code)) => write!(
2280                f,
2281                "Mitigation {} failed for policy '{}': {} (error code: 0x{:08X})",
2282                self.operation, self.policy, reason, code
2283            ),
2284            (None, Some(reason), None) => write!(
2285                f,
2286                "Mitigation {} failed for policy '{}': {}",
2287                self.operation, self.policy, reason
2288            ),
2289            (None, None, Some(code)) => write!(
2290                f,
2291                "Mitigation {} failed for policy '{}' (error code: 0x{:08X})",
2292                self.operation, self.policy, code
2293            ),
2294            (None, None, None) => write!(
2295                f,
2296                "Mitigation {} failed for policy '{}'",
2297                self.operation, self.policy
2298            ),
2299        }
2300    }
2301}
2302
2303impl std::error::Error for MitigationOperationError {}
2304
2305#[cfg(test)]
2306mod tests {
2307    use super::{EtwConsumeError, EtwProviderError, EtwSessionError, MitigationOperationError};
2308    use std::borrow::Cow;
2309
2310    #[test]
2311    fn etw_session_error_invalid_config_message_contains_field() {
2312        let err = EtwSessionError::invalid_config(
2313            Cow::Borrowed("MySession"),
2314            "providers",
2315            Cow::Borrowed("cannot mix kernel and user providers"),
2316        );
2317
2318        assert_eq!(err.session_name, "MySession");
2319        assert!(err.reason.contains("Invalid providers"));
2320        assert!(err.reason.contains("cannot mix kernel and user providers"));
2321        assert!(err.error_code.is_none());
2322    }
2323
2324    #[test]
2325    fn etw_provider_error_not_found_has_expected_code() {
2326        let err = EtwProviderError::not_found(Cow::Borrowed("{provider-guid}"));
2327
2328        assert_eq!(err.provider, "{provider-guid}");
2329        assert_eq!(err.error_code, Some(0x00000490));
2330        assert!(err.reason.contains("Provider not registered"));
2331    }
2332
2333    #[test]
2334    fn etw_consume_error_display_with_code_contains_hex() {
2335        let err = EtwConsumeError::with_code(Cow::Borrowed("OpenTraceW failed"), 0x57);
2336        let rendered = err.to_string();
2337
2338        assert!(rendered.contains("OpenTraceW failed"));
2339        assert!(rendered.contains("0x00000057"));
2340    }
2341
2342    #[test]
2343    fn mitigation_operation_error_display_includes_policy_pid_and_code() {
2344        let err = MitigationOperationError::new("apply", "dynamic_code")
2345            .with_process_id(1234)
2346            .with_reason("Access denied")
2347            .with_code(5);
2348
2349        let rendered = err.to_string();
2350        assert!(rendered.contains("dynamic_code"));
2351        assert!(rendered.contains("1234"));
2352        assert!(rendered.contains("0x00000005"));
2353    }
2354}