Skip to content

Commit

Permalink
Windows: Add wrappers for GetCurrent(Process|Thread) via NT_TIB
Browse files Browse the repository at this point in the history
This is how they've been implemented in `kernel32` since NT 3.1.
  • Loading branch information
The-King-of-Toasters committed Mar 15, 2024
1 parent 852f0f3 commit f326e86
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 3 deletions.
2 changes: 1 addition & 1 deletion lib/std/child_process.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion lib/std/debug.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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| {
Expand Down
43 changes: 42 additions & 1 deletion lib/std/os/windows.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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 process_pseudo_thread: usize = @bitCast(@as(isize, -2));
return @ptrFromInt(process_pseudo_thread);
}

pub fn GetCurrentThreadId() HANDLE {
return teb().ClientId.UniqueThread;
}

pub const CreatePipeError = error{ Unexpected, SystemResources };

/// A Zig wrapper around `NtCreateNamedPipeFile` and `NtCreateFile` syscalls.
Expand Down Expand Up @@ -4296,7 +4314,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,
Expand All @@ -4308,6 +4330,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,
Expand Down

0 comments on commit f326e86

Please sign in to comment.