authorgravatar for dev@sgregoratto.meStephen Gregoratto <dev@sgregoratto.me> 2024-03-12 22:21:55+11:00
committergravatar for dev@sgregoratto.meStephen Gregoratto <dev@sgregoratto.me> 2024-03-16 23:37:50+11:00
log69175ad62f531327e9fd693c13890ca1d472a7a3
tree8f6a8b5f626cfca74a6973479bec61b441815db7
parent9532f729371d8142fb65c61794b7bd765cd82396

Windows: Add wrappers for `GetCurrent(Process|Thread)` via NT_TIB

This is how they've been implemented in `kernel32` since NT 3.1.

3 files changed, 46 insertions(+), 5 deletions(-)

lib/std/child_process.zig+1-1
...@@ -1420,7 +1420,7 @@ fn windowsMakeAsyncPipe(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *cons...@@ -1420,7 +1420,7 @@ fn windowsMakeAsyncPipe(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *cons
1420 const pipe_path = std.fmt.bufPrintZ(1420 const pipe_path = std.fmt.bufPrintZ(
1421 &tmp_buf,1421 &tmp_buf,
1422 "\\\\.\\pipe\\zig-childprocess-{d}-{d}",1422 "\\\\.\\pipe\\zig-childprocess-{d}-{d}",
1423 .{ windows.kernel32.GetCurrentProcessId(), pipe_name_counter.fetchAdd(1, .monotonic) },1423 .{ windows.GetCurrentProcessId(), pipe_name_counter.fetchAdd(1, .monotonic) },
1424 ) catch unreachable;1424 ) catch unreachable;
1425 const len = std.unicode.wtf8ToWtf16Le(&tmp_bufw, pipe_path) catch unreachable;1425 const len = std.unicode.wtf8ToWtf16Le(&tmp_bufw, pipe_path) catch unreachable;
1426 tmp_bufw[len] = 0;1426 tmp_bufw[len] = 0;
lib/std/debug.zig+1-1
...@@ -814,7 +814,7 @@ pub noinline fn walkStackWindows(addresses: []usize, existing_context: ?*const w...@@ -814,7 +814,7 @@ pub noinline fn walkStackWindows(addresses: []usize, existing_context: ?*const w
814 return windows.ntdll.RtlCaptureStackBackTrace(0, addresses.len, @as(**anyopaque, @ptrCast(addresses.ptr)), null);814 return windows.ntdll.RtlCaptureStackBackTrace(0, addresses.len, @as(**anyopaque, @ptrCast(addresses.ptr)), null);
815 }815 }
816816
817 const tib = @as(*const windows.NT_TIB, @ptrCast(&windows.teb().Reserved1));817 const tib = &windows.teb().NtTib;
818818
819 var context: windows.CONTEXT = undefined;819 var context: windows.CONTEXT = undefined;
820 if (existing_context) |context_ptr| {820 if (existing_context) |context_ptr| {
lib/std/os/windows.zig+44-3
...@@ -153,6 +153,24 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN...@@ -153,6 +153,24 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
153 }153 }
154}154}
155155
156pub fn GetCurrentProcess() HANDLE {
157 const process_pseudo_handle: usize = @bitCast(@as(isize, -1));
158 return @ptrFromInt(process_pseudo_handle);
159}
160
161pub fn GetCurrentProcessId() DWORD {
162 return @truncate(@intFromPtr(teb().ClientId.UniqueProcess));
163}
164
165pub fn GetCurrentThread() HANDLE {
166 const thread_pseudo_handle: usize = @bitCast(@as(isize, -2));
167 return @ptrFromInt(thread_pseudo_handle);
168}
169
170pub fn GetCurrentThreadId() DWORD {
171 return @truncate(@intFromPtr(teb().ClientId.UniqueThread));
172}
173
156pub const CreatePipeError = error{ Unexpected, SystemResources };174pub const CreatePipeError = error{ Unexpected, SystemResources };
157175
158var npfs: ?HANDLE = null;176var npfs: ?HANDLE = null;
...@@ -259,12 +277,12 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C...@@ -259,12 +277,12 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C
259 var write: HANDLE = undefined;277 var write: HANDLE = undefined;
260 switch (ntdll.NtCreateFile(278 switch (ntdll.NtCreateFile(
261 &write,279 &write,
262 FILE_GENERIC_WRITE,280 GENERIC_WRITE | SYNCHRONIZE | FILE_READ_ATTRIBUTES,
263 &attrs,281 &attrs,
264 &iosb,282 &iosb,
265 null,283 null,
266 0,284 0,
267 FILE_SHARE_READ,285 FILE_SHARE_READ | FILE_SHARE_WRITE,
268 FILE_OPEN,286 FILE_OPEN,
269 FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE,287 FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE,
270 null,288 null,
...@@ -4309,7 +4327,11 @@ pub const THREAD_BASIC_INFORMATION = extern struct {...@@ -4309,7 +4327,11 @@ pub const THREAD_BASIC_INFORMATION = extern struct {
4309};4327};
43104328
4311pub const TEB = extern struct {4329pub const TEB = extern struct {
4312 Reserved1: [12]PVOID,4330 NtTib: NT_TIB,
4331 EnvironmentPointer: PVOID,
4332 ClientId: CLIENT_ID,
4333 ActiveRpcHandle: PVOID,
4334 ThreadLocalStoragePointer: PVOID,
4313 ProcessEnvironmentBlock: *PEB,4335 ProcessEnvironmentBlock: *PEB,
4314 Reserved2: [399]PVOID,4336 Reserved2: [399]PVOID,
4315 Reserved3: [1952]u8,4337 Reserved3: [1952]u8,
...@@ -4321,6 +4343,25 @@ pub const TEB = extern struct {...@@ -4321,6 +4343,25 @@ pub const TEB = extern struct {
4321 TlsExpansionSlots: PVOID,4343 TlsExpansionSlots: PVOID,
4322};4344};
43234345
4346comptime {
4347 // Offsets taken from WinDbg info and Geoff Chappell[1] (RIP)
4348 // [1]: https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/pebteb/teb/index.htm
4349 assert(@offsetOf(TEB, "NtTib") == 0x00);
4350 if (@sizeOf(usize) == 4) {
4351 assert(@offsetOf(TEB, "EnvironmentPointer") == 0x1C);
4352 assert(@offsetOf(TEB, "ClientId") == 0x20);
4353 assert(@offsetOf(TEB, "ActiveRpcHandle") == 0x28);
4354 assert(@offsetOf(TEB, "ThreadLocalStoragePointer") == 0x2C);
4355 assert(@offsetOf(TEB, "ProcessEnvironmentBlock") == 0x30);
4356 } else if (@sizeOf(usize) == 8) {
4357 assert(@offsetOf(TEB, "EnvironmentPointer") == 0x38);
4358 assert(@offsetOf(TEB, "ClientId") == 0x40);
4359 assert(@offsetOf(TEB, "ActiveRpcHandle") == 0x50);
4360 assert(@offsetOf(TEB, "ThreadLocalStoragePointer") == 0x58);
4361 assert(@offsetOf(TEB, "ProcessEnvironmentBlock") == 0x60);
4362 }
4363}
4364
4324pub const EXCEPTION_REGISTRATION_RECORD = extern struct {4365pub const EXCEPTION_REGISTRATION_RECORD = extern struct {
4325 Next: ?*EXCEPTION_REGISTRATION_RECORD,4366 Next: ?*EXCEPTION_REGISTRATION_RECORD,
4326 Handler: ?*EXCEPTION_DISPOSITION,4367 Handler: ?*EXCEPTION_DISPOSITION,