use thiserror::Error;
use windows::Win32::Foundation::{GetHandleInformation, HANDLE};
#[derive(Error, Debug)]
pub enum HandleError {
#[error("Handle ({0:X?}) has either become invalid or was always invalid. ")]
Invalid(u64),
}
pub struct SafeHandle {
raw_handle: HANDLE,
}
impl SafeHandle {
pub fn new(raw_handle: HANDLE) -> Self {
Self { raw_handle }
}
pub fn is_valid(&self) -> bool {
if self.raw_handle.is_invalid() {
return false;
}
unsafe {
let mut flags: u32 = 0;
match GetHandleInformation(self.raw_handle, &mut flags) {
Ok(_) => true,
Err(_) => false,
}
}
}
pub fn get(&self) -> Result<HANDLE, HandleError> {
if !self.is_valid() {
return Err(HandleError::Invalid(self.raw_handle.0 as _));
}
Ok(self.raw_handle)
}
}
impl From<u64> for SafeHandle {
fn from(value: u64) -> Self {
SafeHandle::new(HANDLE(value as _))
}
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn handle_valid() {
let safe_handle_1 = SafeHandle::new(HANDLE(0x0 as _));
let safe_handle_2 = SafeHandle::new(HANDLE(0x1337 as _));
assert_eq!(safe_handle_1.is_valid(), false);
assert_eq!(safe_handle_2.is_valid(), false);
}
}