1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
#![cfg(windows)] use std::ptr; use information::TokenInformation; use winapi::um::handleapi::CloseHandle; use winapi::um::winnt::HANDLE; use winapi::um::{ processthreadsapi::{GetCurrentProcess, GetCurrentThread, OpenProcessToken, OpenThreadToken}, securitybaseapi::GetTokenInformation, }; use winapi::{ctypes::c_void, shared::winerror, um::errhandlingapi::GetLastError}; pub mod information; mod level; pub mod security; pub use level::TokenAccessLevel; pub struct AccessToken { handle: HANDLE, } impl AccessToken { pub(crate) fn from_raw_handle(handle: HANDLE) -> Self { Self { handle } } pub fn open_process(access_level: TokenAccessLevel) -> Result<Self, std::io::Error> { let mut handle = ptr::null_mut(); unsafe { if OpenProcessToken(GetCurrentProcess(), access_level.bits(), &mut handle) == 0 { let error = std::io::Error::from_raw_os_error(GetLastError() as i32); return Err(error); } } Ok(AccessToken { handle }) } pub fn open_thread( open_as_self: bool, access_level: TokenAccessLevel, ) -> Result<Self, std::io::Error> { let mut handle = ptr::null_mut(); unsafe { if OpenThreadToken( GetCurrentThread(), access_level.bits(), open_as_self as i32, &mut handle, ) == 0 { let error = std::io::Error::from_raw_os_error(GetLastError() as i32); return Err(error); } } Ok(AccessToken { handle }) } pub fn token_information<T: TokenInformation>( &self, ) -> Result<Option<T::Output>, std::io::Error> { let mut length: u32 = 0; unsafe { if GetTokenInformation(self.handle, T::LEVEL, ptr::null_mut(), 0, &mut length) != 0 { return Ok(None); } match GetLastError() { winerror::ERROR_BAD_LENGTH | winerror::ERROR_INSUFFICIENT_BUFFER => {} code => return Err(std::io::Error::from_raw_os_error(code as i32)), } let mut buffer = vec![0u8; length as usize]; if GetTokenInformation( self.handle, T::LEVEL, buffer.as_mut_ptr() as *mut c_void, length, &mut length, ) == 0 { let code = GetLastError(); return Err(std::io::Error::from_raw_os_error(code as i32)); } Ok(T::from_buf(&buffer)) } } } impl Drop for AccessToken { fn drop(&mut self) { unsafe { CloseHandle(self.handle); } } } #[cfg(test)] mod tests { #[test] fn it_works() { assert_eq!(2 + 2, 4); } }