1use core::fmt;
4
5pub type NtStatus = i32;
7
8#[derive(Debug)]
10pub enum KmError {
11 NtStatus(NtStatus),
13
14 PoolAllocationFailed {
16 size: usize,
17 pool_type: u32,
18 },
19
20 MdlOperationFailed {
22 reason: &'static str,
23 },
24
25 PhysicalMemoryFailed {
27 address: u64,
28 size: usize,
29 },
30
31 VirtualMemoryFailed {
33 address: u64,
34 size: usize,
35 reason: &'static str,
36 },
37
38 ProcessOperationFailed {
40 pid: u32,
41 reason: &'static str,
42 },
43
44 DeviceCreationFailed {
46 reason: &'static str,
47 },
48
49 SymbolicLinkFailed {
51 reason: &'static str,
52 },
53
54 IoctlFailed {
56 code: u32,
57 reason: &'static str,
58 },
59
60 InvalidParameter {
62 context: &'static str,
63 },
64
65 BufferTooSmall {
67 required: usize,
68 provided: usize,
69 },
70
71 AccessDenied {
73 context: &'static str,
74 },
75
76 InvalidAddress {
78 address: u64,
79 },
80
81 NotImplemented {
83 feature: &'static str,
84 },
85}
86
87impl fmt::Display for KmError {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 match self {
90 Self::NtStatus(status) => write!(f, "NTSTATUS error: {status:#x}"),
91 Self::PoolAllocationFailed { size, pool_type } => {
92 write!(f, "pool allocation failed: {size} bytes, type {pool_type}")
93 }
94 Self::MdlOperationFailed { reason } => {
95 write!(f, "MDL operation failed: {reason}")
96 }
97 Self::PhysicalMemoryFailed { address, size } => {
98 write!(f, "physical memory access failed at {address:#x} ({size} bytes)")
99 }
100 Self::VirtualMemoryFailed { address, size, reason } => {
101 write!(f, "virtual memory operation failed at {address:#x} ({size} bytes): {reason}")
102 }
103 Self::ProcessOperationFailed { pid, reason } => {
104 write!(f, "process operation failed for PID {pid}: {reason}")
105 }
106 Self::DeviceCreationFailed { reason } => {
107 write!(f, "device creation failed: {reason}")
108 }
109 Self::SymbolicLinkFailed { reason } => {
110 write!(f, "symbolic link creation failed: {reason}")
111 }
112 Self::IoctlFailed { code, reason } => {
113 write!(f, "IOCTL {code:#x} failed: {reason}")
114 }
115 Self::InvalidParameter { context } => {
116 write!(f, "invalid parameter in {context}")
117 }
118 Self::BufferTooSmall { required, provided } => {
119 write!(f, "buffer too small: need {required} bytes, got {provided}")
120 }
121 Self::AccessDenied { context } => {
122 write!(f, "access denied: {context}")
123 }
124 Self::InvalidAddress { address } => {
125 write!(f, "invalid address: {address:#x}")
126 }
127 Self::NotImplemented { feature } => {
128 write!(f, "not implemented: {feature}")
129 }
130 }
131 }
132}
133
134pub type KmResult<T> = core::result::Result<T, KmError>;
136
137pub mod status {
139 use super::NtStatus;
140
141 pub const STATUS_SUCCESS: NtStatus = 0;
142 pub const STATUS_UNSUCCESSFUL: NtStatus = 0xC0000001_u32 as i32;
143 pub const STATUS_NOT_IMPLEMENTED: NtStatus = 0xC0000002_u32 as i32;
144 pub const STATUS_INVALID_HANDLE: NtStatus = 0xC0000008_u32 as i32;
145 pub const STATUS_INVALID_PARAMETER: NtStatus = 0xC000000D_u32 as i32;
146 pub const STATUS_NO_SUCH_DEVICE: NtStatus = 0xC000000E_u32 as i32;
147 pub const STATUS_NO_SUCH_FILE: NtStatus = 0xC000000F_u32 as i32;
148 pub const STATUS_ACCESS_DENIED: NtStatus = 0xC0000022_u32 as i32;
149 pub const STATUS_BUFFER_TOO_SMALL: NtStatus = 0xC0000023_u32 as i32;
150 pub const STATUS_OBJECT_NAME_NOT_FOUND: NtStatus = 0xC0000034_u32 as i32;
151 pub const STATUS_OBJECT_NAME_COLLISION: NtStatus = 0xC0000035_u32 as i32;
152 pub const STATUS_INSUFFICIENT_RESOURCES: NtStatus = 0xC000009A_u32 as i32;
153 pub const STATUS_INVALID_DEVICE_REQUEST: NtStatus = 0xC0000010_u32 as i32;
154 pub const STATUS_INFO_LENGTH_MISMATCH: NtStatus = 0xC0000004_u32 as i32;
155 pub const STATUS_PARTIAL_COPY: NtStatus = 0x8000000D_u32 as i32;
156 pub const STATUS_NO_MEMORY: NtStatus = 0xC0000017_u32 as i32;
157
158 #[inline]
160 pub const fn nt_success(status: NtStatus) -> bool {
161 status >= 0
162 }
163
164 #[inline]
166 pub const fn nt_information(status: NtStatus) -> bool {
167 (status as u32) >> 30 == 1
168 }
169
170 #[inline]
172 pub const fn nt_warning(status: NtStatus) -> bool {
173 (status as u32) >> 30 == 2
174 }
175
176 #[inline]
178 pub const fn nt_error(status: NtStatus) -> bool {
179 (status as u32) >> 30 == 3
180 }
181}
182
183impl From<NtStatus> for KmError {
184 fn from(status: NtStatus) -> Self {
185 KmError::NtStatus(status)
186 }
187}
188
189impl KmError {
190 pub fn to_ntstatus(&self) -> NtStatus {
192 match self {
193 Self::NtStatus(s) => *s,
194 Self::PoolAllocationFailed { .. } => status::STATUS_INSUFFICIENT_RESOURCES,
195 Self::MdlOperationFailed { .. } => status::STATUS_UNSUCCESSFUL,
196 Self::PhysicalMemoryFailed { .. } => status::STATUS_ACCESS_DENIED,
197 Self::VirtualMemoryFailed { .. } => status::STATUS_ACCESS_DENIED,
198 Self::ProcessOperationFailed { .. } => status::STATUS_UNSUCCESSFUL,
199 Self::DeviceCreationFailed { .. } => status::STATUS_UNSUCCESSFUL,
200 Self::SymbolicLinkFailed { .. } => status::STATUS_UNSUCCESSFUL,
201 Self::IoctlFailed { .. } => status::STATUS_UNSUCCESSFUL,
202 Self::InvalidParameter { .. } => status::STATUS_INVALID_PARAMETER,
203 Self::BufferTooSmall { .. } => status::STATUS_BUFFER_TOO_SMALL,
204 Self::AccessDenied { .. } => status::STATUS_ACCESS_DENIED,
205 Self::InvalidAddress { .. } => status::STATUS_INVALID_PARAMETER,
206 Self::NotImplemented { .. } => status::STATUS_NOT_IMPLEMENTED,
207 }
208 }
209}