Skip to content

Commit 08f2741

Browse files
committed
Atomic Load/Store
Signed-off-by: Joe Richey <[email protected]>
1 parent ddb680d commit 08f2741

File tree

1 file changed

+31
-17
lines changed

1 file changed

+31
-17
lines changed

src/windows.rs

+31-17
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,47 @@
11
//! Implementation for Windows
22
use crate::Error;
3-
use core::mem::MaybeUninit;
4-
5-
extern crate std;
6-
use std::println;
3+
use core::{
4+
ffi::c_void,
5+
mem,
6+
mem::MaybeUninit,
7+
ptr,
8+
sync::atomic::{fence, AtomicPtr, Ordering},
9+
};
710

811
type HMODULE = isize;
912
type BOOL = i32;
1013
const TRUE: BOOL = 1;
1114

12-
type ProcessPrng = unsafe extern "system" fn(*mut u8, usize) -> BOOL;
13-
1415
#[link(name = "kernel32")]
1516
extern "system" {
1617
fn LoadLibraryA(libfilename: *const u8) -> HMODULE;
17-
fn GetProcAddress(hmodule: HMODULE, procname: *const u8) -> Option<ProcessPrng>;
18+
fn GetProcAddress(hmodule: HMODULE, procname: *const u8) -> *mut c_void;
1819
}
1920

20-
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
21-
let dll = unsafe { LoadLibraryA(b"bcryptprimitives.dll\0".as_ptr()) };
22-
println!("Got DLL: {}", dll);
23-
if dll == 0 {
24-
return Err(Error::WINDOWS_LOAD_DLL);
21+
type ProcessPrng = unsafe extern "system" fn(*mut u8, usize) -> BOOL;
22+
23+
static PROCESS_PRNG_PTR: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());
24+
25+
fn get_process_prng() -> Result<ProcessPrng, Error> {
26+
let mut p = PROCESS_PRNG_PTR.load(Ordering::Relaxed);
27+
if p.is_null() {
28+
let dll = unsafe { LoadLibraryA(b"bcryptprimitives.dll\0".as_ptr()) };
29+
if dll == 0 {
30+
return Err(Error::WINDOWS_LOAD_DLL);
31+
}
32+
p = unsafe { GetProcAddress(dll, b"ProcessPrng\0".as_ptr()) };
33+
if p.is_null() {
34+
return Err(Error::WINDOWS_LOAD_DLL);
35+
}
36+
PROCESS_PRNG_PTR.store(p, Ordering::Release);
37+
} else {
38+
fence(Ordering::Acquire);
2539
}
26-
let process_prng = match unsafe { GetProcAddress(dll, b"ProcessPrng\0".as_ptr()) } {
27-
Some(p) => p,
28-
None => return Err(Error::WINDOWS_LOAD_DLL),
29-
};
30-
println!("Got ProcessPrng: {:p}", process_prng);
40+
Ok(unsafe { mem::transmute(p) })
41+
}
42+
43+
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
44+
let process_prng = get_process_prng()?;
3145
match unsafe { process_prng(dest.as_mut_ptr() as *mut u8, dest.len()) } {
3246
TRUE => Ok(()),
3347
_ => Err(Error::WINDOWS_PROCESS_PRNG),

0 commit comments

Comments
 (0)