// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms.
/// Must never be `HKEY_PERFORMANCE_DATA`. pub(crate) struct RegistryKey(Repr);
#[allow(clippy::upper_case_acronyms)] type DWORD = u32;
struct OwnedKey(HKEY);
/// Note: must not encode `HKEY_PERFORMANCE_DATA` or one of its subkeys. enum Repr { /// `HKEY_LOCAL_MACHINE`.
LocalMachine, /// A subkey of `HKEY_LOCAL_MACHINE`.
Owned(OwnedKey),
}
/// Open a sub-key of `self`. pubfn open(&self, key: &OsStr) -> io::Result<RegistryKey> { let key = key.encode_wide().chain(Some(0)).collect::<Vec<_>>(); letmut ret = null_mut(); let err = unsafe {
RegOpenKeyExW( self.raw(),
key.as_ptr(), 0,
KEY_READ | KEY_WOW64_32KEY,
&mut ret,
)
}; if err == ERROR_SUCCESS {
Ok(RegistryKey(Repr::Owned(OwnedKey(ret))))
} else {
Err(io::Error::from_raw_os_error(err as i32))
}
}
pubfn iter(&self) -> Iter {
Iter {
idx: 0..,
key: self,
}
}
pubfn query_str(&self, name: &str) -> io::Result<OsString> { let name: &OsStr = name.as_ref(); let name = name.encode_wide().chain(Some(0)).collect::<Vec<_>>(); letmut len = 0; letmut kind = 0; unsafe { let err = RegQueryValueExW( self.raw(),
name.as_ptr(),
null_mut(),
&mut kind,
null_mut(),
&mut len,
); if err != ERROR_SUCCESS { return Err(io::Error::from_raw_os_error(err as i32));
} if kind != REG_SZ { return Err(io::Error::new(
io::ErrorKind::Other, "registry key wasn't a string",
));
}
// The length here is the length in bytes, but we're using wide // characters so we need to be sure to halve it for the length // passed in.
assert!(len % 2 == 0, "impossible wide string size: {} bytes", len); let vlen = len as usize / 2; // Defensively initialized, see comment about // `HKEY_PERFORMANCE_DATA` below. letmut v = vec![0u16; vlen]; let err = RegQueryValueExW( self.raw(),
name.as_ptr(),
null_mut(),
null_mut(),
v.as_mut_ptr() as *mut _,
&mut len,
); // We don't check for `ERROR_MORE_DATA` (which would if the value // grew between the first and second call to `RegQueryValueExW`), // both because it's extremely unlikely, and this is a bit more // defensive more defensive against weird types of registry keys. if err != ERROR_SUCCESS { return Err(io::Error::from_raw_os_error(err as i32));
} // The length is allowed to change, but should still be even, as // well as smaller.
assert!(len % 2 == 0, "impossible wide string size: {} bytes", len); // If the length grew but returned a success code, it *probably* // indicates we're `HKEY_PERFORMANCE_DATA` or a subkey(?). We // consider this UB, since those keys write "undefined" or // "unpredictable" values to len, and need to use a completely // different loop structure. This should be impossible (and enforce // it in the API to the best of our ability), but to mitigate the // damage we do some smoke-checks on the len, and ensure `v` has // been fully initialized (rather than trusting the result of // `RegQueryValueExW`). let actual_len = len as usize / 2;
assert!(actual_len <= v.len());
v.truncate(actual_len); // Some registry keys may have a terminating nul character, but // we're not interested in that, so chop it off if it's there. if !v.is_empty() && v[v.len() - 1] == 0 {
v.pop();
}
Ok(OsString::from_wide(&v))
}
}
}
impl Drop for OwnedKey { fn drop(&mutself) { unsafe {
RegCloseKey(self.0);
}
}
}
impl<'a> Iterator for Iter<'a> { type Item = io::Result<OsString>;
fn next(&mutself) -> Option<io::Result<OsString>> { self.idx.next().and_then(|i| unsafe { letmut v = Vec::with_capacity(256); letmut len = v.capacity() as DWORD; let ret = RegEnumKeyExW( self.key.raw(),
i,
v.as_mut_ptr(),
&mut len,
null_mut(),
null_mut(),
null_mut(),
null_mut(),
); if ret == ERROR_NO_MORE_ITEMS {
None
} elseif ret != ERROR_SUCCESS {
Some(Err(io::Error::from_raw_os_error(ret as i32)))
} else {
v.set_len(len as usize);
Some(Ok(OsString::from_wide(&v)))
}
})
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-18)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.