winbrew_windows\registry/
uninstall.rs

1use winreg::{
2    RegKey,
3    enums::{HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE},
4};
5
6pub(super) const UNINSTALL: &str = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
7pub(super) const WOW6432_UNINSTALL: &str =
8    "SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
9
10/// Registry hive that can contain uninstall data.
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12enum Hive {
13    /// `HKEY_LOCAL_MACHINE`.
14    LocalMachine,
15    /// `HKEY_CURRENT_USER`.
16    CurrentUser,
17}
18
19impl Hive {
20    /// Open the registry root associated with this hive.
21    pub fn open(self) -> RegKey {
22        let hkey = match self {
23            Self::LocalMachine => HKEY_LOCAL_MACHINE,
24            Self::CurrentUser => HKEY_CURRENT_USER,
25        };
26        RegKey::predef(hkey)
27    }
28}
29
30/// Snapshot of one uninstall registry location.
31#[derive(Debug)]
32pub(super) struct UninstallRoot {
33    key: RegKey,
34}
35
36impl UninstallRoot {
37    /// Open registry key handle for the uninstall root.
38    pub(super) fn key(&self) -> &RegKey {
39        &self.key
40    }
41
42    fn new(key: RegKey) -> Self {
43        Self { key }
44    }
45}
46
47/// Iterate over the uninstall roots that exist on the current machine.
48///
49/// The iterator includes the standard machine, WOW6432Node, and user uninstall
50/// locations when they are present. Missing roots are skipped, so callers can
51/// iterate lazily without allocating a collection first.
52pub(super) fn uninstall_roots() -> impl Iterator<Item = UninstallRoot> {
53    [
54        (Hive::LocalMachine, UNINSTALL),
55        (Hive::LocalMachine, WOW6432_UNINSTALL),
56        (Hive::CurrentUser, UNINSTALL),
57    ]
58    .into_iter()
59    .filter_map(|(hive, key_path)| {
60        hive.open()
61            .open_subkey(key_path)
62            .ok()
63            .map(UninstallRoot::new)
64    })
65}