use forensic_rs::{
info,
traits::registry::{auto_close_key, RegHiveKey, RegistryReader},
utils::time::Filetime,
};
use super::{read_value_string_or_empty, read_value_u32_or_empty};
#[derive(Clone, Debug, Default)]
pub struct InventoryApplication {
pub program_id: String,
pub program_instance_id: String,
pub name: String,
pub version: String,
pub publisher: String,
pub language: u32,
pub source: String,
pub r#type: String,
pub store_app_type: String,
pub msi_package_code: String,
pub msi_product_code: String,
pub hidden_arp: u32,
pub inbox_modern_app: u32,
pub os_version_at_install_time: String,
pub install_date: String,
pub package_full_name: String,
pub manifest_path: String,
pub bundle_manifest_path: String,
pub root_dir_path: String,
pub uninstall_string: String,
pub registry_key_path: String,
pub timestamp: Filetime,
}
pub struct InventoryApplicationIter<'a, R: RegistryReader> {
pub(crate) pos: u32,
pub(crate) key: RegHiveKey,
pub(crate) reader: &'a R,
}
impl<'a, R: RegistryReader> Iterator for InventoryApplicationIter<'a, R> {
type Item = InventoryApplication;
fn next(&mut self) -> Option<Self::Item> {
if self.key == RegHiveKey::Hkey(0) {
return None;
}
let pos = self.pos;
self.pos += 1;
let next_subkey = self.reader.key_at(self.key, pos).ok()?;
let key = self.reader.open_key(self.key, &next_subkey).ok()?;
match auto_close_key(self.reader, key, || {
let program_id: String = read_value_string_or_empty(self.reader, key, "ProgramId");
let program_instance_id: String =
read_value_string_or_empty(self.reader, key, "ProgramInstanceId");
let name: String = read_value_string_or_empty(self.reader, key, "Name");
let version: String = read_value_string_or_empty(self.reader, key, "Version");
let publisher: String = read_value_string_or_empty(self.reader, key, "Publisher");
let language: u32 = read_value_u32_or_empty(self.reader, key, "Language");
let source: String = read_value_string_or_empty(self.reader, key, "Source");
let r#type: String = read_value_string_or_empty(self.reader, key, "Type");
let store_app_type: String =
read_value_string_or_empty(self.reader, key, "StoreAppType");
let msi_package_code: String =
read_value_string_or_empty(self.reader, key, "MsiPackageCode");
let msi_product_code: String =
read_value_string_or_empty(self.reader, key, "MsiProductCode");
let hidden_arp = read_value_u32_or_empty(self.reader, key, "HiddenArp");
let inbox_modern_app = read_value_u32_or_empty(self.reader, key, "InboxModernApp");
let os_version_at_install_time: String =
read_value_string_or_empty(self.reader, key, "OSVersionAtInstallTime");
let install_date: String = read_value_string_or_empty(self.reader, key, "InstallDate");
let package_full_name: String =
read_value_string_or_empty(self.reader, key, "PackageFullName");
let manifest_path: String =
read_value_string_or_empty(self.reader, key, "ManifestPath");
let bundle_manifest_path =
read_value_string_or_empty(self.reader, key, "BundleManifestPath");
let root_dir_path = read_value_string_or_empty(self.reader, key, "RootDirPath");
let uninstall_string = read_value_string_or_empty(self.reader, key, "UninstallString");
let registry_key_path = read_value_string_or_empty(self.reader, key, "RegistryKeyPath");
let key_info = self.reader.key_info(key)?;
Ok(InventoryApplication {
program_id,
program_instance_id,
name,
version,
publisher,
language,
source,
r#type,
store_app_type,
msi_package_code,
msi_product_code,
hidden_arp,
inbox_modern_app,
os_version_at_install_time,
install_date,
package_full_name,
manifest_path,
bundle_manifest_path,
root_dir_path,
uninstall_string,
registry_key_path,
timestamp: key_info.last_write_time,
})
}) {
Ok(v) => Some(v),
Err(e) => {
info!("Error getting AmCache File {}", e);
None
}
}
}
}
impl<'a, R: RegistryReader> Drop for InventoryApplicationIter<'a, R> {
fn drop(&mut self) {
self.reader.close_key(self.key);
self.key = RegHiveKey::Hkey(0);
}
}