diff --git a/src/windows.rs b/src/windows.rs index e5a626c0..be4cb60f 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -21,6 +21,14 @@ extern "system" { ) -> u32; } +// Forbidden when targetting UWP +#[cfg(not(target_vendor = "uwp"))] +#[link(name = "advapi32")] +extern "system" { + #[link_name = "SystemFunction036"] + fn RtlGenRandom(RandomBuffer: *mut c_void, RandomBufferLength: u32) -> u8; +} + pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { // Prevent overflow of u32 for chunk in dest.chunks_mut(u32::max_value() as usize) { @@ -35,6 +43,15 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { }; // NTSTATUS codes use the two highest bits for severity status. if ret >> 30 == 0b11 { + // Failed. Try RtlGenRandom as a fallback. + #[cfg(not(target_vendor = "uwp"))] + { + if unsafe { RtlGenRandom(chunk.as_mut_ptr() as *mut c_void, chunk.len() as u32) } + != 0 + { + continue; + } + } // We zeroize the highest bit, so the error code will reside // inside the range designated for OS codes. let code = ret ^ (1 << 31);