use super::ThreadId;
use crate::utils::ptr_upgrade::HandleUpgrade;
use crate::utils::windows_handle::Handle;
use std::io::Error;
use std::io::Result;
use std::mem::MaybeUninit;
use windows_sys::Win32::Foundation::FALSE;
use windows_sys::Win32::Foundation::FILETIME;
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::System::Threading::GetCurrentThread;
use windows_sys::Win32::System::Threading::GetThreadTimes;
use windows_sys::Win32::System::Threading::OpenThread;
use windows_sys::Win32::System::Threading::THREAD_QUERY_LIMITED_INFORMATION;
pub struct ThreadTimes {
pub create: FILETIME,
pub exit: FILETIME,
pub kernel: FILETIME,
pub user: FILETIME,
}
impl ThreadTimes {
#[allow(dead_code)]
pub fn capture_current() -> Result<Self> {
unsafe {
Self::capture_with_handle(
GetCurrentThread()
)
}
}
pub fn capture_with_thread_id(
ThreadId(tid): ThreadId
) -> Result<Self> {
let handle =
unsafe {
OpenThread(
THREAD_QUERY_LIMITED_INFORMATION,
FALSE as i32,
thread_id
)
}
.upgrade()
.map(|x| unsafe { Handle::new(x) });
let Some(handle) = handle else {
return Err(Error::last_os_error());
};
unsafe {
Self::capture_with_handle(
handle.as_handle()
)
}
}
pub unsafe fn capture_with_handle(handle: HANDLE)
-> Result<Self>
{
let mut create =
MaybeUninit::<FILETIME>::uninit();
let mut exit =
MaybeUninit::<FILETIME>::uninit();
let mut kernel =
MaybeUninit::<FILETIME>::uninit();
let mut user =
MaybeUninit::<FILETIME>::uninit();
let ret =
unsafe {
GetThreadTimes(
handle,
create.as_mut_ptr(),
exit.as_mut_ptr(),
kernel.as_mut_ptr(),
user.as_mut_ptr(),
)
};
if ret == 0 {
return Err(Error::last_os_error());
}
Ok(unsafe {
Self {
create: create.assume_init(),
exit: exit.assume_init(),
kernel: kernel.assume_init(),
user: user.assume_init(),
}
})
}
}