Commit 8347791ce3

qilme <89187439+qilme@users.noreply.github.com>
2025-10-31 14:54:50
std.os.windows: eliminate forwarder function in kernel32 (#25766)
#1840 kernel32.AddVectoredExceptionHandler -> ntdll.RtlAddVectoredExceptionHandler kernel32.RemoveVectoredExceptionHandler -> ntdll.RtlRemoveVectoredExceptionHandler kernel32.ExitProcess -> ntdll.RtlExitUserProcess kernel32.InitializeCriticalSection -> ntdll.RtlInitializeCriticalSection kernel32.EnterCriticalSection -> ntdll.RtlEnterCriticalSection kernel32.LeaveCriticalSection -> ntdll.RtlLeaveCriticalSection kernel32.DeleteCriticalSection -> ntdll.RtlDeleteCriticalSection kernel32.TryAcquireSRWLockExclusive -> ntdll.RtlTryAcquireSRWLockExclusive kernel32.AcquireSRWLockExclusive -> ntdll.RtlAcquireSRWLockExclusive kernel32.ReleaseSRWLockExclusive -> ntdll.RtlReleaseSRWLockExclusive kernel32.WakeConditionVariable -> ntdll.RtlWakeConditionVariable kernel32.WakeAllConditionVariable -> ntdll.RtlWakeAllConditionVariable kernel32.HeapReAlloc -> ntdll.RtlReAllocateHeap kernel32.HeapAlloc -> ntdll.RtlAllocateHeap
1 parent 62de7a2
lib/std/os/windows/kernel32.zig
@@ -2,17 +2,14 @@ const std = @import("../../std.zig");
 const windows = std.os.windows;
 
 const BOOL = windows.BOOL;
-const BOOLEAN = windows.BOOLEAN;
 const CONDITION_VARIABLE = windows.CONDITION_VARIABLE;
 const CONSOLE_SCREEN_BUFFER_INFO = windows.CONSOLE_SCREEN_BUFFER_INFO;
 const COORD = windows.COORD;
-const CRITICAL_SECTION = windows.CRITICAL_SECTION;
 const DWORD = windows.DWORD;
 const FARPROC = windows.FARPROC;
 const FILETIME = windows.FILETIME;
 const HANDLE = windows.HANDLE;
 const HANDLER_ROUTINE = windows.HANDLER_ROUTINE;
-const HLOCAL = windows.HLOCAL;
 const HMODULE = windows.HMODULE;
 const INIT_ONCE = windows.INIT_ONCE;
 const INIT_ONCE_FN = windows.INIT_ONCE_FN;
@@ -32,30 +29,29 @@ const SECURITY_ATTRIBUTES = windows.SECURITY_ATTRIBUTES;
 const SIZE_T = windows.SIZE_T;
 const SRWLOCK = windows.SRWLOCK;
 const STARTUPINFOW = windows.STARTUPINFOW;
+const SYSTEM_INFO = windows.SYSTEM_INFO;
 const UCHAR = windows.UCHAR;
 const UINT = windows.UINT;
 const ULONG = windows.ULONG;
 const ULONG_PTR = windows.ULONG_PTR;
 const va_list = windows.va_list;
-const VECTORED_EXCEPTION_HANDLER = windows.VECTORED_EXCEPTION_HANDLER;
 const WCHAR = windows.WCHAR;
 const WIN32_FIND_DATAW = windows.WIN32_FIND_DATAW;
 const Win32Error = windows.Win32Error;
 const WORD = windows.WORD;
-const SYSTEM_INFO = windows.SYSTEM_INFO;
 
 // I/O - Filesystem
 
 pub extern "kernel32" fn ReadDirectoryChangesW(
-    hDirectory: windows.HANDLE,
+    hDirectory: HANDLE,
     lpBuffer: [*]align(@alignOf(windows.FILE_NOTIFY_INFORMATION)) u8,
-    nBufferLength: windows.DWORD,
-    bWatchSubtree: windows.BOOL,
+    nBufferLength: DWORD,
+    bWatchSubtree: BOOL,
     dwNotifyFilter: windows.FileNotifyChangeFilter,
-    lpBytesReturned: ?*windows.DWORD,
-    lpOverlapped: ?*windows.OVERLAPPED,
+    lpBytesReturned: ?*DWORD,
+    lpOverlapped: ?*OVERLAPPED,
     lpCompletionRoutine: windows.LPOVERLAPPED_COMPLETION_ROUTINE,
-) callconv(.winapi) windows.BOOL;
+) callconv(.winapi) BOOL;
 
 // TODO: Wrapper around NtCancelIoFile.
 pub extern "kernel32" fn CancelIo(
@@ -258,17 +254,6 @@ pub extern "kernel32" fn CreateIoCompletionPort(
     NumberOfConcurrentThreads: DWORD,
 ) callconv(.winapi) ?HANDLE;
 
-// TODO: Forwarder to NtAddVectoredExceptionHandler.
-pub extern "kernel32" fn AddVectoredExceptionHandler(
-    First: ULONG,
-    Handler: ?VECTORED_EXCEPTION_HANDLER,
-) callconv(.winapi) ?LPVOID;
-
-// TODO: Forwarder to NtRemoveVectoredExceptionHandler.
-pub extern "kernel32" fn RemoveVectoredExceptionHandler(
-    Handle: HANDLE,
-) callconv(.winapi) ULONG;
-
 // TODO: Wrapper around RtlReportSilentProcessExit + NtTerminateProcess.
 pub extern "kernel32" fn TerminateProcess(
     hProcess: HANDLE,
@@ -321,11 +306,6 @@ pub extern "kernel32" fn CreateProcessW(
     lpProcessInformation: *PROCESS_INFORMATION,
 ) callconv(.winapi) BOOL;
 
-// TODO: Fowarder to RtlExitUserProcess.
-pub extern "kernel32" fn ExitProcess(
-    exit_code: UINT,
-) callconv(.winapi) noreturn;
-
 // TODO: implement via ntdll instead
 pub extern "kernel32" fn SleepEx(
     dwMilliseconds: DWORD,
@@ -372,41 +352,6 @@ pub extern "kernel32" fn SwitchToThread() callconv(.winapi) BOOL;
 
 // Locks, critical sections, initializers
 
-// TODO: Forwarder to RtlInitializeCriticalSection
-pub extern "kernel32" fn InitializeCriticalSection(
-    lpCriticalSection: *CRITICAL_SECTION,
-) callconv(.winapi) void;
-
-// TODO: Forwarder to RtlEnterCriticalSection
-pub extern "kernel32" fn EnterCriticalSection(
-    lpCriticalSection: *CRITICAL_SECTION,
-) callconv(.winapi) void;
-
-// TODO: Forwarder to RtlLeaveCriticalSection
-pub extern "kernel32" fn LeaveCriticalSection(
-    lpCriticalSection: *CRITICAL_SECTION,
-) callconv(.winapi) void;
-
-// TODO: Forwarder to RtlDeleteCriticalSection
-pub extern "kernel32" fn DeleteCriticalSection(
-    lpCriticalSection: *CRITICAL_SECTION,
-) callconv(.winapi) void;
-
-// TODO: Forwarder to RtlTryAcquireSRWLockExclusive
-pub extern "kernel32" fn TryAcquireSRWLockExclusive(
-    SRWLock: *SRWLOCK,
-) callconv(.winapi) BOOLEAN;
-
-// TODO: Forwarder to RtlAcquireSRWLockExclusive
-pub extern "kernel32" fn AcquireSRWLockExclusive(
-    SRWLock: *SRWLOCK,
-) callconv(.winapi) void;
-
-// TODO: Forwarder to RtlReleaseSRWLockExclusive
-pub extern "kernel32" fn ReleaseSRWLockExclusive(
-    SRWLock: *SRWLOCK,
-) callconv(.winapi) void;
-
 pub extern "kernel32" fn InitOnceExecuteOnce(
     InitOnce: *INIT_ONCE,
     InitFn: INIT_ONCE_FN,
@@ -414,16 +359,6 @@ pub extern "kernel32" fn InitOnceExecuteOnce(
     Context: ?*anyopaque,
 ) callconv(.winapi) BOOL;
 
-// TODO: Forwarder to RtlWakeConditionVariable
-pub extern "kernel32" fn WakeConditionVariable(
-    ConditionVariable: *CONDITION_VARIABLE,
-) callconv(.winapi) void;
-
-// TODO: Forwarder to RtlWakeAllConditionVariable
-pub extern "kernel32" fn WakeAllConditionVariable(
-    ConditionVariable: *CONDITION_VARIABLE,
-) callconv(.winapi) void;
-
 // TODO:
 //  - dwMilliseconds -> LARGE_INTEGER.
 //  - RtlSleepConditionVariableSRW
@@ -514,22 +449,9 @@ pub extern "kernel32" fn HeapCreate(
     dwMaximumSize: SIZE_T,
 ) callconv(.winapi) ?HANDLE;
 
-// TODO: Forwarder to RtlReAllocateHeap.
-pub extern "kernel32" fn HeapReAlloc(
-    hHeap: HANDLE,
-    dwFlags: DWORD,
-    lpMem: *anyopaque,
-    dwBytes: SIZE_T,
-) callconv(.winapi) ?*anyopaque;
-
-// TODO: Fowrarder to RtlAllocateHeap.
-pub extern "kernel32" fn HeapAlloc(
-    hHeap: HANDLE,
-    dwFlags: DWORD,
-    dwBytes: SIZE_T,
-) callconv(.winapi) ?*anyopaque;
-
-// TODO: Fowrarder to RtlFreeHeap.
+// TODO: Fowrarder to RtlFreeHeap before win11_zn.
+// Since win11_zn this function points to unexported symbol RtlFreeHeapFast.
+// See https://github.com/ziglang/zig/pull/25766#discussion_r2479727640
 pub extern "kernel32" fn HeapFree(
     hHeap: HANDLE,
     dwFlags: DWORD,
@@ -642,4 +564,6 @@ pub extern "kernel32" fn SetLastError(
 
 // Everything Else
 
-pub extern "kernel32" fn GetSystemInfo(lpSystemInfo: *SYSTEM_INFO) callconv(.winapi) void;
+pub extern "kernel32" fn GetSystemInfo(
+    lpSystemInfo: *SYSTEM_INFO,
+) callconv(.winapi) void;
lib/std/os/windows/ntdll.zig
@@ -37,6 +37,10 @@ const PROCESSINFOCLASS = windows.PROCESSINFOCLASS;
 const LPVOID = windows.LPVOID;
 const LPCVOID = windows.LPCVOID;
 const SECTION_INHERIT = windows.SECTION_INHERIT;
+const VECTORED_EXCEPTION_HANDLER = windows.VECTORED_EXCEPTION_HANDLER;
+const CRITICAL_SECTION = windows.CRITICAL_SECTION;
+const SRWLOCK = windows.SRWLOCK;
+const CONDITION_VARIABLE = windows.CONDITION_VARIABLE;
 
 pub extern "ntdll" fn NtQueryInformationProcess(
     ProcessHandle: HANDLE,
@@ -375,3 +379,53 @@ pub extern "ntdll" fn NtFreeVirtualMemory(
     RegionSize: *SIZE_T,
     FreeType: ULONG,
 ) callconv(.winapi) NTSTATUS;
+
+pub extern "ntdll" fn RtlAddVectoredExceptionHandler(
+    First: ULONG,
+    Handler: ?VECTORED_EXCEPTION_HANDLER,
+) callconv(.winapi) ?LPVOID;
+pub extern "ntdll" fn RtlRemoveVectoredExceptionHandler(
+    Handle: HANDLE,
+) callconv(.winapi) ULONG;
+
+pub extern "ntdll" fn RtlInitializeCriticalSection(
+    lpCriticalSection: *CRITICAL_SECTION,
+) callconv(.winapi) NTSTATUS;
+pub extern "ntdll" fn RtlEnterCriticalSection(
+    lpCriticalSection: *CRITICAL_SECTION,
+) callconv(.winapi) NTSTATUS;
+pub extern "ntdll" fn RtlLeaveCriticalSection(
+    lpCriticalSection: *CRITICAL_SECTION,
+) callconv(.winapi) NTSTATUS;
+pub extern "ntdll" fn RtlDeleteCriticalSection(
+    lpCriticalSection: *CRITICAL_SECTION,
+) callconv(.winapi) NTSTATUS;
+
+pub extern "ntdll" fn RtlTryAcquireSRWLockExclusive(
+    SRWLock: *SRWLOCK,
+) callconv(.winapi) BOOLEAN;
+pub extern "ntdll" fn RtlAcquireSRWLockExclusive(
+    SRWLock: *SRWLOCK,
+) callconv(.winapi) void;
+pub extern "ntdll" fn RtlReleaseSRWLockExclusive(
+    SRWLock: *SRWLOCK,
+) callconv(.winapi) void;
+
+pub extern "ntdll" fn RtlWakeConditionVariable(
+    ConditionVariable: *CONDITION_VARIABLE,
+) callconv(.winapi) void;
+pub extern "ntdll" fn RtlWakeAllConditionVariable(
+    ConditionVariable: *CONDITION_VARIABLE,
+) callconv(.winapi) void;
+
+pub extern "ntdll" fn RtlReAllocateHeap(
+    HeapHandle: HANDLE,
+    Flags: ULONG,
+    BaseAddress: PVOID,
+    Size: SIZE_T,
+) callconv(.winapi) ?PVOID;
+pub extern "ntdll" fn RtlAllocateHeap(
+    HeapHandle: HANDLE,
+    Flags: ULONG,
+    Size: SIZE_T,
+) callconv(.winapi) ?PVOID;
lib/std/Thread/Condition.zig
@@ -180,8 +180,8 @@ const WindowsImpl = struct {
 
     fn wake(self: *Impl, comptime notify: Notify) void {
         switch (notify) {
-            .one => os.windows.kernel32.WakeConditionVariable(&self.condition),
-            .all => os.windows.kernel32.WakeAllConditionVariable(&self.condition),
+            .one => os.windows.ntdll.RtlWakeConditionVariable(&self.condition),
+            .all => os.windows.ntdll.RtlWakeAllConditionVariable(&self.condition),
         }
     }
 };
lib/std/Thread/Mutex.zig
@@ -109,15 +109,15 @@ const WindowsImpl = struct {
     srwlock: windows.SRWLOCK = .{},
 
     fn tryLock(self: *@This()) bool {
-        return windows.kernel32.TryAcquireSRWLockExclusive(&self.srwlock) != windows.FALSE;
+        return windows.ntdll.RtlTryAcquireSRWLockExclusive(&self.srwlock) != windows.FALSE;
     }
 
     fn lock(self: *@This()) void {
-        windows.kernel32.AcquireSRWLockExclusive(&self.srwlock);
+        windows.ntdll.RtlAcquireSRWLockExclusive(&self.srwlock);
     }
 
     fn unlock(self: *@This()) void {
-        windows.kernel32.ReleaseSRWLockExclusive(&self.srwlock);
+        windows.ntdll.RtlReleaseSRWLockExclusive(&self.srwlock);
     }
 
     const windows = std.os.windows;
lib/std/debug.zig
@@ -1433,7 +1433,7 @@ pub fn attachSegfaultHandler() void {
         @compileError("segfault handler not supported for this target");
     }
     if (native_os == .windows) {
-        windows_segfault_handle = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows);
+        windows_segfault_handle = windows.ntdll.RtlAddVectoredExceptionHandler(0, handleSegfaultWindows);
         return;
     }
     const act = posix.Sigaction{
@@ -1447,7 +1447,7 @@ pub fn attachSegfaultHandler() void {
 fn resetSegfaultHandler() void {
     if (native_os == .windows) {
         if (windows_segfault_handle) |handle| {
-            assert(windows.kernel32.RemoveVectoredExceptionHandler(handle) != 0);
+            assert(windows.ntdll.RtlRemoveVectoredExceptionHandler(handle) != 0);
             windows_segfault_handle = null;
         }
         return;
lib/std/posix.zig
@@ -701,7 +701,7 @@ pub fn abort() noreturn {
         if (builtin.mode == .Debug and windows.peb().BeingDebugged != 0) {
             @breakpoint();
         }
-        windows.kernel32.ExitProcess(3);
+        windows.ntdll.RtlExitUserProcess(3);
     }
     if (!builtin.link_libc and native_os == .linux) {
         // The Linux man page says that the libc abort() function
@@ -794,7 +794,7 @@ pub fn exit(status: u8) noreturn {
         std.c.exit(status);
     }
     if (native_os == .windows) {
-        windows.kernel32.ExitProcess(status);
+        windows.ntdll.RtlExitUserProcess(status);
     }
     if (native_os == .wasi) {
         wasi.proc_exit(status);
lib/std/Thread.zig
@@ -674,7 +674,7 @@ const WindowsThreadImpl = struct {
 
         const heap_handle = windows.kernel32.GetProcessHeap() orelse return error.OutOfMemory;
         const alloc_bytes = @alignOf(Instance) + @sizeOf(Instance);
-        const alloc_ptr = windows.kernel32.HeapAlloc(heap_handle, 0, alloc_bytes) orelse return error.OutOfMemory;
+        const alloc_ptr = windows.ntdll.RtlAllocateHeap(heap_handle, 0, alloc_bytes) orelse return error.OutOfMemory;
         errdefer assert(windows.kernel32.HeapFree(heap_handle, 0, alloc_ptr) != 0);
 
         const instance_bytes = @as([*]u8, @ptrCast(alloc_ptr))[0..alloc_bytes];