Skip to content

Commit

Permalink
Optional parse_multi_z_str len; #148.
Browse files Browse the repository at this point in the history
  • Loading branch information
rodrigocfd committed Jan 29, 2025
1 parent a5d193c commit a240b00
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 26 deletions.
22 changes: 12 additions & 10 deletions src/advapi/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,26 +81,28 @@ impl RegistryValue {
match reg_type {
co::REG::NONE => RegistryValue::None,
co::REG::DWORD => RegistryValue::Dword(
u32::from_ne_bytes(unsafe {
*std::mem::transmute::<_, *const [u8; 4]>(buf.as_ptr())
})
u32::from_ne_bytes(
*std::mem::transmute::<_, *const [u8; 4]>(buf.as_ptr()),

This comment has been minimized.

Copy link
@justanotheranonymoususer

justanotheranonymoususer Feb 6, 2025

What if buf's size isn't 4 bytes? I didn't see that you verify it in RegGetValue.

)
),
co::REG::QWORD => RegistryValue::Qword(
u64::from_ne_bytes(unsafe {
*std::mem::transmute::<_, *const [u8; 8]>(buf.as_ptr())
})
u64::from_ne_bytes(
*std::mem::transmute::<_, *const [u8; 8]>(buf.as_ptr()),
)
),
co::REG::SZ => {
let (_, vec16, _) = unsafe { buf.align_to::<u16>() };
let (_, vec16, _) = buf.align_to::<u16>();
RegistryValue::Sz(WString::from_wchars_slice(&vec16).to_string())
},
co::REG::EXPAND_SZ => {

This comment has been minimized.

Copy link
@justanotheranonymoususer

justanotheranonymoususer Feb 6, 2025

Same as co::REG::SZ? Can do co::REG::SZ | co::REG::EXPAND_SZ => {?

let (_, vec16, _) = unsafe { buf.align_to::<u16>() };
let (_, vec16, _) = buf.align_to::<u16>();
RegistryValue::Sz(WString::from_wchars_slice(&vec16).to_string())
},
co::REG::MULTI_SZ => {
let (_, vec16, _) = unsafe { buf.align_to::<u16>() };
RegistryValue::MultiSz(parse_multi_z_str(vec16.as_ptr()))
let (_, vec16, _) = buf.align_to::<u16>();
RegistryValue::MultiSz(
parse_multi_z_str(vec16.as_ptr(), Some(vec16.len())),
)
},
co::REG::BINARY => RegistryValue::Binary(buf),
_ => RegistryValue::None, // other types not implemented yet
Expand Down
12 changes: 8 additions & 4 deletions src/kernel/funcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,9 @@ pub fn GetDiskSpaceInformation(
pub fn GetEnvironmentStrings() -> SysResult<Vec<(String, String)>> {
ptr_to_sysresult(unsafe { ffi::GetEnvironmentStringsW() } as _)
.map(|ptr| {
let vec_entries = unsafe { parse_multi_z_str(ptr as *mut _ as _) };
let vec_entries = unsafe {
parse_multi_z_str(ptr as *mut _ as _, None)
};
unsafe { ffi::FreeEnvironmentStringsW(ptr); }
vec_entries.iter()
.map(|env_str| {
Expand Down Expand Up @@ -478,7 +480,7 @@ pub fn GetLogicalDriveStrings() -> SysResult<Vec<String>> {
unsafe {
bool_to_sysresult(
ffi::GetLogicalDriveStringsW(len, buf.as_mut_ptr()) as _,
).map(|_| parse_multi_z_str(buf.as_ptr()))
).map(|_| parse_multi_z_str(buf.as_ptr(), Some(buf.buf_len())))
}
}

Expand Down Expand Up @@ -564,7 +566,7 @@ pub fn GetPrivateProfileSection(
return Err(co::ERROR::FILE_NOT_FOUND);
} else if (returned_chars as usize) < buf_sz { // to break, must have at least 1 char gap
return Ok(
unsafe { parse_multi_z_str(buf.as_ptr()) }
unsafe { parse_multi_z_str(buf.as_ptr(), Some(buf.buf_len())) }
.iter()
.map(|line| match line.split_once('=') {
Some((key, val)) => (key.to_owned(), val.to_owned()),
Expand Down Expand Up @@ -622,7 +624,9 @@ pub fn GetPrivateProfileSectionNames(
if GetLastError() == co::ERROR::FILE_NOT_FOUND {
return Err(co::ERROR::FILE_NOT_FOUND);
} else if (returned_chars as usize) < buf_sz { // to break, must have at least 1 char gap
return Ok(unsafe { parse_multi_z_str(buf.as_ptr()) });
return Ok(
unsafe { parse_multi_z_str(buf.as_ptr(), Some(buf.buf_len())) },
);
}

buf_sz *= 2; // double the buffer size to try again
Expand Down
31 changes: 21 additions & 10 deletions src/kernel/privs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,29 +98,40 @@ pub(crate) fn str_to_iso88591(s: &str) -> Vec<u8> {
.collect()
}

/// Parses a null-delimited multi-string, which ends with two terminating nulls.
/// Parses a null-delimited multi-string, ending with two terminating nulls.
///
/// # Safety
///
/// Make sure the string has two terminating nulls.
/// If `len` is not informed, make sure the string has two terminating nulls.
#[must_use]
pub(crate) unsafe fn parse_multi_z_str(src: *const u16) -> Vec<String> {
pub(crate) unsafe fn parse_multi_z_str(
src: *const u16,
len: Option<usize>,
) -> Vec<String>
{
let given_len = len.unwrap_or(usize::MAX);
let mut src = src;
let mut strings = Vec::<String>::new();
let mut i = 0;
let mut ch = 0; // relative index of char in current string
let mut tot_ch = 0; // absolute index of char in original src

loop {
if unsafe { *src.add(i) } == 0 {
let slice = unsafe { std::slice::from_raw_parts(src, i) };
if *src.add(ch) == 0 || tot_ch == given_len {
let slice = std::slice::from_raw_parts(src, ch);
if slice.is_empty() {
break;
break; // empty string means two consecutive nulls
}
strings.push(WString::from_wchars_slice(slice).to_string());
src = unsafe { src.add(i + 1) };
i = 0;
src = src.add(ch + 1);
ch = 0;
} else {
i += 1;
ch += 1;
}

if len.is_some() && tot_ch == given_len {
break;
}
tot_ch += 1;
}
strings
}
Expand Down
4 changes: 2 additions & 2 deletions src/shell/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ impl<'a, 'b, 'c> SHFILEOPSTRUCT<'a, 'b, 'c> {
pub fn pFrom(&self) -> Option<Vec<String>> {
unsafe {
self.pFrom.as_mut()
.map(|p| parse_multi_z_str(p))
.map(|p| parse_multi_z_str(p, None))
}
}

Expand All @@ -116,7 +116,7 @@ impl<'a, 'b, 'c> SHFILEOPSTRUCT<'a, 'b, 'c> {
pub fn pTo(&self) -> Option<Vec<String>> {
unsafe {
self.pTo.as_mut()
.map(|p| parse_multi_z_str(p))
.map(|p| parse_multi_z_str(p, None))
}
}

Expand Down

0 comments on commit a240b00

Please # to comment.