Skip to content

Commit

Permalink
get_registry_com_ports using utf16 API
Browse files Browse the repository at this point in the history
also removed all the unused optional parameters from `RegQueryInfoKey`
  • Loading branch information
Crzyrndm committed Mar 27, 2023
1 parent 97f03bc commit 397a5f7
Showing 1 changed file with 31 additions and 38 deletions.
69 changes: 31 additions & 38 deletions src/windows/enumerate.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::collections::HashSet;
use std::ffi::CStr;
use std::{mem, ptr};

use regex::Regex;
Expand Down Expand Up @@ -304,76 +303,70 @@ impl PortDevice {
fn get_registry_com_ports() -> HashSet<String> {
let mut ports_list = HashSet::new();

let reg_key = b"HARDWARE\\DEVICEMAP\\SERIALCOMM\0";
let key_ptr = reg_key.as_ptr() as *const i8;
let reg_key = as_utf16("HARDWARE\\DEVICEMAP\\SERIALCOMM");
let mut ports_key = std::ptr::null_mut();

// SAFETY: ffi, all inputs are correct
let open_res =
unsafe { RegOpenKeyExA(HKEY_LOCAL_MACHINE, key_ptr, 0, KEY_READ, &mut ports_key) };
let open_res = unsafe {
RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
reg_key.as_ptr(),
0,
KEY_READ,
&mut ports_key,
)
};
if SUCCEEDED(open_res) {
let mut class_name_buff = [0i8; MAX_PATH];
let mut class_name_size = MAX_PATH as u32;
let mut sub_key_count = 0;
let mut largest_sub_key = 0;
let mut largest_class_string = 0;
let mut num_key_values = 0;
let mut longest_value_name = 0;
let mut longest_value_data = 0;
let mut size_security_desc = 0;
let mut last_write_time = FILETIME {
dwLowDateTime: 0,
dwHighDateTime: 0,
};

// SAFETY: ffi, all inputs are correct
let query_res = unsafe {
RegQueryInfoKeyA(
RegQueryInfoKeyW(
ports_key,
class_name_buff.as_mut_ptr(),
&mut class_name_size,
std::ptr::null_mut(),
&mut sub_key_count,
&mut largest_sub_key,
&mut largest_class_string,
std::ptr::null_mut(),
std::ptr::null_mut(),
std::ptr::null_mut(),
std::ptr::null_mut(),
std::ptr::null_mut(),
&mut num_key_values,
&mut longest_value_name,
&mut longest_value_data,
&mut size_security_desc,
&mut last_write_time,
std::ptr::null_mut(),
std::ptr::null_mut(),
std::ptr::null_mut(),
std::ptr::null_mut(),
)
};
if SUCCEEDED(query_res) {
for idx in 0..num_key_values {
let mut val_name_buff = [0i8; MAX_PATH];
let mut val_name_buff = [0u16; MAX_PATH];
let mut val_name_size = MAX_PATH as u32;
let mut value_type = 0;
// if 100 chars is not enough for COM<number> something is very wrong
let mut val_data = [0; 100];
let mut data_size = val_data.len() as u32;
let mut val_data = [0u16; 100];
let byte_len = 2 * val_data.len() as u32; // len doubled
let mut data_size = byte_len;
// SAFETY: ffi, all inputs are correct
let res = unsafe {
RegEnumValueA(
RegEnumValueW(
ports_key,
idx,
val_name_buff.as_mut_ptr(),
&mut val_name_size,
std::ptr::null_mut(),
&mut value_type,
val_data.as_mut_ptr(),
val_data.as_mut_ptr() as *mut u8,
&mut data_size,
)
};
if FAILED(res) || val_data.len() < data_size as usize {
break;
}
// SAFETY: data_size is checked and pointer is valid
let val_data = CStr::from_bytes_with_nul(unsafe {
std::slice::from_raw_parts(val_data.as_ptr(), data_size as usize)
let val_data = from_utf16_lossy_trimmed(unsafe {
let utf16_len = data_size / 2;
std::slice::from_raw_parts(val_data.as_ptr(), utf16_len as usize)
});

if let Ok(port) = val_data {
ports_list.insert(port.to_string_lossy().into_owned());
}
ports_list.insert(val_data);
}
}
// SAFETY: ffi, all inputs are correct
Expand Down

0 comments on commit 397a5f7

Please sign in to comment.