use std::ops::{Deref, DerefMut};
use crate::decl::*;
use crate::kernel::ffi;
use crate::prelude::*;
pub struct CloseHandleGuard<T>
where
T: Handle,
{
handle: T,
}
impl<T> Drop for CloseHandleGuard<T>
where
T: Handle,
{
fn drop(&mut self) {
if let Some(h) = self.handle.as_opt() {
unsafe {
ffi::CloseHandle(h.ptr()); }
}
}
}
impl<T> Deref for CloseHandleGuard<T>
where
T: Handle,
{
type Target = T;
fn deref(&self) -> &Self::Target {
&self.handle
}
}
impl<T> DerefMut for CloseHandleGuard<T>
where
T: Handle,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.handle
}
}
impl<T> CloseHandleGuard<T>
where
T: Handle,
{
#[must_use]
pub const unsafe fn new(handle: T) -> Self {
Self { handle }
}
#[must_use]
pub fn leak(&mut self) -> T {
std::mem::replace(&mut self.handle, T::INVALID)
}
}
pub struct CloseHandlePiGuard {
pi: PROCESS_INFORMATION,
}
impl Drop for CloseHandlePiGuard {
fn drop(&mut self) {
if let Some(h) = self.pi.hProcess.as_opt() {
let _ = unsafe { CloseHandleGuard::new(h.raw_copy()) };
}
if let Some(h) = self.pi.hThread.as_opt() {
let _ = unsafe { CloseHandleGuard::new(h.raw_copy()) };
}
}
}
impl Deref for CloseHandlePiGuard {
type Target = PROCESS_INFORMATION;
fn deref(&self) -> &Self::Target {
&self.pi
}
}
impl DerefMut for CloseHandlePiGuard {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.pi
}
}
impl CloseHandlePiGuard {
#[must_use]
pub const unsafe fn new(pi: PROCESS_INFORMATION) -> Self {
Self { pi }
}
#[must_use]
pub fn leak(&mut self) -> PROCESS_INFORMATION {
std::mem::take(&mut self.pi)
}
}
pub struct EndUpdateResourceGuard {
hupsrc: HUPDATERSRC,
}
impl Drop for EndUpdateResourceGuard {
fn drop(&mut self) {
if let Some(h) = self.hupsrc.as_opt() {
unsafe {
ffi::EndUpdateResourceW(h.ptr(), false as _);
} }
}
}
impl Deref for EndUpdateResourceGuard {
type Target = HUPDATERSRC;
fn deref(&self) -> &Self::Target {
&self.hupsrc
}
}
impl DerefMut for EndUpdateResourceGuard {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.hupsrc
}
}
impl EndUpdateResourceGuard {
#[must_use]
pub const unsafe fn new(hupsrc: HUPDATERSRC) -> Self {
Self { hupsrc }
}
#[must_use]
pub fn leak(&mut self) -> HUPDATERSRC {
std::mem::replace(&mut self.hupsrc, HUPDATERSRC::INVALID)
}
}
handle_guard! { FindCloseGuard: HFINDFILE;
ffi::FindClose;
}
handle_guard! { FreeLibraryGuard: HINSTANCE;
ffi::FreeLibrary;
}
handle_guard! { GlobalFreeGuard: HGLOBAL;
ffi::GlobalFree;
}
pub struct GlobalUnlockGuard<'a> {
hglobal: &'a HGLOBAL,
pmem: *mut std::ffi::c_void,
sz: usize,
}
impl<'a> Drop for GlobalUnlockGuard<'a> {
fn drop(&mut self) {
if let Some(h) = self.hglobal.as_opt() {
unsafe {
ffi::GlobalUnlock(h.ptr()); }
}
}
}
impl<'a> GlobalUnlockGuard<'a> {
#[must_use]
pub const unsafe fn new(hglobal: &'a HGLOBAL, pmem: *mut std::ffi::c_void, sz: usize) -> Self {
Self { hglobal, pmem, sz }
}
pub_fn_mem_block!();
}
handle_guard! { HeapDestroyGuard: HHEAP;
ffi::HeapDestroy;
}
pub struct HeapFreeGuard<'a> {
hheap: &'a HHEAP,
pmem: *mut std::ffi::c_void,
sz: usize,
}
impl<'a> Drop for HeapFreeGuard<'a> {
fn drop(&mut self) {
if let Some(h) = self.hheap.as_opt() {
if !self.pmem.is_null() {
unsafe {
ffi::HeapFree(h.ptr(), 0, self.pmem); }
}
}
}
}
impl<'a> HeapFreeGuard<'a> {
#[must_use]
pub const unsafe fn new(hheap: &'a HHEAP, pmem: *mut std::ffi::c_void, sz: usize) -> Self {
Self { hheap, pmem, sz }
}
#[must_use]
pub fn leak(&mut self) -> (*mut std::ffi::c_void, usize) {
(
std::mem::replace(&mut self.pmem, std::ptr::null_mut()),
std::mem::replace(&mut self.sz, 0),
)
}
pub_fn_mem_block!();
}
pub struct HeapUnlockGuard<'a> {
hheap: &'a HHEAP,
}
impl<'a> Drop for HeapUnlockGuard<'a> {
fn drop(&mut self) {
if let Some(h) = self.hheap.as_opt() {
unsafe {
ffi::HeapUnlock(h.ptr()); }
}
}
}
impl<'a> HeapUnlockGuard<'a> {
#[must_use]
pub const unsafe fn new(hheap: &'a HHEAP) -> Self {
Self { hheap }
}
}
handle_guard! { LocalFreeGuard: HLOCAL;
ffi::LocalFree;
}
pub struct LocalUnlockGuard<'a> {
hlocal: &'a HLOCAL,
pmem: *mut std::ffi::c_void,
sz: usize,
}
impl<'a> Drop for LocalUnlockGuard<'a> {
fn drop(&mut self) {
if let Some(h) = self.hlocal.as_opt() {
unsafe {
ffi::LocalUnlock(h.ptr()); }
}
}
}
impl<'a> LocalUnlockGuard<'a> {
#[must_use]
pub const unsafe fn new(hlocal: &'a HLOCAL, pmem: *mut std::ffi::c_void, sz: usize) -> Self {
Self { hlocal, pmem, sz }
}
pub_fn_mem_block!();
}
handle_guard! { ReleaseActCtxGuard: HACTCTX;
ffi::ReleaseActCtx;
}
pub struct UnlockFileGuard<'a> {
hfile: &'a HFILE,
offset: u64,
num_bytes_to_lock: u64,
}
impl<'a> Drop for UnlockFileGuard<'a> {
fn drop(&mut self) {
if let Some(h) = self.hfile.as_opt() {
unsafe {
ffi::UnlockFile(
h.ptr(),
LODWORD(self.offset),
HIDWORD(self.offset),
LODWORD(self.num_bytes_to_lock),
HIDWORD(self.num_bytes_to_lock),
); }
}
}
}
impl<'a> UnlockFileGuard<'a> {
#[must_use]
pub const unsafe fn new(hfile: &'a HFILE, offset: u64, num_bytes_to_lock: u64) -> Self {
Self { hfile, offset, num_bytes_to_lock }
}
#[must_use]
pub const fn offset(&self) -> u64 {
self.offset
}
#[must_use]
pub const fn num_bytes_to_lock(&self) -> u64 {
self.num_bytes_to_lock
}
}
handle_guard! { UnmapViewOfFileGuard: HFILEMAPVIEW;
ffi::UnmapViewOfFile;
}