use regf::writer::HiveBuilder;
use regf::structures::DataType;
use regf::hive::RegistryHive;
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Creating a SOFTWARE-like Registry Hive ===\n");
let mut builder = HiveBuilder::new();
let root = builder.root_offset();
let classes = builder.add_key(root, "Classes")?;
let microsoft = builder.add_key(root, "Microsoft")?;
let policies = builder.add_key(root, "Policies")?;
let wow6432node = builder.add_key(root, "Wow6432Node")?;
let txt_ext = builder.add_key(classes, ".txt")?;
add_string_value(&mut builder, txt_ext, "", "txtfile")?;
add_string_value(&mut builder, txt_ext, "Content Type", "text/plain")?;
add_string_value(&mut builder, txt_ext, "PerceivedType", "text")?;
let txtfile = builder.add_key(classes, "txtfile")?;
add_string_value(&mut builder, txtfile, "", "Text Document")?;
let shell = builder.add_key(txtfile, "shell")?;
let open = builder.add_key(shell, "open")?;
let command = builder.add_key(open, "command")?;
add_string_value(&mut builder, command, "", "notepad.exe %1")?;
let windows = builder.add_key(microsoft, "Windows")?;
let current_version = builder.add_key(windows, "CurrentVersion")?;
add_string_value(&mut builder, current_version, "ProductName", "Windows 11 Pro")?;
add_string_value(&mut builder, current_version, "EditionID", "Professional")?;
add_string_value(&mut builder, current_version, "DisplayVersion", "23H2")?;
builder.add_value(
current_version,
"CurrentMajorVersionNumber",
DataType::Dword,
&11u32.to_le_bytes(),
)?;
builder.add_value(
current_version,
"CurrentMinorVersionNumber",
DataType::Dword,
&0u32.to_le_bytes(),
)?;
let expand_str = encode_utf16("%SystemRoot%\\System32");
builder.add_value(current_version, "CommonFilesDir", DataType::ExpandString, &expand_str)?;
let program_files = builder.add_key(current_version, "ProgramFilesDir")?;
add_string_value(&mut builder, program_files, "", "C:\\Program Files")?;
let app_paths = builder.add_key(current_version, "App Paths")?;
let notepad_path = builder.add_key(app_paths, "notepad.exe")?;
add_string_value(&mut builder, notepad_path, "", "C:\\Windows\\System32\\notepad.exe")?;
add_string_value(&mut builder, notepad_path, "Path", "C:\\Windows\\System32")?;
let calc_path = builder.add_key(app_paths, "calc.exe")?;
add_string_value(&mut builder, calc_path, "", "C:\\Windows\\System32\\calc.exe")?;
let uninstall = builder.add_key(current_version, "Uninstall")?;
let app1 = builder.add_key(uninstall, "{12345678-1234-1234-1234-123456789ABC}")?;
add_string_value(&mut builder, app1, "DisplayName", "Example Application")?;
add_string_value(&mut builder, app1, "DisplayVersion", "1.0.0")?;
add_string_value(&mut builder, app1, "Publisher", "Example Corp")?;
add_string_value(&mut builder, app1, "UninstallString", "C:\\Program Files\\ExampleApp\\uninstall.exe")?;
builder.add_value(app1, "EstimatedSize", DataType::Dword, &102400u32.to_le_bytes())?;
builder.add_value(app1, "NoModify", DataType::Dword, &1u32.to_le_bytes())?;
builder.add_value(app1, "NoRepair", DataType::Dword, &1u32.to_le_bytes())?;
let ms_policies = builder.add_key(policies, "Microsoft")?;
let windows_pol = builder.add_key(ms_policies, "Windows")?;
let explorer_pol = builder.add_key(windows_pol, "Explorer")?;
builder.add_value(explorer_pol, "NoDesktop", DataType::Dword, &0u32.to_le_bytes())?;
let wow_microsoft = builder.add_key(wow6432node, "Microsoft")?;
add_string_value(&mut builder, wow_microsoft, "Description", "32-bit application settings")?;
let output_path = std::env::temp_dir().join("software_example.dat");
println!("Writing hive to: {:?}", output_path);
builder.write_to_file(&output_path)?;
println!("\n=== Verifying Created Hive ===\n");
let hive = RegistryHive::from_file(&output_path)?;
println!("All keys in hive:");
for path in hive.enumerate_all_keys()? {
println!(" {}", path);
}
println!("\n--- CurrentVersion Values ---");
let cv = hive.open_key("Microsoft\\Windows\\CurrentVersion")?;
for value in cv.values()? {
let name = if value.is_default() { "(Default)" } else { &value.name() };
println!(" {} = {:?}", name, value.data()?);
}
println!("\n--- App Paths ---");
let apps = hive.open_key("Microsoft\\Windows\\CurrentVersion\\App Paths")?;
for subkey in apps.subkeys()? {
println!(" {}", subkey.name());
for value in subkey.values()? {
let name = if value.is_default() { "(Default)" } else { &value.name() };
println!(" {} = {:?}", name, value.data()?);
}
}
std::fs::remove_file(&output_path)?;
println!("\nDone!");
Ok(())
}
fn add_string_value(
builder: &mut HiveBuilder,
key_offset: u32,
name: &str,
value: &str,
) -> Result<u32, Box<dyn std::error::Error>> {
let data = encode_utf16(value);
Ok(builder.add_value(key_offset, name, DataType::String, &data)?)
}
fn encode_utf16(s: &str) -> Vec<u8> {
let mut bytes: Vec<u8> = s
.encode_utf16()
.flat_map(|c| c.to_le_bytes())
.collect();
bytes.extend_from_slice(&[0, 0]); bytes
}