use crate::utils::{HKEY_LM_REG_KEY, get_winreg_arch_flags};
use std::fs::copy;
use std::path::PathBuf;
use std::sync::Once;
use tracing::{debug, warn};
use winreg::enums;
pub fn restore_protocol_dll() {
static ONCE: Once = Once::new();
ONCE.call_once(|| {
try_restore_protocol_dll("SOFTWARE\\Softing\\D-PDU API", "InstallLocation");
try_restore_protocol_dll("SOFTWARE\\Softing\\D-PDU API_Module", "PDUAPIInstallDir");
});
}
fn try_restore_protocol_dll(winreg_path: &str, install_dir_key: &str) {
let Ok(path) = HKEY_LM_REG_KEY
.open_subkey_with_flags(winreg_path, get_winreg_arch_flags())
.inspect_err(|err| {
debug!(
path = winreg_path,
"Registry path cannot be opened: {err:?}"
)
})
else {
return;
};
for version_path in path.enum_keys().flatten() {
let full_winreg_path = format!("{winreg_path}\\{version_path}\\Installer");
let Ok(installer) = path
.open_subkey_with_flags(format!("{version_path}\\Installer"), enums::KEY_READ)
.inspect_err(|err| {
debug!(
path = full_winreg_path,
"Registry path cannot be opened: {err:?}"
)
})
else {
continue;
};
let Ok(install_directory) = installer
.get_value::<String, _>(install_dir_key)
.inspect_err(|err| {
debug!(
path = full_winreg_path,
key = install_dir_key,
"Registry value cannot be read: {err:?}"
)
})
.map(PathBuf::from)
else {
continue;
};
let vecom_directory = install_directory.join("VeCom");
if !vecom_directory.is_dir() {
continue;
}
let protocol_dll_path = vecom_directory.join("protocol.dll");
if protocol_dll_path.exists() {
continue;
}
let vcifman_pdu_dll_path = vecom_directory.join("vcifman_pdu.dll");
if !vcifman_pdu_dll_path.is_file() {
continue;
}
if let Err(err) = copy(&vcifman_pdu_dll_path, &protocol_dll_path) {
warn!(
edic_version = version_path,
source = ?vcifman_pdu_dll_path,
dest = ?protocol_dll_path,
"Failed to create protocol.dll from vcifman_pdu.dll: {err}"
);
}
}
}