From 51a229c596b010396c64ef8769cde7018b05ab17 Mon Sep 17 00:00:00 2001 From: qilme <89187439+qilme@users.noreply.github.com> Date: Thu, 30 Oct 2025 17:51:28 +0800 Subject: [PATCH 1/5] std.os.windows: eliminate forwarder function in kernel32 #1840 --- lib/std/os/windows/kernel32.zig | 115 ++++++++------------------------ lib/std/os/windows/ntdll.zig | 59 ++++++++++++++++ 2 files changed, 85 insertions(+), 89 deletions(-) diff --git a/lib/std/os/windows/kernel32.zig b/lib/std/os/windows/kernel32.zig index c93304d82b9a..9067fc20698e 100644 --- a/lib/std/os/windows/kernel32.zig +++ b/lib/std/os/windows/kernel32.zig @@ -1,18 +1,16 @@ const std = @import("../../std.zig"); const windows = std.os.windows; +const ntdll = windows.ntdll; 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 +30,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,16 +255,8 @@ 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; +pub const AddVectoredExceptionHandler = ntdll.RtlAddVectoredExceptionHandler; +pub const RemoveVectoredExceptionHandler = ntdll.RtlRemoveVectoredExceptionHandler; // TODO: Wrapper around RtlReportSilentProcessExit + NtTerminateProcess. pub extern "kernel32" fn TerminateProcess( @@ -321,10 +310,7 @@ 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; +pub const ExitProcess = ntdll.RtlExitUserProcess; // TODO: implement via ntdll instead pub extern "kernel32" fn SleepEx( @@ -372,40 +358,14 @@ 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; +pub const InitializeCriticalSection = ntdll.RtlInitializeCriticalSection; +pub const EnterCriticalSection = ntdll.RtlEnterCriticalSection; +pub const LeaveCriticalSection = ntdll.RtlLeaveCriticalSection; +pub const DeleteCriticalSection = ntdll.RtlDeleteCriticalSection; -// TODO: Forwarder to RtlReleaseSRWLockExclusive -pub extern "kernel32" fn ReleaseSRWLockExclusive( - SRWLock: *SRWLOCK, -) callconv(.winapi) void; +pub const TryAcquireSRWLockExclusive = ntdll.RtlTryAcquireSRWLockExclusive; +pub const AcquireSRWLockExclusive = ntdll.RtlAcquireSRWLockExclusive; +pub const ReleaseSRWLockExclusive = ntdll.RtlReleaseSRWLockExclusive; pub extern "kernel32" fn InitOnceExecuteOnce( InitOnce: *INIT_ONCE, @@ -414,15 +374,8 @@ 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; +pub const WakeConditionVariable = ntdll.RtlWakeConditionVariable; +pub const WakeAllConditionVariable = ntdll.RtlWakeAllConditionVariable; // TODO: // - dwMilliseconds -> LARGE_INTEGER. @@ -514,27 +467,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. -pub extern "kernel32" fn HeapFree( - hHeap: HANDLE, - dwFlags: DWORD, - lpMem: LPVOID, -) callconv(.winapi) BOOL; +pub const HeapReAlloc = ntdll.RtlReAllocateHeap; +pub const HeapAlloc = ntdll.RtlAllocateHeap; +pub const HeapFree = ntdll.RtlFreeHeap; // TODO: Wrapper around RtlValidateHeap (BOOLEAN -> BOOL) pub extern "kernel32" fn HeapValidate( @@ -642,4 +577,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; diff --git a/lib/std/os/windows/ntdll.zig b/lib/std/os/windows/ntdll.zig index 474aea3330c7..355fddf92bd4 100644 --- a/lib/std/os/windows/ntdll.zig +++ b/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,58 @@ 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) void; +pub extern "ntdll" fn RtlEnterCriticalSection( + lpCriticalSection: *CRITICAL_SECTION, +) callconv(.winapi) void; +pub extern "ntdll" fn RtlLeaveCriticalSection( + lpCriticalSection: *CRITICAL_SECTION, +) callconv(.winapi) void; +pub extern "ntdll" fn RtlDeleteCriticalSection( + lpCriticalSection: *CRITICAL_SECTION, +) callconv(.winapi) void; + +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( + hHeap: HANDLE, + dwFlags: DWORD, + lpMem: *anyopaque, + dwBytes: SIZE_T, +) callconv(.winapi) ?*anyopaque; +pub extern "ntdll" fn RtlAllocateHeap( + hHeap: HANDLE, + dwFlags: DWORD, + dwBytes: SIZE_T, +) callconv(.winapi) ?*anyopaque; +pub extern "ntdll" fn RtlFreeHeap( + hHeap: HANDLE, + dwFlags: DWORD, + lpMem: LPVOID, +) callconv(.winapi) BOOL; From f2b87b06a983a1dbedc67a4798a7886d5b35c206 Mon Sep 17 00:00:00 2001 From: qilme <89187439+qilme@users.noreply.github.com> Date: Thu, 30 Oct 2025 18:35:37 +0800 Subject: [PATCH 2/5] std.os.windows: move kernel32 api to ntdll. 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 kernel32.HeapFree -> ntdll.RtlFreeHeap --- lib/std/Thread.zig | 6 +++--- lib/std/Thread/Condition.zig | 4 ++-- lib/std/Thread/Mutex.zig | 6 +++--- lib/std/debug.zig | 4 ++-- lib/std/os/windows/kernel32.zig | 22 ---------------------- lib/std/posix.zig | 4 ++-- 6 files changed, 12 insertions(+), 34 deletions(-) diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index f3abe1e6cfe1..d235e14eef1b 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -650,7 +650,7 @@ const WindowsThreadImpl = struct { thread_handle: windows.HANDLE = undefined, fn free(self: ThreadCompletion) void { - const status = windows.kernel32.HeapFree(self.heap_handle, 0, self.heap_ptr); + const status = windows.ntdll.RtlFreeHeap(self.heap_handle, 0, self.heap_ptr); assert(status != 0); } }; @@ -674,8 +674,8 @@ 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; - errdefer assert(windows.kernel32.HeapFree(heap_handle, 0, alloc_ptr) != 0); + const alloc_ptr = windows.ntdll.RtlAllocateHeap(heap_handle, 0, alloc_bytes) orelse return error.OutOfMemory; + errdefer assert(windows.ntdll.RtlFreeHeap(heap_handle, 0, alloc_ptr) != 0); const instance_bytes = @as([*]u8, @ptrCast(alloc_ptr))[0..alloc_bytes]; var fba = std.heap.FixedBufferAllocator.init(instance_bytes); diff --git a/lib/std/Thread/Condition.zig b/lib/std/Thread/Condition.zig index b298e598df57..788b24038e71 100644 --- a/lib/std/Thread/Condition.zig +++ b/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), } } }; diff --git a/lib/std/Thread/Mutex.zig b/lib/std/Thread/Mutex.zig index 402c96a4d523..392fcde42a30 100644 --- a/lib/std/Thread/Mutex.zig +++ b/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; diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 3bb5d6d7abc0..694d8df150bc 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -1430,7 +1430,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{ @@ -1444,7 +1444,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; diff --git a/lib/std/os/windows/kernel32.zig b/lib/std/os/windows/kernel32.zig index 9067fc20698e..edb9546043ef 100644 --- a/lib/std/os/windows/kernel32.zig +++ b/lib/std/os/windows/kernel32.zig @@ -1,6 +1,5 @@ const std = @import("../../std.zig"); const windows = std.os.windows; -const ntdll = windows.ntdll; const BOOL = windows.BOOL; const CONDITION_VARIABLE = windows.CONDITION_VARIABLE; @@ -255,9 +254,6 @@ pub extern "kernel32" fn CreateIoCompletionPort( NumberOfConcurrentThreads: DWORD, ) callconv(.winapi) ?HANDLE; -pub const AddVectoredExceptionHandler = ntdll.RtlAddVectoredExceptionHandler; -pub const RemoveVectoredExceptionHandler = ntdll.RtlRemoveVectoredExceptionHandler; - // TODO: Wrapper around RtlReportSilentProcessExit + NtTerminateProcess. pub extern "kernel32" fn TerminateProcess( hProcess: HANDLE, @@ -310,8 +306,6 @@ pub extern "kernel32" fn CreateProcessW( lpProcessInformation: *PROCESS_INFORMATION, ) callconv(.winapi) BOOL; -pub const ExitProcess = ntdll.RtlExitUserProcess; - // TODO: implement via ntdll instead pub extern "kernel32" fn SleepEx( dwMilliseconds: DWORD, @@ -358,15 +352,6 @@ pub extern "kernel32" fn SwitchToThread() callconv(.winapi) BOOL; // Locks, critical sections, initializers -pub const InitializeCriticalSection = ntdll.RtlInitializeCriticalSection; -pub const EnterCriticalSection = ntdll.RtlEnterCriticalSection; -pub const LeaveCriticalSection = ntdll.RtlLeaveCriticalSection; -pub const DeleteCriticalSection = ntdll.RtlDeleteCriticalSection; - -pub const TryAcquireSRWLockExclusive = ntdll.RtlTryAcquireSRWLockExclusive; -pub const AcquireSRWLockExclusive = ntdll.RtlAcquireSRWLockExclusive; -pub const ReleaseSRWLockExclusive = ntdll.RtlReleaseSRWLockExclusive; - pub extern "kernel32" fn InitOnceExecuteOnce( InitOnce: *INIT_ONCE, InitFn: INIT_ONCE_FN, @@ -374,9 +359,6 @@ pub extern "kernel32" fn InitOnceExecuteOnce( Context: ?*anyopaque, ) callconv(.winapi) BOOL; -pub const WakeConditionVariable = ntdll.RtlWakeConditionVariable; -pub const WakeAllConditionVariable = ntdll.RtlWakeAllConditionVariable; - // TODO: // - dwMilliseconds -> LARGE_INTEGER. // - RtlSleepConditionVariableSRW @@ -467,10 +449,6 @@ pub extern "kernel32" fn HeapCreate( dwMaximumSize: SIZE_T, ) callconv(.winapi) ?HANDLE; -pub const HeapReAlloc = ntdll.RtlReAllocateHeap; -pub const HeapAlloc = ntdll.RtlAllocateHeap; -pub const HeapFree = ntdll.RtlFreeHeap; - // TODO: Wrapper around RtlValidateHeap (BOOLEAN -> BOOL) pub extern "kernel32" fn HeapValidate( hHeap: HANDLE, diff --git a/lib/std/posix.zig b/lib/std/posix.zig index 6faf6bbe7215..0dd3a2f924fc 100644 --- a/lib/std/posix.zig +++ b/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); From 8082fe05a6d10f3f803441dc9a32531209165cc7 Mon Sep 17 00:00:00 2001 From: qilme <89187439+qilme@users.noreply.github.com> Date: Fri, 31 Oct 2025 13:34:23 +0800 Subject: [PATCH 3/5] std.os.windows: fix some mismatched definitions in ntdll and restore `HeapFree` in kernel32 --- lib/std/Thread.zig | 4 ++-- lib/std/os/windows/kernel32.zig | 6 ++++++ lib/std/os/windows/ntdll.zig | 23 +++++++++-------------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index d235e14eef1b..59c6d78166c6 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -650,7 +650,7 @@ const WindowsThreadImpl = struct { thread_handle: windows.HANDLE = undefined, fn free(self: ThreadCompletion) void { - const status = windows.ntdll.RtlFreeHeap(self.heap_handle, 0, self.heap_ptr); + const status = windows.kernel32.HeapFree(self.heap_handle, 0, self.heap_ptr); assert(status != 0); } }; @@ -675,7 +675,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.ntdll.RtlAllocateHeap(heap_handle, 0, alloc_bytes) orelse return error.OutOfMemory; - errdefer assert(windows.ntdll.RtlFreeHeap(heap_handle, 0, alloc_ptr) != 0); + errdefer assert(windows.kernel32.HeapFree(heap_handle, 0, alloc_ptr) != 0); const instance_bytes = @as([*]u8, @ptrCast(alloc_ptr))[0..alloc_bytes]; var fba = std.heap.FixedBufferAllocator.init(instance_bytes); diff --git a/lib/std/os/windows/kernel32.zig b/lib/std/os/windows/kernel32.zig index edb9546043ef..c2cb2d57bc2a 100644 --- a/lib/std/os/windows/kernel32.zig +++ b/lib/std/os/windows/kernel32.zig @@ -449,6 +449,12 @@ pub extern "kernel32" fn HeapCreate( dwMaximumSize: SIZE_T, ) callconv(.winapi) ?HANDLE; +pub extern "kernel32" fn HeapFree( + hHeap: HANDLE, + dwFlags: DWORD, + lpMem: LPVOID, +) callconv(.winapi) BOOL; + // TODO: Wrapper around RtlValidateHeap (BOOLEAN -> BOOL) pub extern "kernel32" fn HeapValidate( hHeap: HANDLE, diff --git a/lib/std/os/windows/ntdll.zig b/lib/std/os/windows/ntdll.zig index 355fddf92bd4..65486365c230 100644 --- a/lib/std/os/windows/ntdll.zig +++ b/lib/std/os/windows/ntdll.zig @@ -419,18 +419,13 @@ pub extern "ntdll" fn RtlWakeAllConditionVariable( ) callconv(.winapi) void; pub extern "ntdll" fn RtlReAllocateHeap( - hHeap: HANDLE, - dwFlags: DWORD, - lpMem: *anyopaque, - dwBytes: SIZE_T, -) callconv(.winapi) ?*anyopaque; + HeapHandle: HANDLE, + Flags: ULONG, + BaseAddress: PVOID, + Size: SIZE_T, +) callconv(.winapi) ?PVOID; pub extern "ntdll" fn RtlAllocateHeap( - hHeap: HANDLE, - dwFlags: DWORD, - dwBytes: SIZE_T, -) callconv(.winapi) ?*anyopaque; -pub extern "ntdll" fn RtlFreeHeap( - hHeap: HANDLE, - dwFlags: DWORD, - lpMem: LPVOID, -) callconv(.winapi) BOOL; + HeapHandle: HANDLE, + Flags: ULONG, + Size: SIZE_T, +) callconv(.winapi) ?PVOID; From cb9fda482653450ec1d8535d8a15f7f286fd4d1b Mon Sep 17 00:00:00 2001 From: qilme <89187439+qilme@users.noreply.github.com> Date: Fri, 31 Oct 2025 14:47:54 +0800 Subject: [PATCH 4/5] std.os.windows.kernel32: add note to `HeapFree` --- lib/std/os/windows/kernel32.zig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/std/os/windows/kernel32.zig b/lib/std/os/windows/kernel32.zig index c2cb2d57bc2a..98d72a04e1b6 100644 --- a/lib/std/os/windows/kernel32.zig +++ b/lib/std/os/windows/kernel32.zig @@ -449,6 +449,9 @@ pub extern "kernel32" fn HeapCreate( dwMaximumSize: SIZE_T, ) callconv(.winapi) ?HANDLE; +// 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, From 0b00f45023e34d84510c4d51ad212aa4a3eb5492 Mon Sep 17 00:00:00 2001 From: qilme <89187439+qilme@users.noreply.github.com> Date: Fri, 31 Oct 2025 15:59:15 +0800 Subject: [PATCH 5/5] std.os.windows: fix some mismatched definitions in ntdll --- lib/std/os/windows/ntdll.zig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/std/os/windows/ntdll.zig b/lib/std/os/windows/ntdll.zig index 65486365c230..d323fbd5b5dc 100644 --- a/lib/std/os/windows/ntdll.zig +++ b/lib/std/os/windows/ntdll.zig @@ -390,16 +390,16 @@ pub extern "ntdll" fn RtlRemoveVectoredExceptionHandler( pub extern "ntdll" fn RtlInitializeCriticalSection( lpCriticalSection: *CRITICAL_SECTION, -) callconv(.winapi) void; +) callconv(.winapi) NTSTATUS; pub extern "ntdll" fn RtlEnterCriticalSection( lpCriticalSection: *CRITICAL_SECTION, -) callconv(.winapi) void; +) callconv(.winapi) NTSTATUS; pub extern "ntdll" fn RtlLeaveCriticalSection( lpCriticalSection: *CRITICAL_SECTION, -) callconv(.winapi) void; +) callconv(.winapi) NTSTATUS; pub extern "ntdll" fn RtlDeleteCriticalSection( lpCriticalSection: *CRITICAL_SECTION, -) callconv(.winapi) void; +) callconv(.winapi) NTSTATUS; pub extern "ntdll" fn RtlTryAcquireSRWLockExclusive( SRWLock: *SRWLOCK,