Skip to content

Commit 3773091

Browse files
committed
Remove static dependency on bcrypt.dll, advapi32.dll, userenv.dll
- Make `home_dir_crt` return `None` if the required APIs are not available - Fall back to `RtlGenRandom` if `BCryptGenRandom` is not supported - Fall back to custom `hashmap_random_keys` implementation if `RtlGenRandom` is also not supported
1 parent d945ac0 commit 3773091

File tree

5 files changed

+96
-9
lines changed

5 files changed

+96
-9
lines changed

library/std/src/sys/windows/c.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,55 @@ compat_fn_optional! {
469469
pub fn WakeConditionVariable(conditionvariable: *mut CONDITION_VARIABLE) -> ();
470470
}
471471

472+
compat_fn_lazy! {
473+
pub static USERENV: &CStr = c"userenv" => { load: true, unicows: false };
474+
475+
pub fn GetUserProfileDirectoryW(
476+
htoken: HANDLE,
477+
lpprofiledir: PWSTR,
478+
lpcchsize: *mut u32,
479+
) -> BOOL;
480+
}
481+
482+
compat_fn_with_fallback! {
483+
pub static BCRYPT: &CStr = c"bcrypt" => { load: true, unicows: false };
484+
485+
pub fn BCryptGenRandom(
486+
halgorithm: BCRYPT_ALG_HANDLE,
487+
pbbuffer: *mut u8,
488+
cbbuffer: u32,
489+
dwflags: BCRYPTGENRANDOM_FLAGS,
490+
) -> NTSTATUS {
491+
if SystemFunction036(pbbuffer.cast(), cbbuffer) == TRUE as _ {
492+
0 // STATUS_SUCCESS
493+
} else {
494+
0xC0000001u32 as i32 // STATUS_UNSUCCESSFUL
495+
}
496+
}
497+
}
498+
499+
compat_fn_lazy! {
500+
pub static ADVAPI32: &CStr = c"advapi32" => { load: true, unicows: false };
501+
502+
pub fn OpenProcessToken(
503+
processhandle: HANDLE,
504+
desiredaccess: TOKEN_ACCESS_MASK,
505+
tokenhandle: *mut HANDLE,
506+
) -> BOOL;
507+
}
508+
compat_fn_with_fallback! {
509+
pub static ADVAPI32: &CStr = c"advapi32" => { load: true, unicows: false };
510+
511+
pub fn SystemFunction036(randombuffer: *mut ::core::ffi::c_void, randombufferlength: u32)
512+
-> BOOLEAN {
513+
0
514+
}
515+
}
516+
pub const RtlGenRandom: unsafe fn(
517+
randombuffer: *mut ::core::ffi::c_void,
518+
randombufferlength: u32,
519+
) -> BOOLEAN = SystemFunction036;
520+
472521
compat_fn_with_fallback! {
473522
pub static NTDLL: &CStr = c"ntdll" => { load: true, unicows: false };
474523

library/std/src/sys/windows/c/windows_sys.lst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2617,3 +2617,7 @@ Windows.Win32.System.Time.SystemTimeToFileTime
26172617
Windows.Win32.Storage.FileSystem.SetFilePointer
26182618
Windows.Win32.Storage.FileSystem.SetEndOfFile
26192619
Windows.Win32.Storage.FileSystem.INVALID_SET_FILE_POINTER
2620+
2621+
// hashmap crypt fallback
2622+
Windows.Win32.System.SystemInformation.GetTickCount
2623+
Windows.Win32.System.Threading.GetCurrentThreadId

library/std/src/sys/windows/c/windows_sys.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,10 @@ extern "system" {
282282
pub fn GetCurrentThread() -> HANDLE;
283283
}
284284
#[link(name = "kernel32")]
285+
extern "system" {
286+
pub fn GetCurrentThreadId() -> u32;
287+
}
288+
#[link(name = "kernel32")]
285289
extern "system" {
286290
pub fn GetEnvironmentStringsW() -> PWSTR;
287291
}
@@ -393,6 +397,10 @@ extern "system" {
393397
pub fn GetTempPathW(nbufferlength: u32, lpbuffer: PWSTR) -> u32;
394398
}
395399
#[link(name = "kernel32")]
400+
extern "system" {
401+
pub fn GetTickCount() -> u32;
402+
}
403+
#[link(name = "kernel32")]
396404
extern "system" {
397405
pub fn GetWindowsDirectoryW(lpbuffer: PWSTR, usize: u32) -> u32;
398406
}

library/std/src/sys/windows/os.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,10 @@ pub fn temp_dir() -> PathBuf {
320320

321321
#[cfg(not(target_vendor = "uwp"))]
322322
fn home_dir_crt() -> Option<PathBuf> {
323+
if c::OpenProcessToken::option().is_none() || c::GetUserProfileDirectoryW::option().is_none() {
324+
return None;
325+
}
326+
323327
unsafe {
324328
// The magic constant -4 can be used as the token passed to GetUserProfileDirectoryW below
325329
// instead of us having to go through these multiple steps to get a token. However this is

library/std/src/sys/windows/rand.rs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,22 @@ use crate::sys::c;
44

55
pub fn hashmap_random_keys() -> (u64, u64) {
66
let mut v = (0, 0);
7-
let ret = unsafe {
8-
c::BCryptGenRandom(
9-
ptr::null_mut(),
10-
&mut v as *mut _ as *mut u8,
11-
mem::size_of_val(&v) as c::ULONG,
12-
c::BCRYPT_USE_SYSTEM_PREFERRED_RNG,
13-
)
14-
};
15-
if c::nt_success(ret) { v } else { fallback_rng() }
7+
8+
if c::BCryptGenRandom::available() {
9+
let ret = unsafe {
10+
c::BCryptGenRandom(
11+
ptr::null_mut(),
12+
&mut v as *mut _ as *mut u8,
13+
mem::size_of_val(&v) as c::ULONG,
14+
c::BCRYPT_USE_SYSTEM_PREFERRED_RNG,
15+
)
16+
};
17+
if c::nt_success(ret) { v } else { fallback_rng() }
18+
} else if c::SystemFunction036::available() {
19+
fallback_rng()
20+
} else {
21+
true_fallback_rng()
22+
}
1623
}
1724

1825
/// Generate random numbers using the fallback RNG function (RtlGenRandom)
@@ -40,3 +47,18 @@ fn fallback_rng() -> (u64, u64) {
4047
fn fallback_rng() -> (u64, u64) {
4148
panic!("fallback RNG broken: RtlGenRandom() not supported on UWP");
4249
}
50+
51+
#[inline(never)]
52+
fn true_fallback_rng() -> (u64, u64) {
53+
unsafe {
54+
let tickCount = c::GetTickCount();
55+
let id = c::GetCurrentThreadId();
56+
let mut file_time: c::FILETIME = crate::mem::zeroed();
57+
c::GetSystemTimeAsFileTime(&mut file_time as *mut _);
58+
59+
(
60+
(file_time.dwHighDateTime as u64) << 32 | tickCount as u64,
61+
(id as u64) << 32 | file_time.dwLowDateTime as u64,
62+
)
63+
}
64+
}

0 commit comments

Comments
 (0)