cyberstorm/src/domains/observe/windows.rs

72 lines
2.0 KiB
Rust

use serde::{Deserialize, Serialize};
use crate::util::xml;
#[derive(Debug, Serialize, Deserialize)]
pub struct WindowsEvent {
pub sample: Vec<Sample>,
}
#[derive(Debug)]
pub struct WindowsEventSummary<'a> {
pub event_id: u32,
pub channel: &'a str,
pub provider_name: &'a str,
pub provider_guid: Option<&'a str>,
}
impl WindowsEvent {
pub fn summary(&self) -> Result<WindowsEventSummary<'_>, &'static str> {
let sample = self.sample.get(0).ok_or("no sample")?;
let event_id: u32 = sample
.event_id()
.ok_or("no event id")?
.parse()
.map_err(|_| "event id not u32")?;
let (provider_name, provider_guid) = sample.provider();
Ok(WindowsEventSummary {
event_id,
channel: sample.channel().ok_or("no channel")?,
provider_name: provider_name.ok_or("no provider name")?,
provider_guid,
})
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Sample {
pub xml: xml::DocumentBuf,
pub description: Option<String>,
}
impl Sample {
pub fn provider_name(&self) -> Option<&str> {
self.provider().0
}
pub fn provider(&self) -> (Option<&str>, Option<&str>) {
self.get_event_element("System", "Provider")
.map(|p| (p.attribute("Name"), p.attribute("Guid")))
.unwrap_or_else(|| (None, None))
}
pub fn channel(&self) -> Option<&str> {
self.get_event_element("System", "Channel")
.and_then(|n| n.text())
}
pub fn event_id(&self) -> Option<&str> {
self.get_event_element("System", "EventID")
.and_then(|n| n.text())
}
fn get_event_element(&self, parent: &str, element: &str) -> Option<xml::Node> {
self.xml
.document()
.root_element()
.children()
.find(|c| c.tag_name().name() == parent)
.and_then(|c| c.children().find(|c| c.tag_name().name() == element))
}
}