use crate::{dbgeng::*, object::traits::context::Context};
use bitflags::bitflags;
use std::mem::MaybeUninit;
bitflags! {
#[derive(Debug, Copy, Clone,Eq, PartialEq)]
pub struct DebugFindSourceFlags: u32 {
const Default = DEBUG_FIND_SOURCE_DEFAULT;
const FullPath = DEBUG_FIND_SOURCE_FULL_PATH;
const BestMatch = DEBUG_FIND_SOURCE_BEST_MATCH;
const NoSrcsrv = DEBUG_FIND_SOURCE_NO_SRCSRV;
const TokenLookup = DEBUG_FIND_SOURCE_TOKEN_LOOKUP;
const WithChecksum = DEBUG_FIND_SOURCE_WITH_CHECKSUM;
const WithChecksumStrict = DEBUG_FIND_SOURCE_WITH_CHECKSUM_STRICT;
}
}
enum_flags! {
pub enum DebugSrcFileSymbolOptions: u32 {
Token = DEBUG_SRCFILE_SYMBOL_TOKEN,
TokenSourceCommandWide = DEBUG_SRCFILE_SYMBOL_TOKEN_SOURCE_COMMAND_WIDE,
ChecksumInfo = DEBUG_SRCFILE_SYMBOL_CHECKSUMINFO,
}
}
pub enum DebugSrcFileSymbolData {
Token(Vec<u8>),
TokenSourceCommandWide(WString),
}
impl_debug_interface!(
DebugAdvanced,
DebugAdvancedRef,
IDebugAdvanced4,
IDebugAdvanced
);
impl DebugAdvanced {
pub unsafe fn get_thread_context<C: Context>(&self) -> WinResult<C> {
unsafe {
let mut context = MaybeUninit::<C>::zeroed();
self.0.GetThreadContext(
context.as_mut_ptr() as *mut _,
size_of::<C>() as u32,
)?;
Ok(context.assume_init())
}
}
pub unsafe fn set_thread_context<C: Context>(
&self,
context: &C,
) -> WinResult<()> {
unsafe {
self.0.SetThreadContext(
context as *const _ as *const _,
size_of::<C>() as u32,
)
}
}
}
impl DebugAdvanced {
unsafe fn _request(&self, request: u32) -> WinResult<bool> {
unsafe {
hr!(vcall!(
self,
Request,
request,
std::ptr::null(),
0,
std::ptr::null_mut(),
0,
std::ptr::null_mut()
))
}
}
unsafe fn _request_i<T: Sized>(
&self,
request: u32,
in_buffer: &T,
) -> WinResult<()> {
unsafe {
vcall!(
self,
Request,
request,
in_buffer as *const T as *const c_void,
size_of::<T>() as u32,
std::ptr::null_mut(),
0,
std::ptr::null_mut()
)
.ok()
}
}
unsafe fn _request_o<T: Sized>(&self, request: u32) -> WinResult<T> {
let mut out_size = 0;
let mut ret = MaybeUninit::<T>::uninit();
let obj_size = size_of::<T>() as u32;
unsafe {
vcall!(
self,
Request,
request,
std::ptr::null(),
0,
ret.as_mut_ptr() as *mut c_void,
obj_size,
&mut out_size,
)
.ok()?;
assert_eq!(obj_size, out_size);
Ok(ret.assume_init())
}
}
pub fn _request_source_path_has_source_server(&self) -> WinResult<bool> {
unsafe { self._request(DEBUG_REQUEST_SOURCE_PATH_HAS_SOURCE_SERVER) }
}
pub fn _request_get_additional_create_options(
&self,
) -> WinResult<DebugCreateProcessOptions> {
unsafe { self._request_o(DEBUG_REQUEST_GET_ADDITIONAL_CREATE_OPTIONS) }
}
pub fn _request_set_additional_create_options(
&self,
options: &DebugCreateProcessOptions,
) -> WinResult<()> {
unsafe {
self._request_i(
DEBUG_REQUEST_SET_ADDITIONAL_CREATE_OPTIONS,
options,
)
}
}
pub fn _request_target_can_detach(&self) -> WinResult<bool> {
unsafe { self._request(DEBUG_REQUEST_TARGET_CAN_DETACH) }
}
pub fn _request_get_captured_event_code_offset(
&self,
) -> WinResult<DebuggeeOffset> {
unsafe { self._request_o(DEBUG_REQUEST_GET_CAPTURED_EVENT_CODE_OFFSET) }
}
pub fn _request_read_captured_event_code_stream(
&self,
) -> WinResult<Vec<u8>> {
let mut out_size = 0;
let mut ret: Vec<u8> = Vec::with_capacity(64);
unsafe {
vcall!(
self,
Request,
DEBUG_REQUEST_READ_CAPTURED_EVENT_CODE_STREAM,
std::ptr::null(),
0,
ret.as_mut_ptr() as *mut c_void,
64,
&mut out_size,
)
.ok()?;
assert!(
out_size <= 64,
"DbgEng returned an output size larger than the supplied \
buffer"
);
ret.set_len(out_size as usize);
Ok(ret)
}
}
pub fn _request_live_user_non_invasive(&self) -> WinResult<bool> {
unsafe { self._request(DEBUG_LIVE_USER_NON_INVASIVE) }
}
pub fn _request_resume_thread(&self, tid: ThreadId) -> WinResult<()> {
unsafe { self._request_i(DEBUG_REQUEST_RESUME_THREAD, &tid) }
}
}
impl DebugAdvanced {
}
impl DebugAdvanced {
}