use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use crate::advapi::ffi;
use crate::co;
use crate::decl::*;
use crate::guard::*;
use crate::prelude::*;
handle_guard! { CloseServiceHandleGuard: HSC;
ffi::CloseServiceHandle;
}
handle_guard! { CloseServiceHandleSvcGuard: HSERVICE;
ffi::CloseServiceHandle;
}
handle_guard! { DeregisterEventSourceGuard: HEVENTLOG;
ffi::DeregisterEventSource;
}
pub struct FreeSidGuard {
psid: *mut SID,
}
impl Drop for FreeSidGuard {
fn drop(&mut self) {
if !self.psid.is_null() {
unsafe {
ffi::FreeSid(self.psid as *mut _ as _); }
}
}
}
impl Deref for FreeSidGuard {
type Target = SID;
fn deref(&self) -> &Self::Target {
unsafe { &*self.psid }
}
}
impl std::fmt::Display for FreeSidGuard {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.deref(), f) }
}
impl FreeSidGuard {
#[must_use]
pub const unsafe fn new(psid: *mut SID) -> Self {
Self { psid }
}
#[must_use]
pub fn leak(&mut self) -> *mut SID {
std::mem::replace(&mut self.psid, std::ptr::null_mut())
}
}
pub struct RegCloseKeyGuard {
hkey: HKEY,
}
impl Drop for RegCloseKeyGuard {
fn drop(&mut self) {
if let Some(h) = self.hkey.as_opt() {
if !self.is_predef_key() {
unsafe {
ffi::RegCloseKey(h.ptr()); }
}
}
}
}
impl Deref for RegCloseKeyGuard {
type Target = HKEY;
fn deref(&self) -> &Self::Target {
&self.hkey
}
}
impl DerefMut for RegCloseKeyGuard {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.hkey
}
}
impl RegCloseKeyGuard {
#[must_use]
pub const unsafe fn new(hkey: HKEY) -> Self {
Self { hkey }
}
#[must_use]
pub fn leak(&mut self) -> HKEY {
std::mem::replace(&mut self.hkey, HKEY::INVALID)
}
}
pub struct LocalFreeSidGuard {
pmem: LocalFreeGuard,
}
impl Deref for LocalFreeSidGuard {
type Target = SID;
fn deref(&self) -> &Self::Target {
unsafe { &*(self.pmem.ptr() as *mut _) }
}
}
impl std::fmt::Display for LocalFreeSidGuard {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.deref(), f) }
}
impl LocalFreeSidGuard {
#[must_use]
pub const unsafe fn new(pmem: HLOCAL) -> Self {
Self {
pmem: unsafe { LocalFreeGuard::new(pmem) },
}
}
}
pub struct SidGuard {
ptr: GlobalFreeGuard,
}
impl Deref for SidGuard {
type Target = SID;
fn deref(&self) -> &Self::Target {
unsafe { &*(self.ptr.ptr() as *const _) }
}
}
impl std::fmt::Display for SidGuard {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.deref(), f) }
}
impl SidGuard {
#[must_use]
pub const unsafe fn new(ptr: GlobalFreeGuard) -> Self {
Self { ptr }
}
}
pub struct TokenGroupsGuard<'a> {
ptr: GlobalFreeGuard,
_groups: PhantomData<&'a ()>,
}
impl<'a> Deref for TokenGroupsGuard<'a> {
type Target = TOKEN_GROUPS<'a>;
fn deref(&self) -> &Self::Target {
unsafe { &*(self.ptr.ptr() as *const _) }
}
}
impl<'a> DerefMut for TokenGroupsGuard<'a> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *(self.ptr.ptr() as *mut _) }
}
}
impl<'a> TokenGroupsGuard<'a> {
#[must_use]
pub(in crate::advapi) fn new(groups: &'a [SID_AND_ATTRIBUTES<'a>]) -> SysResult<Self> {
let sz = std::mem::size_of::<TOKEN_GROUPS>() - std::mem::size_of::<SID_AND_ATTRIBUTES>()
+ (groups.len() * std::mem::size_of::<SID_AND_ATTRIBUTES>());
let mut new_self = Self {
ptr: HGLOBAL::GlobalAlloc(co::GMEM::FIXED | co::GMEM::ZEROINIT, sz)?,
_groups: PhantomData,
};
new_self.GroupCount = groups.len() as _;
groups
.iter()
.zip(new_self.Groups_mut())
.for_each(|(src, dest)| *dest = src.clone()); Ok(new_self)
}
}
pub struct TokenPrivilegesGuard {
ptr: GlobalFreeGuard,
}
impl Deref for TokenPrivilegesGuard {
type Target = TOKEN_PRIVILEGES;
fn deref(&self) -> &Self::Target {
unsafe { &*(self.ptr.ptr() as *const _) }
}
}
impl DerefMut for TokenPrivilegesGuard {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *(self.ptr.ptr() as *mut _) }
}
}
impl TokenPrivilegesGuard {
#[must_use]
pub(in crate::advapi) fn new(privileges: &[LUID_AND_ATTRIBUTES]) -> SysResult<Self> {
let sz = std::mem::size_of::<TOKEN_PRIVILEGES>() - std::mem::size_of::<LUID_AND_ATTRIBUTES>()
+ (privileges.len() * std::mem::size_of::<LUID_AND_ATTRIBUTES>());
let mut new_self = Self {
ptr: HGLOBAL::GlobalAlloc(co::GMEM::FIXED | co::GMEM::ZEROINIT, sz)?,
};
new_self.PrivilegeCount = privileges.len() as _;
privileges
.iter()
.zip(new_self.Privileges_mut())
.for_each(|(src, dest)| *dest = *src); Ok(new_self)
}
}