|
4 | 4 |
|
5 | 5 | const std = @import("std.zig");
|
6 | 6 | const builtin = @import("builtin");
|
| 7 | +const math = std.math; |
7 | 8 | const os = std.os;
|
8 | 9 | const assert = std.debug.assert;
|
9 | 10 | const target = builtin.target;
|
@@ -85,23 +86,28 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void {
|
85 | 86 |
|
86 | 87 | try file.writer().writeAll(name);
|
87 | 88 | },
|
88 |
| - .windows => if (target.os.isAtLeast(.windows, .win10_rs1)) |res| { |
89 |
| - // SetThreadDescription is only available since version 1607, which is 10.0.14393.795 |
90 |
| - // See https://en.wikipedia.org/wiki/Microsoft_Windows_SDK |
91 |
| - if (!res) { |
92 |
| - return error.Unsupported; |
93 |
| - } |
94 |
| - |
95 |
| - var name_buf_w: [max_name_len:0]u16 = undefined; |
96 |
| - const length = try std.unicode.utf8ToUtf16Le(&name_buf_w, name); |
97 |
| - name_buf_w[length] = 0; |
| 89 | + .windows => { |
| 90 | + var buf: [max_name_len]u16 = undefined; |
| 91 | + const len = try std.unicode.utf8ToUtf16Le(&buf, name); |
| 92 | + const byte_len = math.cast(c_ushort, len * 2) catch return error.NameTooLong; |
| 93 | + |
| 94 | + // Note: The kernel allocates its own copy, no use-after-free here. |
| 95 | + const unicode_string = os.windows.UNICODE_STRING{ |
| 96 | + .Length = byte_len, |
| 97 | + .MaximumLength = byte_len, |
| 98 | + .Buffer = &buf, |
| 99 | + }; |
98 | 100 |
|
99 |
| - try os.windows.SetThreadDescription( |
| 101 | + switch (os.windows.ntdll.NtSetInformationThread( |
100 | 102 | self.getHandle(),
|
101 |
| - @ptrCast(os.windows.LPWSTR, &name_buf_w), |
102 |
| - ); |
103 |
| - } else { |
104 |
| - return error.Unsupported; |
| 103 | + .ThreadNameInformation, |
| 104 | + &unicode_string, |
| 105 | + @sizeOf(os.windows.UNICODE_STRING), |
| 106 | + )) { |
| 107 | + .SUCCESS => {}, |
| 108 | + .NOT_IMPLEMENTED => return error.Unsupported, |
| 109 | + else => |err| return os.windows.unexpectedStatus(err), |
| 110 | + } |
105 | 111 | },
|
106 | 112 | .macos, .ios, .watchos, .tvos => if (use_pthreads) {
|
107 | 113 | // There doesn't seem to be a way to set the name for an arbitrary thread, only the current one.
|
@@ -178,22 +184,25 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co
|
178 | 184 | // musl doesn't provide pthread_getname_np and there's no way to retrieve the thread id of an arbitrary thread.
|
179 | 185 | return error.Unsupported;
|
180 | 186 | },
|
181 |
| - .windows => if (target.os.isAtLeast(.windows, .win10_rs1)) |res| { |
182 |
| - // GetThreadDescription is only available since version 1607, which is 10.0.14393.795 |
183 |
| - // See https://en.wikipedia.org/wiki/Microsoft_Windows_SDK |
184 |
| - if (!res) { |
185 |
| - return error.Unsupported; |
186 |
| - } |
187 |
| - |
188 |
| - var name_w: os.windows.LPWSTR = undefined; |
189 |
| - try os.windows.GetThreadDescription(self.getHandle(), &name_w); |
190 |
| - defer os.windows.LocalFree(name_w); |
| 187 | + .windows => { |
| 188 | + const buf_capacity = @sizeOf(os.windows.UNICODE_STRING) + (@sizeOf(u16) * max_name_len); |
| 189 | + var buf: [buf_capacity]u8 align(@alignOf(os.windows.UNICODE_STRING)) = undefined; |
191 | 190 |
|
192 |
| - const data_len = try std.unicode.utf16leToUtf8(buffer, std.mem.sliceTo(name_w, 0)); |
193 |
| - |
194 |
| - return if (data_len >= 1) buffer[0..data_len] else null; |
195 |
| - } else { |
196 |
| - return error.Unsupported; |
| 191 | + switch (os.windows.ntdll.NtQueryInformationThread( |
| 192 | + self.getHandle(), |
| 193 | + .ThreadNameInformation, |
| 194 | + &buf, |
| 195 | + buf_capacity, |
| 196 | + null, |
| 197 | + )) { |
| 198 | + .SUCCESS => { |
| 199 | + const string = @ptrCast(*const os.windows.UNICODE_STRING, &buf); |
| 200 | + const len = try std.unicode.utf16leToUtf8(buffer, string.Buffer[0 .. string.Length / 2]); |
| 201 | + return if (len > 0) buffer[0..len] else null; |
| 202 | + }, |
| 203 | + .NOT_IMPLEMENTED => return error.Unsupported, |
| 204 | + else => |err| return os.windows.unexpectedStatus(err), |
| 205 | + } |
197 | 206 | },
|
198 | 207 | .macos, .ios, .watchos, .tvos => if (use_pthreads) {
|
199 | 208 | const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1);
|
|
0 commit comments