mirror of
https://github.com/ziglang/zig.git
synced 2026-02-20 16:24:51 +00:00
std.Io.Threaded: fix compilation failures on Windows
This commit is contained in:
parent
aadd8d4a3e
commit
d257b1337a
@ -220,8 +220,14 @@ pub fn io(t: *Threaded) Io {
|
||||
.fileClose = fileClose,
|
||||
.fileWriteStreaming = fileWriteStreaming,
|
||||
.fileWritePositional = fileWritePositional,
|
||||
.fileReadStreaming = fileReadStreaming,
|
||||
.fileReadPositional = fileReadPositional,
|
||||
.fileReadStreaming = switch (builtin.os.tag) {
|
||||
.windows => fileReadStreamingWindows,
|
||||
else => fileReadStreamingPosix,
|
||||
},
|
||||
.fileReadPositional = switch (builtin.os.tag) {
|
||||
.windows => fileReadPositionalWindows,
|
||||
else => fileReadPositionalPosix,
|
||||
},
|
||||
.fileSeekBy = fileSeekBy,
|
||||
.fileSeekTo = fileSeekTo,
|
||||
.openSelfExe = openSelfExe,
|
||||
@ -258,15 +264,21 @@ pub fn io(t: *Threaded) Io {
|
||||
.netConnectUnix = netConnectUnix,
|
||||
.netClose = netClose,
|
||||
.netRead = switch (builtin.os.tag) {
|
||||
.windows => @panic("TODO"),
|
||||
.windows => netReadWindows,
|
||||
else => netReadPosix,
|
||||
},
|
||||
.netWrite = switch (builtin.os.tag) {
|
||||
.windows => @panic("TODO"),
|
||||
.windows => netWriteWindows,
|
||||
else => netWritePosix,
|
||||
},
|
||||
.netSend = netSend,
|
||||
.netReceive = netReceive,
|
||||
.netSend = switch (builtin.os.tag) {
|
||||
.windows => netSendWindows,
|
||||
else => netSendPosix,
|
||||
},
|
||||
.netReceive = switch (builtin.os.tag) {
|
||||
.windows => netReceiveWindows,
|
||||
else => netReceivePosix,
|
||||
},
|
||||
.netInterfaceNameResolve = netInterfaceNameResolve,
|
||||
.netInterfaceName = netInterfaceName,
|
||||
.netLookup = netLookup,
|
||||
@ -284,6 +296,10 @@ const have_futex = switch (builtin.cpu.arch) {
|
||||
.wasm32, .wasm64 => builtin.cpu.has(.wasm, .atomics),
|
||||
else => true,
|
||||
};
|
||||
const have_preadv = switch (native_os) {
|
||||
.windows, .haiku, .serenity => false, // 💩💩💩
|
||||
else => true,
|
||||
};
|
||||
|
||||
const openat_sym = if (posix.lfs64_abi) posix.system.openat64 else posix.system.openat;
|
||||
const fstat_sym = if (posix.lfs64_abi) posix.system.fstat64 else posix.system.fstat;
|
||||
@ -1899,12 +1915,19 @@ fn dirOpenFileWindows(
|
||||
flags: Io.File.OpenFlags,
|
||||
) Io.File.OpenError!Io.File {
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
try t.checkCancel();
|
||||
|
||||
const w = windows;
|
||||
const sub_path_w_array = try w.sliceToPrefixedFileW(dir.handle, sub_path);
|
||||
const sub_path_w_array = try windows.sliceToPrefixedFileW(dir.handle, sub_path);
|
||||
const sub_path_w = sub_path_w_array.span();
|
||||
return dirOpenFileWindowsInner(t, dir, sub_path_w, flags);
|
||||
}
|
||||
|
||||
fn dirOpenFileWindowsInner(
|
||||
t: *Threaded,
|
||||
dir: Io.Dir,
|
||||
sub_path_w: [:0]const u16,
|
||||
flags: Io.File.OpenFlags,
|
||||
) Io.File.OpenError!Io.File {
|
||||
try t.checkCancel();
|
||||
const w = windows;
|
||||
const handle = try w.OpenFile(sub_path_w, .{
|
||||
.dir = dir.handle,
|
||||
.access_mask = w.SYNCHRONIZE |
|
||||
@ -2247,47 +2270,9 @@ fn fileClose(userdata: ?*anyopaque, file: Io.File) void {
|
||||
posix.close(file.handle);
|
||||
}
|
||||
|
||||
fn fileReadStreaming(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File.ReadStreamingError!usize {
|
||||
fn fileReadStreamingPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File.ReadStreamingError!usize {
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
|
||||
if (is_windows) {
|
||||
const DWORD = windows.DWORD;
|
||||
var index: usize = 0;
|
||||
var truncate: usize = 0;
|
||||
var total: usize = 0;
|
||||
while (index < data.len) {
|
||||
try t.checkCancel();
|
||||
{
|
||||
const untruncated = data[index];
|
||||
data[index] = untruncated[truncate..];
|
||||
defer data[index] = untruncated;
|
||||
const buffer = data[index..];
|
||||
const want_read_count: DWORD = @min(std.math.maxInt(DWORD), buffer.len);
|
||||
var n: DWORD = undefined;
|
||||
if (windows.kernel32.ReadFile(file.handle, buffer.ptr, want_read_count, &n, null) == 0) {
|
||||
switch (windows.GetLastError()) {
|
||||
.IO_PENDING => |err| return windows.statusBug(err),
|
||||
.OPERATION_ABORTED => continue,
|
||||
.BROKEN_PIPE => return 0,
|
||||
.HANDLE_EOF => return 0,
|
||||
.NETNAME_DELETED => return error.ConnectionResetByPeer,
|
||||
.LOCK_VIOLATION => return error.LockViolation,
|
||||
.ACCESS_DENIED => return error.AccessDenied,
|
||||
.INVALID_HANDLE => return error.NotOpenForReading,
|
||||
else => |err| return windows.unexpectedError(err),
|
||||
}
|
||||
}
|
||||
total += n;
|
||||
truncate += n;
|
||||
}
|
||||
while (index < data.len and truncate >= data[index].len) {
|
||||
truncate -= data[index].len;
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined;
|
||||
var i: usize = 0;
|
||||
for (data) |buf| {
|
||||
@ -2348,70 +2333,37 @@ fn fileReadStreaming(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File
|
||||
}
|
||||
}
|
||||
|
||||
fn fileReadPositional(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset: u64) Io.File.ReadPositionalError!usize {
|
||||
fn fileReadStreamingWindows(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File.ReadStreamingError!usize {
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
try t.checkCancel();
|
||||
|
||||
const DWORD = windows.DWORD;
|
||||
var index: usize = 0;
|
||||
while (data[index].len == 0) index += 1;
|
||||
|
||||
const buffer = data[index];
|
||||
const want_read_count: DWORD = @min(std.math.maxInt(DWORD), buffer.len);
|
||||
var n: DWORD = undefined;
|
||||
if (windows.kernel32.ReadFile(file.handle, buffer.ptr, want_read_count, &n, null) == 0) {
|
||||
switch (windows.GetLastError()) {
|
||||
.IO_PENDING => |err| return windows.errorBug(err),
|
||||
.OPERATION_ABORTED => return error.Canceled,
|
||||
.BROKEN_PIPE => return 0,
|
||||
.HANDLE_EOF => return 0,
|
||||
.NETNAME_DELETED => return error.ConnectionResetByPeer,
|
||||
.LOCK_VIOLATION => return error.LockViolation,
|
||||
.ACCESS_DENIED => return error.AccessDenied,
|
||||
.INVALID_HANDLE => return error.NotOpenForReading,
|
||||
else => |err| return windows.unexpectedError(err),
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
fn fileReadPositionalPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset: u64) Io.File.ReadPositionalError!usize {
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
|
||||
if (is_windows) {
|
||||
const DWORD = windows.DWORD;
|
||||
const OVERLAPPED = windows.OVERLAPPED;
|
||||
var index: usize = 0;
|
||||
var truncate: usize = 0;
|
||||
var total: usize = 0;
|
||||
while (true) {
|
||||
try t.checkCancel();
|
||||
{
|
||||
const untruncated = data[index];
|
||||
data[index] = untruncated[truncate..];
|
||||
defer data[index] = untruncated;
|
||||
const buffer = data[index..];
|
||||
const want_read_count: DWORD = @min(std.math.maxInt(DWORD), buffer.len);
|
||||
var n: DWORD = undefined;
|
||||
var overlapped_data: OVERLAPPED = undefined;
|
||||
const overlapped: ?*OVERLAPPED = if (offset) |off| blk: {
|
||||
overlapped_data = .{
|
||||
.Internal = 0,
|
||||
.InternalHigh = 0,
|
||||
.DUMMYUNIONNAME = .{
|
||||
.DUMMYSTRUCTNAME = .{
|
||||
.Offset = @as(u32, @truncate(off)),
|
||||
.OffsetHigh = @as(u32, @truncate(off >> 32)),
|
||||
},
|
||||
},
|
||||
.hEvent = null,
|
||||
};
|
||||
break :blk &overlapped_data;
|
||||
} else null;
|
||||
if (windows.kernel32.ReadFile(file.handle, buffer.ptr, want_read_count, &n, overlapped) == 0) {
|
||||
switch (windows.GetLastError()) {
|
||||
.IO_PENDING => |err| return windows.statusBug(err),
|
||||
.OPERATION_ABORTED => continue,
|
||||
.BROKEN_PIPE => return 0,
|
||||
.HANDLE_EOF => return 0,
|
||||
.NETNAME_DELETED => return error.ConnectionResetByPeer,
|
||||
.LOCK_VIOLATION => return error.LockViolation,
|
||||
.ACCESS_DENIED => return error.AccessDenied,
|
||||
.INVALID_HANDLE => return error.NotOpenForReading,
|
||||
else => |err| return windows.unexpectedError(err),
|
||||
}
|
||||
}
|
||||
total += n;
|
||||
truncate += n;
|
||||
}
|
||||
while (index < data.len and truncate >= data[index].len) {
|
||||
truncate -= data[index].len;
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
const have_pread_but_not_preadv = switch (native_os) {
|
||||
.windows, .haiku, .serenity => true,
|
||||
else => false,
|
||||
};
|
||||
if (have_pread_but_not_preadv) {
|
||||
@compileError("TODO");
|
||||
}
|
||||
if (!have_preadv) @compileError("TODO");
|
||||
|
||||
var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined;
|
||||
var i: usize = 0;
|
||||
@ -2480,6 +2432,48 @@ fn fileReadPositional(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset
|
||||
}
|
||||
}
|
||||
|
||||
fn fileReadPositionalWindows(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset: u64) Io.File.ReadPositionalError!usize {
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
try t.checkCancel();
|
||||
|
||||
const DWORD = windows.DWORD;
|
||||
const OVERLAPPED = windows.OVERLAPPED;
|
||||
|
||||
var index: usize = 0;
|
||||
while (data[index].len == 0) index += 1;
|
||||
|
||||
const buffer = data[index];
|
||||
const want_read_count: DWORD = @min(std.math.maxInt(DWORD), buffer.len);
|
||||
var n: DWORD = undefined;
|
||||
var overlapped: OVERLAPPED = .{
|
||||
.Internal = 0,
|
||||
.InternalHigh = 0,
|
||||
.DUMMYUNIONNAME = .{
|
||||
.DUMMYSTRUCTNAME = .{
|
||||
.Offset = @as(u32, @truncate(offset)),
|
||||
.OffsetHigh = @as(u32, @truncate(offset >> 32)),
|
||||
},
|
||||
},
|
||||
.hEvent = null,
|
||||
};
|
||||
|
||||
if (windows.kernel32.ReadFile(file.handle, buffer.ptr, want_read_count, &n, &overlapped) == 0) {
|
||||
switch (windows.GetLastError()) {
|
||||
.IO_PENDING => |err| return windows.errorBug(err),
|
||||
.OPERATION_ABORTED => return error.Canceled,
|
||||
.BROKEN_PIPE => return 0,
|
||||
.HANDLE_EOF => return 0,
|
||||
.NETNAME_DELETED => return error.ConnectionResetByPeer,
|
||||
.LOCK_VIOLATION => return error.LockViolation,
|
||||
.ACCESS_DENIED => return error.AccessDenied,
|
||||
.INVALID_HANDLE => return error.NotOpenForReading,
|
||||
else => |err| return windows.unexpectedError(err),
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
fn fileSeekBy(userdata: ?*anyopaque, file: Io.File, offset: i64) Io.File.SeekError!void {
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
try t.checkCancel();
|
||||
@ -2563,11 +2557,9 @@ fn openSelfExe(userdata: ?*anyopaque, flags: Io.File.OpenFlags) Io.File.OpenSelf
|
||||
// the file, we can let the openFileW call follow the symlink for us.
|
||||
const image_path_unicode_string = &windows.peb().ProcessParameters.ImagePathName;
|
||||
const image_path_name = image_path_unicode_string.Buffer.?[0 .. image_path_unicode_string.Length / 2 :0];
|
||||
const prefixed_path_w_array = try windows.wToPrefixedFileW(null, image_path_name);
|
||||
const prefixed_path_w = prefixed_path_w_array.span();
|
||||
const cwd_handle = std.os.windows.peb().ProcessParameters.CurrentDirectory.Handle;
|
||||
|
||||
return dirOpenFileWindows(t, .{ .handle = cwd_handle }, prefixed_path_w, flags);
|
||||
return dirOpenFileWindowsInner(t, .{ .handle = cwd_handle }, image_path_name, flags);
|
||||
}
|
||||
@panic("TODO");
|
||||
}
|
||||
@ -3493,7 +3485,16 @@ fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.
|
||||
}
|
||||
}
|
||||
|
||||
fn netSend(
|
||||
fn netReadWindows(userdata: ?*anyopaque, handle: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize {
|
||||
if (!have_networking) return .{ error.NetworkDown, 0 };
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
_ = t;
|
||||
_ = handle;
|
||||
_ = data;
|
||||
@panic("TODO");
|
||||
}
|
||||
|
||||
fn netSendPosix(
|
||||
userdata: ?*anyopaque,
|
||||
handle: net.Socket.Handle,
|
||||
messages: []net.OutgoingMessage,
|
||||
@ -3504,9 +3505,9 @@ fn netSend(
|
||||
|
||||
const posix_flags: u32 =
|
||||
@as(u32, if (@hasDecl(posix.MSG, "CONFIRM") and flags.confirm) posix.MSG.CONFIRM else 0) |
|
||||
@as(u32, if (flags.dont_route) posix.MSG.DONTROUTE else 0) |
|
||||
@as(u32, if (flags.eor) posix.MSG.EOR else 0) |
|
||||
@as(u32, if (flags.oob) posix.MSG.OOB else 0) |
|
||||
@as(u32, if (@hasDecl(posix.MSG, "DONTROUTE") and flags.dont_route) posix.MSG.DONTROUTE else 0) |
|
||||
@as(u32, if (@hasDecl(posix.MSG, "EOR") and flags.eor) posix.MSG.EOR else 0) |
|
||||
@as(u32, if (@hasDecl(posix.MSG, "OOB") and flags.oob) posix.MSG.OOB else 0) |
|
||||
@as(u32, if (@hasDecl(posix.MSG, "FASTOPEN") and flags.fastopen) posix.MSG.FASTOPEN else 0) |
|
||||
posix.MSG.NOSIGNAL;
|
||||
|
||||
@ -3522,6 +3523,21 @@ fn netSend(
|
||||
return .{ null, i };
|
||||
}
|
||||
|
||||
fn netSendWindows(
|
||||
userdata: ?*anyopaque,
|
||||
handle: net.Socket.Handle,
|
||||
messages: []net.OutgoingMessage,
|
||||
flags: net.SendFlags,
|
||||
) struct { ?net.Socket.SendError, usize } {
|
||||
if (!have_networking) return .{ error.NetworkDown, 0 };
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
_ = t;
|
||||
_ = handle;
|
||||
_ = messages;
|
||||
_ = flags;
|
||||
@panic("TODO");
|
||||
}
|
||||
|
||||
fn netSendOne(
|
||||
t: *Threaded,
|
||||
handle: net.Socket.Handle,
|
||||
@ -3676,7 +3692,7 @@ fn netSendMany(
|
||||
}
|
||||
}
|
||||
|
||||
fn netReceive(
|
||||
fn netReceivePosix(
|
||||
userdata: ?*anyopaque,
|
||||
handle: net.Socket.Handle,
|
||||
message_buffer: []net.IncomingMessage,
|
||||
@ -3805,6 +3821,25 @@ fn netReceive(
|
||||
}
|
||||
}
|
||||
|
||||
fn netReceiveWindows(
|
||||
userdata: ?*anyopaque,
|
||||
handle: net.Socket.Handle,
|
||||
message_buffer: []net.IncomingMessage,
|
||||
data_buffer: []u8,
|
||||
flags: net.ReceiveFlags,
|
||||
timeout: Io.Timeout,
|
||||
) struct { ?net.Socket.ReceiveTimeoutError, usize } {
|
||||
if (!have_networking) return .{ error.NetworkDown, 0 };
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
_ = t;
|
||||
_ = handle;
|
||||
_ = message_buffer;
|
||||
_ = data_buffer;
|
||||
_ = flags;
|
||||
_ = timeout;
|
||||
@panic("TODO");
|
||||
}
|
||||
|
||||
fn netWritePosix(
|
||||
userdata: ?*anyopaque,
|
||||
fd: net.Socket.Handle,
|
||||
@ -3887,6 +3922,22 @@ fn netWritePosix(
|
||||
}
|
||||
}
|
||||
|
||||
fn netWriteWindows(
|
||||
userdata: ?*anyopaque,
|
||||
handle: net.Socket.Handle,
|
||||
header: []const u8,
|
||||
data: []const []const u8,
|
||||
splat: usize,
|
||||
) net.Stream.Writer.Error!usize {
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
_ = t;
|
||||
_ = handle;
|
||||
_ = header;
|
||||
_ = data;
|
||||
_ = splat;
|
||||
@panic("TODO");
|
||||
}
|
||||
|
||||
fn addBuf(v: []posix.iovec_const, i: *@FieldType(posix.msghdr_const, "iovlen"), bytes: []const u8) void {
|
||||
// OS checks ptr addr before length so zero length vectors must be omitted.
|
||||
if (bytes.len == 0) return;
|
||||
@ -3899,7 +3950,7 @@ fn netClose(userdata: ?*anyopaque, handle: net.Socket.Handle) void {
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
_ = t;
|
||||
switch (native_os) {
|
||||
.windows => closeSocketWindows(handle) catch recoverableOsBugDetected(),
|
||||
.windows => closeSocketWindows(handle),
|
||||
else => posix.close(handle),
|
||||
}
|
||||
}
|
||||
@ -4559,7 +4610,7 @@ fn lookupDns(
|
||||
message_i += 1;
|
||||
}
|
||||
}
|
||||
_ = netSend(t, socket.handle, message_buffer[0..message_i], .{});
|
||||
_ = netSendPosix(t, socket.handle, message_buffer[0..message_i], .{});
|
||||
}
|
||||
|
||||
const timeout: Io.Timeout = .{ .deadline = .{
|
||||
@ -4607,7 +4658,7 @@ fn lookupDns(
|
||||
.data_ptr = query.ptr,
|
||||
.data_len = query.len,
|
||||
};
|
||||
_ = netSend(t, socket.handle, (&retry_message)[0..1], .{});
|
||||
_ = netSendPosix(t, socket.handle, (&retry_message)[0..1], .{});
|
||||
continue;
|
||||
},
|
||||
else => continue,
|
||||
@ -5157,9 +5208,9 @@ fn closeSocketWindows(s: ws2_32.SOCKET) void {
|
||||
if (builtin.mode == .Debug) switch (rc) {
|
||||
0 => {},
|
||||
ws2_32.SOCKET_ERROR => switch (ws2_32.WSAGetLastError()) {
|
||||
else => unreachable,
|
||||
else => recoverableOsBugDetected(),
|
||||
},
|
||||
else => unreachable,
|
||||
else => recoverableOsBugDetected(),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -186,15 +186,6 @@ test "listen on a port, send bytes, receive bytes" {
|
||||
|
||||
const io = testing.io;
|
||||
|
||||
if (builtin.os.tag == .windows) {
|
||||
_ = try std.os.windows.WSAStartup(2, 2);
|
||||
}
|
||||
defer {
|
||||
if (builtin.os.tag == .windows) {
|
||||
std.os.windows.WSACleanup() catch unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
// Try only the IPv4 variant as some CI builders have no IPv6 localhost
|
||||
// configured.
|
||||
const localhost: net.IpAddress = .{ .ip4 = .loopback(0) };
|
||||
@ -282,15 +273,6 @@ test "listen on a unix socket, send bytes, receive bytes" {
|
||||
|
||||
const io = testing.io;
|
||||
|
||||
if (builtin.os.tag == .windows) {
|
||||
_ = try std.os.windows.WSAStartup(2, 2);
|
||||
}
|
||||
defer {
|
||||
if (builtin.os.tag == .windows) {
|
||||
std.os.windows.WSACleanup() catch unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
const socket_path = try generateFileName("socket.unix");
|
||||
defer testing.allocator.free(socket_path);
|
||||
|
||||
|
||||
@ -144,10 +144,12 @@ fn rescanWithPath(cb: *Bundle, gpa: Allocator, io: Io, now: Io.Timestamp, cert_f
|
||||
|
||||
const RescanWindowsError = Allocator.Error || ParseCertError || std.posix.UnexpectedError || error{FileNotFound};
|
||||
|
||||
fn rescanWindows(cb: *Bundle, gpa: Allocator) RescanWindowsError!void {
|
||||
fn rescanWindows(cb: *Bundle, gpa: Allocator, io: Io, now: Io.Timestamp) RescanWindowsError!void {
|
||||
cb.bytes.clearRetainingCapacity();
|
||||
cb.map.clearRetainingCapacity();
|
||||
|
||||
_ = io;
|
||||
|
||||
const w = std.os.windows;
|
||||
const GetLastError = w.GetLastError;
|
||||
const root = [4:0]u16{ 'R', 'O', 'O', 'T' };
|
||||
@ -157,7 +159,7 @@ fn rescanWindows(cb: *Bundle, gpa: Allocator) RescanWindowsError!void {
|
||||
};
|
||||
defer _ = w.crypt32.CertCloseStore(store, 0);
|
||||
|
||||
const now_sec = std.time.timestamp();
|
||||
const now_sec = now.toSeconds();
|
||||
|
||||
var ctx = w.crypt32.CertEnumCertificatesInStore(store, null);
|
||||
while (ctx) |context| : (ctx = w.crypt32.CertEnumCertificatesInStore(store, ctx)) {
|
||||
|
||||
@ -2735,6 +2735,13 @@ pub fn statusBug(status: NTSTATUS) UnexpectedError {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn errorBug(err: Win32Error) UnexpectedError {
|
||||
switch (builtin.mode) {
|
||||
.Debug => std.debug.panic("programmer bug caused syscall status: {t}", .{err}),
|
||||
else => return error.Unexpected,
|
||||
}
|
||||
}
|
||||
|
||||
pub const Win32Error = @import("windows/win32error.zig").Win32Error;
|
||||
pub const NTSTATUS = @import("windows/ntstatus.zig").NTSTATUS;
|
||||
pub const LANG = @import("windows/lang.zig");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user