From 69175ad62f531327e9fd693c13890ca1d472a7a3 Mon Sep 17 00:00:00 2001 From: Stephen Gregoratto Date: Tue, 12 Mar 2024 22:21:55 +1100 Subject: [PATCH] Windows: Add wrappers for `GetCurrent(Process|Thread)` via NT_TIB This is how they've been implemented in `kernel32` since NT 3.1. --- lib/std/child_process.zig | 2 +- lib/std/debug.zig | 2 +- lib/std/os/windows.zig | 47 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig index edc97c2c3e..85fa3d294e 100644 --- a/lib/std/child_process.zig +++ b/lib/std/child_process.zig @@ -1420,7 +1420,7 @@ fn windowsMakeAsyncPipe(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *cons const pipe_path = std.fmt.bufPrintZ( &tmp_buf, "\\\\.\\pipe\\zig-childprocess-{d}-{d}", - .{ windows.kernel32.GetCurrentProcessId(), pipe_name_counter.fetchAdd(1, .monotonic) }, + .{ windows.GetCurrentProcessId(), pipe_name_counter.fetchAdd(1, .monotonic) }, ) catch unreachable; const len = std.unicode.wtf8ToWtf16Le(&tmp_bufw, pipe_path) catch unreachable; tmp_bufw[len] = 0; diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 932fb4a730..13e2d95e2c 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -814,7 +814,7 @@ pub noinline fn walkStackWindows(addresses: []usize, existing_context: ?*const w return windows.ntdll.RtlCaptureStackBackTrace(0, addresses.len, @as(**anyopaque, @ptrCast(addresses.ptr)), null); } - const tib = @as(*const windows.NT_TIB, @ptrCast(&windows.teb().Reserved1)); + const tib = &windows.teb().NtTib; var context: windows.CONTEXT = undefined; if (existing_context) |context_ptr| { diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index 24ea53b0a9..147ad7a12b 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -153,6 +153,24 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN } } +pub fn GetCurrentProcess() HANDLE { + const process_pseudo_handle: usize = @bitCast(@as(isize, -1)); + return @ptrFromInt(process_pseudo_handle); +} + +pub fn GetCurrentProcessId() DWORD { + return @truncate(@intFromPtr(teb().ClientId.UniqueProcess)); +} + +pub fn GetCurrentThread() HANDLE { + const thread_pseudo_handle: usize = @bitCast(@as(isize, -2)); + return @ptrFromInt(thread_pseudo_handle); +} + +pub fn GetCurrentThreadId() DWORD { + return @truncate(@intFromPtr(teb().ClientId.UniqueThread)); +} + pub const CreatePipeError = error{ Unexpected, SystemResources }; var npfs: ?HANDLE = null; @@ -259,12 +277,12 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C var write: HANDLE = undefined; switch (ntdll.NtCreateFile( &write, - FILE_GENERIC_WRITE, + GENERIC_WRITE | SYNCHRONIZE | FILE_READ_ATTRIBUTES, &attrs, &iosb, null, 0, - FILE_SHARE_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE, null, @@ -4309,7 +4327,11 @@ pub const THREAD_BASIC_INFORMATION = extern struct { }; pub const TEB = extern struct { - Reserved1: [12]PVOID, + NtTib: NT_TIB, + EnvironmentPointer: PVOID, + ClientId: CLIENT_ID, + ActiveRpcHandle: PVOID, + ThreadLocalStoragePointer: PVOID, ProcessEnvironmentBlock: *PEB, Reserved2: [399]PVOID, Reserved3: [1952]u8, @@ -4321,6 +4343,25 @@ pub const TEB = extern struct { TlsExpansionSlots: PVOID, }; +comptime { + // Offsets taken from WinDbg info and Geoff Chappell[1] (RIP) + // [1]: https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/pebteb/teb/index.htm + assert(@offsetOf(TEB, "NtTib") == 0x00); + if (@sizeOf(usize) == 4) { + assert(@offsetOf(TEB, "EnvironmentPointer") == 0x1C); + assert(@offsetOf(TEB, "ClientId") == 0x20); + assert(@offsetOf(TEB, "ActiveRpcHandle") == 0x28); + assert(@offsetOf(TEB, "ThreadLocalStoragePointer") == 0x2C); + assert(@offsetOf(TEB, "ProcessEnvironmentBlock") == 0x30); + } else if (@sizeOf(usize) == 8) { + assert(@offsetOf(TEB, "EnvironmentPointer") == 0x38); + assert(@offsetOf(TEB, "ClientId") == 0x40); + assert(@offsetOf(TEB, "ActiveRpcHandle") == 0x50); + assert(@offsetOf(TEB, "ThreadLocalStoragePointer") == 0x58); + assert(@offsetOf(TEB, "ProcessEnvironmentBlock") == 0x60); + } +} + pub const EXCEPTION_REGISTRATION_RECORD = extern struct { Next: ?*EXCEPTION_REGISTRATION_RECORD, Handler: ?*EXCEPTION_DISPOSITION,