authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-05 00:36:11-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-05 00:36:11-08:00
log60e2ea0bfbb8a8ae2df31a8e45ef8c416a9ff77e
treec221bd13b362fbc0161260bb41fe94c16bdb9bb4
parent36044a0e81702954e0ad5d5bd14a8b23929e7db8

windows: use ProcessPrng from bcryptprimitives.dll

rather than SystemFunction036 from advapi32. This has the advantage that the code is loaded preemptively, preventing random numbers from failing when they are needed for the first time on a system under heavy load.

7 files changed, 6 insertions(+), 36 deletions(-)

lib/std/os/windows.zig+1-27
......@@ -22,6 +22,7 @@ test {
2222}
2323
2424pub const advapi32 = @import("windows/advapi32.zig");
25pub const bcryptprimitives = @import("windows/bcryptprimitives.zig");
2526pub const kernel32 = @import("windows/kernel32.zig");
2627pub const ntdll = @import("windows/ntdll.zig");
2728pub const ws2_32 = @import("windows/ws2_32.zig");
......@@ -2644,33 +2645,6 @@ pub fn SetHandleInformation(h: HANDLE, mask: DWORD, flags: DWORD) SetHandleInfor
26442645 }
26452646}
26462647
2647pub const RtlGenRandomError = error{
2648 /// `RtlGenRandom` has been known to fail in situations where the system is under heavy load.
2649 /// Unfortunately, it does not call `SetLastError`, so it is not possible to get more specific
2650 /// error information; it could actually be due to an out-of-memory condition, for example.
2651 SystemResources,
2652};
2653
2654/// Call RtlGenRandom() instead of CryptGetRandom() on Windows
2655/// https://github.com/rust-lang-nursery/rand/issues/111
2656/// https://bugzilla.mozilla.org/show_bug.cgi?id=504270
2657pub fn RtlGenRandom(output: []u8) RtlGenRandomError!void {
2658 var total_read: usize = 0;
2659 var buff: []u8 = output[0..];
2660 const max_read_size: ULONG = maxInt(ULONG);
2661
2662 while (total_read < output.len) {
2663 const to_read: ULONG = @min(buff.len, max_read_size);
2664
2665 if (advapi32.RtlGenRandom(buff.ptr, to_read) == 0) {
2666 return error.SystemResources;
2667 }
2668
2669 total_read += to_read;
2670 buff = buff[to_read..];
2671 }
2672}
2673
26742648pub const WaitForSingleObjectError = error{
26752649 WaitAbandoned,
26762650 WaitTimeOut,
lib/std/os/windows/advapi32.zig-5
......@@ -28,11 +28,6 @@ pub extern "advapi32" fn RegQueryValueExW(
2828
2929pub extern "advapi32" fn RegCloseKey(hKey: HKEY) callconv(.winapi) LSTATUS;
3030
31// RtlGenRandom is known as SystemFunction036 under advapi32
32// http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx */
33pub extern "advapi32" fn SystemFunction036(output: [*]u8, length: ULONG) callconv(.winapi) BOOL;
34pub const RtlGenRandom = SystemFunction036;
35
3631pub const RRF = struct {
3732 pub const RT_ANY: DWORD = 0x0000ffff;
3833
lib/std/os/windows/bcryptprimitives.zig created+4
......@@ -0,0 +1,4 @@
1const std = @import("../../std.zig");
2const windows = std.os.windows;
3
4pub extern "bcryptprimitives" fn ProcessPrng(pbData: [*]u8, cbData: usize) callconv(.winapi) c_int;
lib/std/posix.zig+1-1
......@@ -370,7 +370,7 @@ pub const GetRandomError = OpenError;
370370/// library implementation.
371371pub fn getrandom(buffer: []u8) GetRandomError!void {
372372 if (native_os == .windows) {
373 return windows.RtlGenRandom(buffer);
373 return assert(windows.bcryptprimitives.ProcessPrng(buffer.ptr, buffer.len) == 1);
374374 }
375375 if (builtin.link_libc and @TypeOf(system.arc4random_buf) != void) {
376376 system.arc4random_buf(buffer.ptr, buffer.len);
test/standalone/issue_5825/build.zig-1
......@@ -32,7 +32,6 @@ pub fn build(b: *std.Build) void {
3232 }),
3333 });
3434 exe.subsystem = .console;
35 exe.root_module.linkSystemLibrary("advapi32", .{}); // for RtlGenRandom
3635 exe.root_module.linkSystemLibrary("kernel32", .{});
3736 exe.root_module.linkSystemLibrary("ntdll", .{});
3837 exe.root_module.addObject(obj);
test/standalone/test_obj_link_run/build.zig-1
......@@ -12,7 +12,6 @@ pub fn build(b: *std.Build) void {
1212 test_obj.root_module.linkSystemLibrary("ntdll", .{});
1313 test_obj.root_module.linkSystemLibrary("kernel32", .{});
1414 test_obj.root_module.linkSystemLibrary("ws2_32", .{});
15 test_obj.root_module.linkSystemLibrary("advapi32", .{}); // for RtlGenRandom
1615 }
1716
1817 const test_exe_mod = b.createModule(.{
test/standalone/windows_argv/build.zig-1
......@@ -86,7 +86,6 @@ pub fn build(b: *std.Build) !void {
8686 .optimize = optimize,
8787 }),
8888 });
89 lib_msvc.root_module.linkSystemLibrary("advapi32", .{}); // for RtlGenRandom
9089 const verify_msvc = b.addExecutable(.{
9190 .name = "verify-msvc",
9291 .root_module = b.createModule(.{