use crate::{dbgeng::WinResult, extsfns::*, *};
use windows_core::PSTR;
impl_debug_interface!(
DebugFailureAnalysis,
DebugFailureAnalysisRef,
IDebugFailureAnalysis3
);
macro_rules! get_entry {
($($t:tt)*) => {{
let entry = $($t)*;
if entry.is_null() { return None; }
FaEntry::from(*entry)
}};
}
impl DebugFailureAnalysis {
pub fn get_failure_class(&self) -> DebugFailureClass {
unsafe { self.0.GetFailureClass().try_into().unwrap() }
}
pub fn get_failure_type(&self) -> DebugFailureType {
unsafe { self.0.GetFailureType().into() }
}
pub fn get_failure_code(&self) -> u32 { unsafe { self.0.GetFailureCode() } }
pub fn get(&self, tag: FaTag) -> Option<FaEntry> {
unsafe {
let entry = self.0.Get(tag.into());
(!entry.is_null()).then_some(FaEntry::from(*entry))
}
}
pub fn get_next(
&self,
entry: Option<&FaEntry>,
tag: FaTag,
tag_mask: FaTag,
) -> Option<FaEntry> {
unsafe {
let entry = self.0.GetNext(
entry.map_or(std::ptr::null_mut(), |x| &x.0 as *const _),
tag.into(),
tag_mask.into(),
);
(!entry.is_null()).then_some(FaEntry::from(*entry))
}
}
pub fn get_string(
&self,
tag: FaTag,
max_size: u32,
) -> Option<(FaEntry, ACPString)> {
let mut buf = Vec::with_capacity(max_size as usize);
unsafe {
let s = vcall!(
self,
GetString,
tag.into(),
PSTR(buf.as_mut_ptr()),
max_size
);
let entry = get_entry!(s);
let ret = ACPString::clone_from_raw(buf.as_ptr());
Some((entry, ret))
}
}
pub fn get_buffer(
&self,
tag: FaTag,
size: u32,
) -> Option<(FaEntry, Vec<u8>)> {
let mut buf = Vec::with_capacity(size as usize);
unsafe {
let entry = get_entry!(self.0.GetBuffer(
tag.into(),
buf.as_mut_ptr() as *mut _,
size
));
buf.set_len(size as usize);
Some((entry, buf))
}
}
pub fn get_ulong(&self, tag: FaTag) -> Option<(FaEntry, u32)> {
let mut value = 0;
unsafe {
let entry = get_entry!(self.0.GetUlong(tag.into(), &mut value));
Some((entry, value))
}
}
pub fn get_ulong64(&self, tag: FaTag) -> Option<(FaEntry, u64)> {
let mut value = 0;
unsafe {
let entry = get_entry!(self.0.GetUlong64(tag.into(), &mut value));
Some((entry, value))
}
}
pub fn next_entry(&self, entry: Option<&FaEntry>) -> Option<FaEntry> {
unsafe {
let entry = self.0.NextEntry(entry.map(|x| &x.0 as *const _));
(!entry.is_null()).then_some(FaEntry::from(*entry))
}
}
}
impl DebugFailureAnalysis {
pub fn set_string(
&self,
tag: FaTag,
str: impl AsRef<ACPStr>,
) -> Option<FaEntry> {
unsafe {
let entry = get_entry!(self.0.SetString(tag.into(), pca!(str)));
Some(entry)
}
}
pub fn set_extension_command(
&self,
tag: FaTag,
extension: impl AsRef<ACPStr>,
) -> Option<FaEntry> {
unsafe {
let entry = get_entry!(
self.0.SetExtensionCommand(tag.into(), pca!(extension))
);
Some(entry)
}
}
pub fn set_ulong(&self, tag: FaTag, value: u32) -> Option<FaEntry> {
unsafe {
let entry = get_entry!(self.0.SetUlong(tag.into(), value));
Some(entry)
}
}
pub fn set_ulong64(&self, tag: FaTag, value: u64) -> Option<FaEntry> {
unsafe {
let entry = get_entry!(self.0.SetUlong64(tag.into(), value));
Some(entry)
}
}
pub fn set_buffer(
&self,
tag: FaTag,
fa_entry_type: FaEntryType,
buf: &[u8],
) -> Option<FaEntry> {
unsafe {
let entry = get_entry!(self.0.SetBuffer(
tag.into(),
fa_entry_type.into(),
buf.as_ptr() as *const _,
buf.len() as u32
));
Some(entry)
}
}
pub fn add_string(
&self,
tag: FaTag,
str: impl AsRef<ACPStr>,
) -> Option<FaEntry> {
unsafe {
let entry = get_entry!(self.0.AddString(tag.into(), pca!(str)));
Some(entry)
}
}
pub fn add_extension_command(
&self,
tag: FaTag,
extension: impl AsRef<ACPStr>,
) -> Option<FaEntry> {
unsafe {
let entry = get_entry!(
self.0.AddExtensionCommand(tag.into(), pca!(extension))
);
Some(entry)
}
}
pub fn add_ulong(&self, tag: FaTag, value: u32) -> Option<FaEntry> {
unsafe {
let entry = get_entry!(self.0.AddUlong(tag.into(), value));
Some(entry)
}
}
pub fn add_ulong64(&self, tag: FaTag, value: u64) -> Option<FaEntry> {
unsafe {
let entry = get_entry!(self.0.AddUlong64(tag.into(), value));
Some(entry)
}
}
pub fn add_buffer(
&self,
tag: FaTag,
fa_entry_type: FaEntryType,
buf: &[u8],
) -> Option<FaEntry> {
unsafe {
let entry = get_entry!(self.0.AddBuffer(
tag.into(),
fa_entry_type.into(),
buf.as_ptr() as *const _,
buf.len() as u32,
));
Some(entry)
}
}
pub fn get_debug_fa_tag_control(&self) -> WinResult<DebugFaEntryTags<'_>> {
unsafe {
Ok(DebugFaEntryTags::_from_base(
self.0.GetDebugFATagControl()?,
self,
))
}
}
}
impl DebugFailureAnalysis {
pub fn attribute_get(&self, index: u32) -> WinResult<Variant> {
unsafe { Ok(self.0.AttributeGet(index)?.into()) }
}
pub fn attribute_set(&self, index: u32, value: Variant) -> WinResult<()> {
unsafe { self.0.AttributeSet(index, &value.0) }
}
}