Skip to main content

dll_syringe/rpc/
error.rs

1use std::io;
2
3use thiserror::Error;
4use winapi::shared::winerror::ERROR_PARTIAL_COPY;
5
6use crate::error::ExceptionCode;
7
8#[derive(Debug, Error)]
9#[cfg(feature = "rpc-core")]
10#[cfg_attr(all(feature = "rpc-core", not(feature = "rpc-raw")), doc(hidden))]
11#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "rpc-raw")))]
12/// An enum repsenting possible errors during remote procedure calls without serialization, deserialization or remote panics.
13pub enum RawRpcError {
14    /// Variant representing an io error.
15    #[error("io error: {}", _0)]
16    Io(io::Error),
17    /// Variant representing an unhandled exception inside the target process.
18    #[error("remote exception: {}", _0)]
19    RemoteException(ExceptionCode),
20    /// Variant representing an inaccessible target process.
21    /// This can occur if it crashed or was terminated.
22    #[error("inaccessible target process")]
23    ProcessInaccessible,
24    /// Variant representing an inaccessible target module.
25    /// This can occur if the target module was ejected or unloaded.
26    #[error("inaccessible target module")]
27    ModuleInaccessible,
28}
29
30#[cfg(feature = "rpc-core")]
31#[cfg_attr(all(feature = "rpc-core", not(feature = "rpc-raw")), doc(hidden))]
32impl From<io::Error> for RawRpcError {
33    fn from(err: io::Error) -> Self {
34        if err.raw_os_error() == Some(ERROR_PARTIAL_COPY as _)
35            || err.kind() == io::ErrorKind::PermissionDenied
36        {
37            Self::ProcessInaccessible
38        } else {
39            Self::Io(err)
40        }
41    }
42}
43
44#[cfg(feature = "rpc-core")]
45#[cfg_attr(all(feature = "rpc-core", not(feature = "rpc-raw")), doc(hidden))]
46impl From<ExceptionCode> for RawRpcError {
47    fn from(err: ExceptionCode) -> Self {
48        Self::RemoteException(err)
49    }
50}
51
52/// Error enum for errors during serialization or deserialization of rpc arguments.
53#[derive(Debug, Error)]
54#[cfg(feature = "rpc-payload")]
55#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "rpc-payload")))]
56pub enum SerdeError {
57    /// Variant representing an error during serialization.
58    #[error("serialize error: {}", _0)]
59    Serialize(#[from] bincode::error::EncodeError),
60    /// Variant representing an error during deserialization.
61    #[error("deserialize error: {}", _0)]
62    Deserialize(#[from] bincode::error::DecodeError),
63}
64
65#[derive(Debug, Error)]
66#[cfg(feature = "rpc-payload")]
67#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "rpc-payload")))]
68/// An enum repsenting possible errors during remote procedure calls.
69pub enum PayloadRpcError {
70    /// Variant representing an io error.
71    #[error("io error: {}", _0)]
72    Io(io::Error),
73    /// Variant representing an unhandled exception inside the target process.
74    #[error("remote exception: {}", _0)]
75    RemoteException(ExceptionCode),
76    /// Variant representing an inaccessible target process.
77    /// This can occur if it crashed or was terminated.
78    #[error("inaccessible target process")]
79    ProcessInaccessible,
80    /// Variant representing an inaccessible target module.
81    /// This can occur if the target module was ejected or unloaded.
82    #[error("inaccessible target module")]
83    ModuleInaccessible,
84    /// Variant representing an error in the remote procedure.
85    #[error("remote procedure error: {}", _0)]
86    RemoteProcedure(String),
87    /// Variant representing an error while serializing or deserializing.
88    #[error("serde error: {}", _0)]
89    Serde(#[from] SerdeError),
90}
91
92#[cfg(feature = "rpc-payload")]
93impl From<bincode::error::EncodeError> for PayloadRpcError {
94    fn from(err: bincode::error::EncodeError) -> Self {
95        Self::Serde(SerdeError::Serialize(err))
96    }
97}
98
99#[cfg(feature = "rpc-payload")]
100impl From<bincode::error::DecodeError> for PayloadRpcError {
101    fn from(err: bincode::error::DecodeError) -> Self {
102        Self::Serde(SerdeError::Deserialize(err))
103    }
104}
105
106#[cfg(feature = "rpc-payload")]
107impl From<io::Error> for PayloadRpcError {
108    fn from(err: io::Error) -> Self {
109        if err.raw_os_error() == Some(ERROR_PARTIAL_COPY as _)
110            || err.kind() == io::ErrorKind::PermissionDenied
111        {
112            Self::ProcessInaccessible
113        } else {
114            Self::Io(err)
115        }
116    }
117}
118
119#[cfg(all(feature = "rpc-payload", feature = "rpc-raw"))]
120impl From<RawRpcError> for PayloadRpcError {
121    fn from(err: RawRpcError) -> Self {
122        match err {
123            RawRpcError::Io(err) => Self::Io(err),
124            RawRpcError::RemoteException(code) => Self::RemoteException(code),
125            RawRpcError::ProcessInaccessible => Self::ProcessInaccessible,
126            RawRpcError::ModuleInaccessible => Self::ModuleInaccessible,
127        }
128    }
129}