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 {...@@ -22,6 +22,7 @@ test {
22}22}
2323
24pub const advapi32 = @import("windows/advapi32.zig");24pub const advapi32 = @import("windows/advapi32.zig");
25pub const bcryptprimitives = @import("windows/bcryptprimitives.zig");
25pub const kernel32 = @import("windows/kernel32.zig");26pub const kernel32 = @import("windows/kernel32.zig");
26pub const ntdll = @import("windows/ntdll.zig");27pub const ntdll = @import("windows/ntdll.zig");
27pub const ws2_32 = @import("windows/ws2_32.zig");28pub const ws2_32 = @import("windows/ws2_32.zig");
...@@ -2644,33 +2645,6 @@ pub fn SetHandleInformation(h: HANDLE, mask: DWORD, flags: DWORD) SetHandleInfor...@@ -2644,33 +2645,6 @@ pub fn SetHandleInformation(h: HANDLE, mask: DWORD, flags: DWORD) SetHandleInfor
2644 }2645 }
2645}2646}
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
2674pub const WaitForSingleObjectError = error{2648pub const WaitForSingleObjectError = error{
2675 WaitAbandoned,2649 WaitAbandoned,
2676 WaitTimeOut,2650 WaitTimeOut,
lib/std/os/windows/advapi32.zig-5
...@@ -28,11 +28,6 @@ pub extern "advapi32" fn RegQueryValueExW(...@@ -28,11 +28,6 @@ pub extern "advapi32" fn RegQueryValueExW(
2828
29pub extern "advapi32" fn RegCloseKey(hKey: HKEY) callconv(.winapi) LSTATUS;29pub 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
36pub const RRF = struct {31pub const RRF = struct {
37 pub const RT_ANY: DWORD = 0x0000ffff;32 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;...@@ -370,7 +370,7 @@ pub const GetRandomError = OpenError;
370/// library implementation.370/// library implementation.
371pub fn getrandom(buffer: []u8) GetRandomError!void {371pub fn getrandom(buffer: []u8) GetRandomError!void {
372 if (native_os == .windows) {372 if (native_os == .windows) {
373 return windows.RtlGenRandom(buffer);373 return assert(windows.bcryptprimitives.ProcessPrng(buffer.ptr, buffer.len) == 1);
374 }374 }
375 if (builtin.link_libc and @TypeOf(system.arc4random_buf) != void) {375 if (builtin.link_libc and @TypeOf(system.arc4random_buf) != void) {
376 system.arc4random_buf(buffer.ptr, buffer.len);376 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 {...@@ -32,7 +32,6 @@ pub fn build(b: *std.Build) void {
32 }),32 }),
33 });33 });
34 exe.subsystem = .console;34 exe.subsystem = .console;
35 exe.root_module.linkSystemLibrary("advapi32", .{}); // for RtlGenRandom
36 exe.root_module.linkSystemLibrary("kernel32", .{});35 exe.root_module.linkSystemLibrary("kernel32", .{});
37 exe.root_module.linkSystemLibrary("ntdll", .{});36 exe.root_module.linkSystemLibrary("ntdll", .{});
38 exe.root_module.addObject(obj);37 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 {...@@ -12,7 +12,6 @@ pub fn build(b: *std.Build) void {
12 test_obj.root_module.linkSystemLibrary("ntdll", .{});12 test_obj.root_module.linkSystemLibrary("ntdll", .{});
13 test_obj.root_module.linkSystemLibrary("kernel32", .{});13 test_obj.root_module.linkSystemLibrary("kernel32", .{});
14 test_obj.root_module.linkSystemLibrary("ws2_32", .{});14 test_obj.root_module.linkSystemLibrary("ws2_32", .{});
15 test_obj.root_module.linkSystemLibrary("advapi32", .{}); // for RtlGenRandom
16 }15 }
1716
18 const test_exe_mod = b.createModule(.{17 const test_exe_mod = b.createModule(.{
test/standalone/windows_argv/build.zig-1
...@@ -86,7 +86,6 @@ pub fn build(b: *std.Build) !void {...@@ -86,7 +86,6 @@ pub fn build(b: *std.Build) !void {
86 .optimize = optimize,86 .optimize = optimize,
87 }),87 }),
88 });88 });
89 lib_msvc.root_module.linkSystemLibrary("advapi32", .{}); // for RtlGenRandom
90 const verify_msvc = b.addExecutable(.{89 const verify_msvc = b.addExecutable(.{
91 .name = "verify-msvc",90 .name = "verify-msvc",
92 .root_module = b.createModule(.{91 .root_module = b.createModule(.{