mod driver;
mod process;
mod memory;
pub mod ioctl;
pub use driver::{DriverClient, DriverHandle};
pub use process::ProcessOps;
pub use memory::{RemoteMemory, MemoryProtection};
pub use ioctl::{IoctlCode, IoctlRequest, IoctlResponse};
use std::io;
pub type ClientResult<T> = Result<T, ClientError>;
#[derive(Debug)]
pub enum ClientError {
DriverOpenFailed(io::Error),
DriverNotFound,
IoctlFailed {
code: u32,
error: io::Error,
},
InvalidResponse {
expected: usize,
received: usize,
},
ProcessError {
pid: u32,
reason: String,
},
MemoryError {
address: u64,
reason: String,
},
BufferTooSmall {
required: usize,
provided: usize,
},
NotSupported,
}
impl std::fmt::Display for ClientError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::DriverOpenFailed(e) => write!(f, "failed to open driver: {e}"),
Self::DriverNotFound => write!(f, "driver not found"),
Self::IoctlFailed { code, error } => write!(f, "IOCTL {code:#x} failed: {error}"),
Self::InvalidResponse { expected, received } => {
write!(f, "invalid response: expected {expected} bytes, got {received}")
}
Self::ProcessError { pid, reason } => {
write!(f, "process {pid} error: {reason}")
}
Self::MemoryError { address, reason } => {
write!(f, "memory error at {address:#x}: {reason}")
}
Self::BufferTooSmall { required, provided } => {
write!(f, "buffer too small: need {required}, got {provided}")
}
Self::NotSupported => write!(f, "operation not supported"),
}
}
}
impl std::error::Error for ClientError {}
impl From<io::Error> for ClientError {
fn from(e: io::Error) -> Self {
Self::DriverOpenFailed(e)
}
}