use crate::error::{Error, Result};
use windows::Win32::Foundation::HANDLE;
use windows::Win32::Security::{ImpersonateLoggedOnUser, RevertToSelf};
use windows::Win32::System::Threading::SetThreadToken;
#[must_use = "dropping this guard calls RevertToSelf; if you drop it immediately \
the impersonation is instantly reverted"]
pub struct ImpersonationGuard {
_not_send: core::marker::PhantomData<*const ()>,
}
impl ImpersonationGuard {
pub(crate) fn impersonate_logged_on(token: HANDLE) -> Result<Self> {
unsafe {
ImpersonateLoggedOnUser(token)
.map_err(|e| Error::win32("ImpersonateLoggedOnUser", e))?;
}
Ok(ImpersonationGuard {
_not_send: core::marker::PhantomData,
})
}
pub(crate) fn set_on_current_thread(token: HANDLE) -> Result<Self> {
unsafe {
SetThreadToken(None, token).map_err(|e| Error::win32("SetThreadToken", e))?;
}
Ok(ImpersonationGuard {
_not_send: core::marker::PhantomData,
})
}
}
impl Drop for ImpersonationGuard {
fn drop(&mut self) {
unsafe {
let r = RevertToSelf();
debug_assert!(
r.is_ok(),
"RevertToSelf failed in ImpersonationGuard::drop: {:?}",
r
);
}
}
}