#![allow(dead_code)]
use crate::*;
use crate::alloc::CBox;
use winapi::shared::basetsd::DWORD64;
use winapi::shared::minwindef::{FALSE, WORD, DWORD, LPVOID};
use winapi::shared::ntdef::*;
use winapi::um::processthreadsapi::*;
use winapi::um::winnt::SECURITY_CAPABILITIES;
use core::fmt::{self, Debug, Formatter};
use core::marker::PhantomData;
use core::mem::size_of_val;
use core::ptr::null_mut;
#[repr(transparent)] pub struct ThreadAttributeList<'a>(CBox<PROC_THREAD_ATTRIBUTE_LIST>, PhantomData<&'a HANDLE>);
impl<'a> Drop for ThreadAttributeList<'a> { fn drop(&mut self) { unsafe { DeleteProcThreadAttributeList(self.0.as_mut_ptr()) } } }
impl Debug for ThreadAttributeList<'_> { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { write!(fmt, "process::ThreadAttributeList {{ .. }}") } }
impl<'a> ThreadAttributeList<'a> {
pub fn new() -> Self { Self::with_attribute_capacity(27).unwrap() }
pub fn with_attribute_capacity(attributes: u32) -> Result<Self, Error> {
let mut bytes = 0;
let _ = unsafe { InitializeProcThreadAttributeList(null_mut(), attributes, 0, &mut bytes) }; let mut cb = CBox::<PROC_THREAD_ATTRIBUTE_LIST>::new_oversized(Default::default(), bytes);
Error::get_last_if(FALSE == unsafe { InitializeProcThreadAttributeList(cb.as_mut_ptr(), attributes, 0, &mut bytes) })?;
Ok(Self(cb, PhantomData))
}
pub fn update<'s>(&'s mut self, ThreadAttributeRef(attribute, value, size, _): ThreadAttributeRef<'a>) -> Result<&'s mut Self, Error> where 'a : 's {
Error::get_last_if(FALSE == unsafe { UpdateProcThreadAttribute(
self.0.as_mut_ptr(),
0, attribute,
value,
size,
null_mut(), null_mut(), )})?;
Ok(self)
}
}
impl<'a> TryFrom<&'_ [ThreadAttributeRef<'a>]> for ThreadAttributeList<'a> {
type Error = Error;
fn try_from(refs: &'_ [ThreadAttributeRef<'a>]) -> Result<Self, Error> {
let len = refs.len().try_into().unwrap_or(!0u32);
let mut list = Self::with_attribute_capacity(len)?;
for r in refs.iter().copied() { list.update(r)?; }
Ok(list)
}
}
#[derive(Clone, Copy)] pub struct ThreadAttributeRef<'a>(usize, LPVOID, usize, PhantomData<&'a usize>);
impl<'a> ThreadAttributeRef<'a> {
pub unsafe fn from_raw<T: ?Sized + 'a>(attribute: usize, value: &'a T) -> Self { Self(attribute, value as *const _ as *mut _, size_of_val(value), PhantomData) }
}
impl<'a> ThreadAttributeRef<'a> {
pub fn group_affinity(value: &'a GROUP_AFFINITY) -> Self { unsafe { Self::from_raw(PROC_THREAD_ATTRIBUTE_GROUP_AFFINITY, value) } }
pub fn handle_list(value: &'a [handle::Borrowed<'a>]) -> Self { unsafe { Self::from_raw(PROC_THREAD_ATTRIBUTE_HANDLE_LIST, value) } }
pub fn ideal_processor_ntdef(value: &'a winapi::shared::ntdef::PROCESSOR_NUMBER) -> Self { unsafe { Self::from_raw(PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR, value) } }
pub fn ideal_processor_winnt(value: &'a winapi::um::winnt::PROCESSOR_NUMBER) -> Self { unsafe { Self::from_raw(PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR, value) } }
pub fn machine_type(value: &'a WORD) -> Self { unsafe { Self::from_raw(PROC_THREAD_ATTRIBUTE_MACHINE_TYPE, value) } }
pub fn mitigation_policy(value: &'a process::creation::MitigationPolicy) -> Self { unsafe { Self::from_raw(PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, value) } }
pub fn parent_process(value: &'a process::OwnedHandle) -> Self { unsafe { Self::from_raw(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, value) } }
pub fn preferred_node(value: &'a u8) -> Self { unsafe { Self::from_raw(PROC_THREAD_ATTRIBUTE_PREFERRED_NODE, value) } }
pub unsafe fn security_capabilities_raw(value: &'a SECURITY_CAPABILITIES) -> Self { unsafe { Self::from_raw(PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES, value) } }
pub fn protection_level(value: &'a DWORD) -> Self { unsafe { Self::from_raw(PROC_THREAD_ATTRIBUTE_PROTECTION_LEVEL, value) } }
pub fn child_process_policy(value: &'a process::creation::ChildProcessPolicyFlags) -> Self { unsafe { Self::from_raw(PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY, value) } }
pub fn desktop_app_policy(value: &'a process::creation::DesktopAppPolicyFlags) -> Self { unsafe { Self::from_raw(PROC_THREAD_ATTRIBUTE_DESKTOP_APP_POLICY, value) } }
pub fn job_list(value: &'a [job::Handle<'a>]) -> Self { unsafe { Self::from_raw(PROC_THREAD_ATTRIBUTE_JOB_LIST, value) } }
pub fn enable_optional_xstate_features(value: &'a DWORD64) -> Self { unsafe { Self::from_raw(PROC_THREAD_ATTRIBUTE_ENABLE_OPTIONAL_XSTATE_FEATURES, value) } }
pub fn component_filter_flags(component_flags: &'a DWORD) -> Self { unsafe { Self::from_raw(PROC_THREAD_ATTRIBUTE_COMPONENT_FILTER, component_flags) } }
}
const PROC_THREAD_ATTRIBUTE_NUMBER : usize = 0x0000FFFF;
const PROC_THREAD_ATTRIBUTE_THREAD : usize = 0x00010000; const PROC_THREAD_ATTRIBUTE_INPUT : usize = 0x00020000; const PROC_THREAD_ATTRIBUTE_ADDITIVE : usize = 0x00040000;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(usize)] enum ProcThreadAttribute { ParentProcess = 0,
HandleList = 2,
GroupAffinity = 3,
PreferredNode = 4,
IdealProcessor = 5,
UmsThread = 6,
MitigationPolicy = 7,
SecurityCapabilities = 9,
ProtectionLevel = 11,
JobList = 13,
ChildProcessPolicy = 14,
AllApplicationPackagesPolicy = 15,
Win32kFilter = 16,
SafeOpenPromptOriginClaim = 17,
DesktopAppPolicy = 18,
PseudoConsole = 22,
MitigationAuditPolicy = 24,
MachineType = 25,
ComponentFilter = 26,
EnableOptionalXStateFeatures = 27,
TrustedApp = 29,
}
#[allow(non_snake_case)] const fn ProcThreadAttributeValue(number: ProcThreadAttribute, thread: bool, input: bool, additive: bool) -> usize {
0 | (number as usize & PROC_THREAD_ATTRIBUTE_NUMBER)
| if thread { PROC_THREAD_ATTRIBUTE_THREAD } else { 0 }
| if input { PROC_THREAD_ATTRIBUTE_INPUT } else { 0 }
| if additive { PROC_THREAD_ATTRIBUTE_ADDITIVE } else { 0 }
}
const PROC_THREAD_ATTRIBUTE_PARENT_PROCESS : usize = ProcThreadAttributeValue(ProcThreadAttribute::ParentProcess, false, true, false);
const PROC_THREAD_ATTRIBUTE_HANDLE_LIST : usize = ProcThreadAttributeValue(ProcThreadAttribute::HandleList, false, true, false);
const PROC_THREAD_ATTRIBUTE_GROUP_AFFINITY : usize = ProcThreadAttributeValue(ProcThreadAttribute::GroupAffinity, true, true, false);
const PROC_THREAD_ATTRIBUTE_PREFERRED_NODE : usize = ProcThreadAttributeValue(ProcThreadAttribute::PreferredNode, false, true, false);
const PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR : usize = ProcThreadAttributeValue(ProcThreadAttribute::IdealProcessor, true, true, false);
const PROC_THREAD_ATTRIBUTE_UMS_THREAD : usize = ProcThreadAttributeValue(ProcThreadAttribute::UmsThread, true, true, false);
const PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY : usize = ProcThreadAttributeValue(ProcThreadAttribute::MitigationPolicy, false, true, false);
const PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES : usize = ProcThreadAttributeValue(ProcThreadAttribute::SecurityCapabilities, false, true, false);
const PROC_THREAD_ATTRIBUTE_PROTECTION_LEVEL : usize = ProcThreadAttributeValue(ProcThreadAttribute::ProtectionLevel, false, true, false);
const PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE : usize = ProcThreadAttributeValue(ProcThreadAttribute::PseudoConsole, false, true, false);
const PROC_THREAD_ATTRIBUTE_MACHINE_TYPE : usize = ProcThreadAttributeValue(ProcThreadAttribute::MachineType, false, true, false);
const PROC_THREAD_ATTRIBUTE_ENABLE_OPTIONAL_XSTATE_FEATURES : usize = ProcThreadAttributeValue(ProcThreadAttribute::EnableOptionalXStateFeatures, true, true, false);
const PROC_THREAD_ATTRIBUTE_JOB_LIST : usize = ProcThreadAttributeValue(ProcThreadAttribute::JobList, false, true, false);
const PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY : usize = ProcThreadAttributeValue(ProcThreadAttribute::ChildProcessPolicy, false, true, false);
const PROC_THREAD_ATTRIBUTE_ALL_APPLICATION_PACKAGES_POLICY : usize = ProcThreadAttributeValue(ProcThreadAttribute::AllApplicationPackagesPolicy, false, true, false);
const PROC_THREAD_ATTRIBUTE_WIN32K_FILTER : usize = ProcThreadAttributeValue(ProcThreadAttribute::Win32kFilter, false, true, false);
const PROC_THREAD_ATTRIBUTE_DESKTOP_APP_POLICY : usize = ProcThreadAttributeValue(ProcThreadAttribute::DesktopAppPolicy, false, true, false);
const PROC_THREAD_ATTRIBUTE_MITIGATION_AUDIT_POLICY : usize = ProcThreadAttributeValue(ProcThreadAttribute::MitigationAuditPolicy, false, true, false);
const PROC_THREAD_ATTRIBUTE_COMPONENT_FILTER : usize = ProcThreadAttributeValue(ProcThreadAttribute::ComponentFilter, false, true, false);
const PROC_THREAD_ATTRIBUTE_TRUSTED_APP : usize = ProcThreadAttributeValue(ProcThreadAttribute::TrustedApp, false, true, false);