udbg 0.3.1

cross-platform library for binary debugging and memory hacking
Documentation
use std::{fmt::Debug, os::windows::prelude::*};

use windows::Win32::{
    Foundation::{
        CloseHandle, DuplicateHandle, DUPLICATE_SAME_ACCESS, HANDLE, INVALID_HANDLE_VALUE,
        WAIT_EVENT,
    },
    System::Threading::{GetCurrentProcess, WaitForSingleObject, INFINITE},
};

#[derive(Deref)]
pub struct Handle(pub(crate) HANDLE);

unsafe impl Send for Handle {}

impl Handle {
    #[inline]
    pub fn borrow(handle: &HANDLE) -> &Self {
        unsafe { &*(handle as *const _ as *const Self) }
    }

    #[inline(always)]
    pub fn is_valid(&self) -> bool {
        self.0 != INVALID_HANDLE_VALUE
    }

    pub fn is_null(&self) -> bool {
        self.0 .0 == 0
    }

    pub fn as_windows_handle(&self) -> HANDLE {
        self.0
    }

    pub fn as_winapi(&self) -> winapi::um::winnt::HANDLE {
        self.0 .0 as _
    }

    pub fn into_owned_handle(self) -> OwnedHandle {
        let result = unsafe { OwnedHandle::from_raw_handle(self.as_raw_handle()) };
        core::mem::forget(self);
        result
    }

    #[inline]
    pub fn success(&self) -> bool {
        self.is_valid() && !self.is_null()
    }

    #[inline(always)]
    pub unsafe fn from_raw_handle(handle: HANDLE) -> Self {
        Self(handle)
    }

    #[inline(always)]
    pub unsafe fn from_winapi_handle(handle: winapi::um::winnt::HANDLE) -> Self {
        Self(HANDLE(handle as _))
    }

    pub unsafe fn clone_from_raw(handle: HANDLE) -> windows::core::Result<Self> {
        let mut result = HANDLE::default();
        DuplicateHandle(
            GetCurrentProcess(),
            handle,
            GetCurrentProcess(),
            &mut result,
            0,
            false,
            DUPLICATE_SAME_ACCESS,
        )?;
        Ok(Self::from_raw_handle(result))
    }

    #[inline(always)]
    pub fn try_clone(&self) -> windows::core::Result<Self> {
        unsafe { Self::clone_from_raw(self.0) }
    }
}

impl Handle {
    pub fn wait_single(&self, timeout: Option<u32>) -> WAIT_EVENT {
        unsafe { WaitForSingleObject(self.0, timeout.unwrap_or(INFINITE)) }
    }
}

impl Debug for Handle {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.0.fmt(f)
    }
}

impl Clone for Handle {
    fn clone(&self) -> Self {
        Handle::try_clone(self).expect("clone")
    }
}

impl Drop for Handle {
    fn drop(&mut self) {
        unsafe {
            CloseHandle(self.0).expect("CloseHandle");
        }
    }
}

impl AsRawHandle for Handle {
    fn as_raw_handle(&self) -> RawHandle {
        self.0 .0 as RawHandle
    }
}

impl AsHandle for Handle {
    fn as_handle(&self) -> BorrowedHandle<'_> {
        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
    }
}

impl IntoRawHandle for Handle {
    fn into_raw_handle(self) -> RawHandle {
        todo!()
    }
}

macro_rules! typed_handle {
    ($ty:ident: $handle:ty) => {
        #[derive(Debug, Clone, Deref)]
        pub struct $ty(pub $handle);

        impl $ty {
            #[inline]
            pub unsafe fn borrow_raw(handle: &::windows::Win32::Foundation::HANDLE) -> &Self {
                Self::borrow_handle(<$handle>::borrow(handle))
            }

            #[inline]
            pub unsafe fn borrow_handle(handle: &$handle) -> &Self {
                &*(handle as *const _ as *const Self)
            }
        }
    };
}

typed_handle!(ThreadHandle: Handle);
typed_handle!(EventHandle: Handle);