Skip to content

Commit 64ae3d9

Browse files
seritoolsmbilker
authored andcommitted
Remove static dependency on bcrypt.dll, advapi32.dll, userenv.dll
- Make `home_dir_crt` return `None` if the required WinAPI functions 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 e94c531 commit 64ae3d9

File tree

5 files changed

+105
-50
lines changed

5 files changed

+105
-50
lines changed

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

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,69 @@ compat_fn_with_fallback! {
535535
}
536536
}
537537

538+
compat_fn_with_fallback! {
539+
pub static ADVAPI32: &CStr = ansi_str!("advapi32");
540+
const LOAD: bool = true;
541+
542+
// >= NT 3.1+
543+
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocesstoken
544+
pub fn OpenProcessToken(
545+
ProcessHandle: HANDLE,
546+
DesiredAccess: DWORD,
547+
TokenHandle: *mut HANDLE
548+
) -> BOOL {
549+
rtabort!("unavailable")
550+
}
551+
552+
// RtlGenRandom
553+
//
554+
// >= Vista / Server 2008
555+
// https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom
556+
pub fn SystemFunction036(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN {
557+
rtabort!("unavailable")
558+
}
559+
}
560+
561+
compat_fn_with_fallback! {
562+
pub static BCRYPT: &CStr = ansi_str!("bcrypt");
563+
const LOAD: bool = true;
564+
565+
// >= Vista / Server 2008
566+
// https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
567+
pub fn BCryptGenRandom(
568+
hAlgorithm: LPVOID,
569+
pBuffer: *mut u8,
570+
cbBuffer: ULONG,
571+
dwFlags: ULONG
572+
) -> NTSTATUS {
573+
if RtlGenRandom(pBuffer, cbBuffer) == TRUE as _ {
574+
0 // STATUS_SUCCESS
575+
} else {
576+
0xC0000001u32 as i32 // STATUS_UNSUCCESSFUL
577+
}
578+
}
579+
}
580+
581+
#[inline(always)]
582+
pub unsafe fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN {
583+
SystemFunction036(RandomBuffer, RandomBufferLength)
584+
}
585+
586+
compat_fn_with_fallback! {
587+
pub static USERENV: &CStr = ansi_str!("userenv");
588+
const LOAD: bool = true;
589+
590+
// >= NT 4
591+
// https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getuserprofiledirectoryw
592+
pub fn GetUserProfileDirectoryW(
593+
hToken: HANDLE,
594+
lpProfileDir: LPWSTR,
595+
lpcchSize: *mut DWORD
596+
) -> BOOL {
597+
rtabort!("unavailable")
598+
}
599+
}
600+
538601
#[link(name = "kernel32")]
539602
extern "system" {
540603
pub fn LoadLibraryA(lpFileName: LPCSTR) -> HMODULE;
@@ -567,4 +630,7 @@ extern "system" {
567630
lpDistanceToMoveHigh: *mut LONG,
568631
dwMoveMethod: DWORD,
569632
) -> DWORD;
633+
634+
pub fn GetTickCount() -> DWORD;
635+
pub fn GetCurrentThreadId() -> DWORD;
570636
}

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,10 +2176,8 @@ Windows.Win32.Networking.WinSock.WSASYSNOTREADY
21762176
Windows.Win32.Networking.WinSock.WSATRY_AGAIN
21772177
Windows.Win32.Networking.WinSock.WSATYPE_NOT_FOUND
21782178
Windows.Win32.Networking.WinSock.WSAVERNOTSUPPORTED
2179-
Windows.Win32.Security.Authentication.Identity.RtlGenRandom
21802179
Windows.Win32.Security.Cryptography.BCRYPT_ALG_HANDLE
21812180
Windows.Win32.Security.Cryptography.BCRYPT_USE_SYSTEM_PREFERRED_RNG
2182-
Windows.Win32.Security.Cryptography.BCryptGenRandom
21832181
Windows.Win32.Security.Cryptography.BCRYPTGENRANDOM_FLAGS
21842182
Windows.Win32.Security.SECURITY_ATTRIBUTES
21852183
Windows.Win32.Security.TOKEN_ACCESS_MASK
@@ -2523,7 +2521,6 @@ Windows.Win32.System.Threading.InitOnceBeginInitialize
25232521
Windows.Win32.System.Threading.InitOnceComplete
25242522
Windows.Win32.System.Threading.LPTHREAD_START_ROUTINE
25252523
Windows.Win32.System.Threading.NORMAL_PRIORITY_CLASS
2526-
Windows.Win32.System.Threading.OpenProcessToken
25272524
Windows.Win32.System.Threading.PCONDITION_VARIABLE
25282525
Windows.Win32.System.Threading.PROCESS_CREATION_FLAGS
25292526
Windows.Win32.System.Threading.PROCESS_INFORMATION
@@ -2571,6 +2568,5 @@ Windows.Win32.System.Threading.WaitForSingleObject
25712568
Windows.Win32.System.WindowsProgramming.IO_STATUS_BLOCK
25722569
Windows.Win32.System.WindowsProgramming.OBJECT_ATTRIBUTES
25732570
Windows.Win32.System.WindowsProgramming.PROGRESS_CONTINUE
2574-
Windows.Win32.UI.Shell.GetUserProfileDirectoryW
25752571
// tidy-alphabetical-end
25762572

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

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,6 @@
77
// Bindings generated by `windows-bindgen` 0.49.0
88

99
#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)]
10-
#[link(name = "advapi32")]
11-
extern "system" {
12-
pub fn OpenProcessToken(
13-
processhandle: HANDLE,
14-
desiredaccess: TOKEN_ACCESS_MASK,
15-
tokenhandle: *mut HANDLE,
16-
) -> BOOL;
17-
}
18-
#[link(name = "advapi32")]
19-
extern "system" {
20-
#[link_name = "SystemFunction036"]
21-
pub fn RtlGenRandom(randombuffer: *mut ::core::ffi::c_void, randombufferlength: u32)
22-
-> BOOLEAN;
23-
}
24-
#[link(name = "bcrypt")]
25-
extern "system" {
26-
pub fn BCryptGenRandom(
27-
halgorithm: BCRYPT_ALG_HANDLE,
28-
pbbuffer: *mut u8,
29-
cbbuffer: u32,
30-
dwflags: BCRYPTGENRANDOM_FLAGS,
31-
) -> NTSTATUS;
32-
}
3310
#[link(name = "kernel32")]
3411
extern "system" {
3512
pub fn CancelIo(hfile: HANDLE) -> BOOL;
@@ -560,14 +537,6 @@ extern "system" {
560537
extern "system" {
561538
pub fn RtlNtStatusToDosError(status: NTSTATUS) -> u32;
562539
}
563-
#[link(name = "userenv")]
564-
extern "system" {
565-
pub fn GetUserProfileDirectoryW(
566-
htoken: HANDLE,
567-
lpprofiledir: PWSTR,
568-
lpcchsize: *mut u32,
569-
) -> BOOL;
570-
}
571540
#[link(name = "ws2_32")]
572541
extern "system" {
573542
pub fn WSACleanup() -> i32;

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

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

281281
#[cfg(not(target_vendor = "uwp"))]
282282
fn home_dir_crt() -> Option<PathBuf> {
283+
if !c::GetUserProfileDirectoryW::available() || !c::OpenProcessToken::available() {
284+
return None;
285+
}
286+
283287
unsafe {
284288
// The magic constant -4 can be used as the token passed to GetUserProfileDirectoryW below
285289
// 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: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
use crate::ffi::c_void;
22
use crate::io;
3+
use crate::mem::MaybeUninit;
34
use crate::mem;
45
use crate::ptr;
56
use crate::sys::c;
67

78
pub fn hashmap_random_keys() -> (u64, u64) {
8-
let mut v = (0, 0);
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() }
9+
if c::BCryptGenRandom::available() {
10+
let mut v = (0, 0);
11+
let ret = unsafe {
12+
c::BCryptGenRandom(
13+
ptr::null_mut(),
14+
&mut v as *mut _ as *mut u8,
15+
mem::size_of_val(&v) as c::ULONG,
16+
c::BCRYPT_USE_SYSTEM_PREFERRED_RNG,
17+
)
18+
};
19+
if c::nt_success(ret) {
20+
return v;
21+
}
22+
}
23+
24+
fallback_rng()
1825
}
1926

2027
/// Generate random numbers using the fallback RNG function (RtlGenRandom)
@@ -25,12 +32,25 @@ pub fn hashmap_random_keys() -> (u64, u64) {
2532
#[cfg(not(target_vendor = "uwp"))]
2633
#[inline(never)]
2734
fn fallback_rng() -> (u64, u64) {
28-
let mut v = (0, 0);
29-
let ret = unsafe {
30-
c::RtlGenRandom(&mut v as *mut _ as *mut c_void, mem::size_of_val(&v) as c::ULONG)
31-
};
35+
if c::SystemFunction036::available() {
36+
let mut v = (0, 0);
37+
let ret = unsafe {
38+
c::RtlGenRandom(&mut v as *mut _ as *mut c_void, mem::size_of_val(&v) as c::ULONG)
39+
};
40+
if ret != 0 { v } else { panic!("fallback RNG broken: {}", io::Error::last_os_error()) }
41+
}
3242

33-
if ret != 0 { v } else { panic!("fallback RNG broken: {}", io::Error::last_os_error()) }
43+
unsafe {
44+
let tick_count = c::GetTickCount();
45+
let id = c::GetCurrentThreadId();
46+
let mut file_time: c::FILETIME = MaybeUninit::zeroed().assume_init();
47+
c::GetSystemTimeAsFileTime(&mut file_time as *mut _);
48+
49+
(
50+
(file_time.dwHighDateTime as u64) << 32 | tick_count as u64,
51+
(id as u64) << 32 | file_time.dwLowDateTime as u64,
52+
)
53+
}
3454
}
3555

3656
/// We can't use RtlGenRandom with UWP, so there is no fallback

0 commit comments

Comments
 (0)