Skip to content

Commit

Permalink
Atomic Load/Store
Browse files Browse the repository at this point in the history
Signed-off-by: Joe Richey <joerichey@google.com>
  • Loading branch information
josephlr committed May 1, 2024
1 parent dd6be1f commit c19da41
Showing 1 changed file with 31 additions and 17 deletions.
48 changes: 31 additions & 17 deletions src/windows.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,47 @@
//! Implementation for Windows
use crate::Error;
use core::mem::MaybeUninit;

extern crate std;
use std::println;
use core::{
ffi::c_void,
mem,
mem::MaybeUninit,
ptr,
sync::atomic::{fence, AtomicPtr, Ordering},
};

type HMODULE = isize;
type BOOL = i32;
const TRUE: BOOL = 1;

type ProcessPrng = unsafe extern "system" fn(*mut u8, usize) -> BOOL;

#[link(name = "kernel32")]
extern "system" {
fn LoadLibraryA(libfilename: *const u8) -> HMODULE;
fn GetProcAddress(hmodule: HMODULE, procname: *const u8) -> Option<ProcessPrng>;
fn GetProcAddress(hmodule: HMODULE, procname: *const u8) -> *mut c_void;
}

pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
let dll = unsafe { LoadLibraryA(b"bcryptprimitives.dll\0".as_ptr()) };
println!("Got DLL: {}", dll);
if dll == 0 {
return Err(Error::WINDOWS_LOAD_DLL);
type ProcessPrng = unsafe extern "system" fn(*mut u8, usize) -> BOOL;

static PROCESS_PRNG_PTR: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());

fn get_process_prng() -> Result<ProcessPrng, Error> {
let mut p = PROCESS_PRNG_PTR.load(Ordering::Relaxed);
if p.is_null() {
let dll = unsafe { LoadLibraryA(b"bcryptprimitives.dll\0".as_ptr()) };
if dll == 0 {
return Err(Error::WINDOWS_LOAD_DLL);
}
p = unsafe { GetProcAddress(dll, b"ProcessPrng\0".as_ptr()) };
if p.is_null() {
return Err(Error::WINDOWS_LOAD_DLL);
}
PROCESS_PRNG_PTR.store(p, Ordering::Release);
} else {
fence(Ordering::Acquire);
}
let process_prng = match unsafe { GetProcAddress(dll, b"ProcessPrng\0".as_ptr()) } {
Some(p) => p,
None => return Err(Error::WINDOWS_LOAD_DLL),
};
println!("Got ProcessPrng: {:p}", process_prng);
Ok(unsafe { mem::transmute(p) })
}

pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
let process_prng = get_process_prng()?;
match unsafe { process_prng(dest.as_mut_ptr() as *mut u8, dest.len()) } {
TRUE => Ok(()),
_ => Err(Error::WINDOWS_PROCESS_PRNG),
Expand Down

0 comments on commit c19da41

Please sign in to comment.