ramensoftware/windhawk · error · SettingsError
RegSetValueEx
Error message
RegSetValueEx
What it means
The RegSetValueExW call in set_raw failed with an OS error other than ERROR_SUCCESS; the write to the registry value did not happen. The error message carries the Win32 function name plus the underlying OS error code.
Solutions
- Check the wrapped OS code — ERROR_ACCESS_DENIED means elevate privileges or choose a writable location (e.g. HKCU instead of HKLM).
- Re-open the key with KEY_SET_VALUE if the handle may have gone stale.
- Verify the key still exists and was not removed concurrently; recreate if needed.
- Reduce value size / use an allowed type if the API rejected type or quota.
Example fix
// before
settings.set_string("key", "v")?; // fails under HKLM without admin
// after
// open settings under HKCU (writable) or handle elevation
match settings.set_string("key", "v") {
Err(e) if e.os_code() == ERROR_ACCESS_DENIED => eprintln!("run elevated or use HKCU"),
r => r?,
} Defensive patterns
Strategy: try-catch
Validate before calling
// ensure the key exists and the process has write access (e.g. prefer HKCU over HKLM)
Try / catch
match settings.set_string("k", "v") {
Err(e) if e.message().starts_with("RegSetValueEx") => {
if e.message().contains("access is denied") { /* elevate or switch to HKCU */ }
}
r => r?,
} Prevention
- Write to user-writable hives (HKCU) unless elevation is guaranteed.
- Handle ERROR_ACCESS_DENIED explicitly with a user-facing hint.
- Avoid concurrent deletion of keys being written.
- Check the wrapped OS code in the message for the precise cause.
When it happens
Trigger: Writing a value when access is denied (ERROR_ACCESS_DENIED), the key handle is invalid, the value type/length combination is rejected, registry quota is exceeded, or the key was deleted concurrently.
Common situations: Writing to HKLM without admin rights (UAC); anti-malware or Group Policy locking mod keys; key deleted by another process mid-run; quota limits on very large values.
Related errors
- value name contains a NUL
- RegQueryValueEx (size)
- RegQueryValueEx (data)
- set on a read-only/absent key
- value is too large for the registry
AI-assisted analysis of ramensoftware/windhawk@61d99ed8e1 (2026-09-12).
Data as JSON: /api/errors/8d953acb3f695d79.
Report an issue: GitHub.
Appendix: source
Thrown at src/windhawk-core/windows/src/registry.rs:466
}
fn set_raw(&self, name: &str, value_type: u32, data: &[u8]) -> Result<(), SettingsError> {
self.check_name("set", name)?;
let Some(hkey) = self.hkey() else {
return Err(self.err("set", 0, "set on a read-only/absent key"));
};
let name_w = to_wide(name);
// A length the API's u32 cannot hold has no honest value to pass, and a
// clamped one would hand the call a length the buffer does not have.
let len = u32::try_from(data.len())
.map_err(|_| self.err("set", 0, "value is too large for the registry"))?;
// SAFETY: name_w is NUL-terminated; data/len describe a valid buffer.
let rc =
unsafe { RegSetValueExW(hkey, name_w.as_ptr(), 0, value_type, data.as_ptr(), len) };
if rc == ERROR_SUCCESS {
Ok(())
} else {
Err(self.err("set", rc, "RegSetValueEx"))
}
}
}
/// Decode a `REG_SZ` byte buffer (UTF-16LE, possibly NUL-terminated).
fn decode_sz(bytes: &[u8]) -> String {
let units: Vec<u16> = bytes
.chunks_exact(2)
.map(|c| u16::from_le_bytes([c[0], c[1]]))
.collect();
from_wide_nul(&units)
}
fn decode_dword(bytes: &[u8]) -> Option<i32> {
if bytes.len() == 4 {
Some(i32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
} else {
NoneView on GitHub (pinned to 61d99ed8e1)