feature. See also
. The project being documented here (as the example) is the Zig library itself.
Threaded.deviceIoControl
fn deviceIoControl(o: *const Io.Operation.DeviceIoControl) Io.Cancelable!Io.Operation.DeviceIoControl.Result
File
Code
fn deviceIoControl(o: *const Io.Operation.DeviceIoControl) Io.Cancelable!Io.Operation.DeviceIoControl.Result {
if (is_windows) {
const NtControlFile = switch (o.code.DeviceType) {
.FILE_SYSTEM, .NAMED_PIPE => &windows.ntdll.NtFsControlFile,
else => &windows.ntdll.NtDeviceIoControlFile,
};
var iosb: windows.IO_STATUS_BLOCK = undefined;
if (o.file.flags.nonblocking) {
var done: bool = false;
switch (NtControlFile(
o.file.handle,
null,
flagApc,
&done,
&iosb,
o.code,
if (o.in.len > 0) o.in.ptr else null,
@intCast(o.in.len),
if (o.out.len > 0) o.out.ptr else null,
@intCast(o.out.len),
)) {
.PENDING, .SUCCESS => while (!done) {
// operation completes, thereby releasing reference to io_status_block.
const alertable_syscall = AlertableSyscall.start() catch |err| switch (err) {
error.Canceled => |e| {
var cancel_iosb: windows.IO_STATUS_BLOCK = undefined;
_ = windows.ntdll.NtCancelIoFileEx(o.file.handle, &iosb, &cancel_iosb);
while (!done) waitForApcOrAlert();
return e;
},
};
waitForApcOrAlert();
alertable_syscall.finish();
},
else => |status| iosb.u.Status = status,
}
} else {
const syscall: Syscall = try .start();
while (true) switch (NtControlFile(
o.file.handle,
null,
null,
null,
&iosb,
o.code,
if (o.in.len > 0) o.in.ptr else null,
@intCast(o.in.len),
if (o.out.len > 0) o.out.ptr else null,
@intCast(o.out.len),
)) {
.PENDING => unreachable,
.CANCELLED => {
try syscall.checkCancel();
continue;
},
else => |status| {
syscall.finish();
iosb.u.Status = status;
break;
},
};
}
return iosb;
} else {
const syscall: Syscall = try .start();
while (true) {
const rc = posix.system.ioctl(o.file.handle, @bitCast(o.code), @intFromPtr(o.arg));
switch (posix.errno(rc)) {
.SUCCESS => {
syscall.finish();
if (@TypeOf(rc) == usize) return @bitCast(@as(u32, @truncate(rc)));
return rc;
},
.INTR => {
try syscall.checkCancel();
continue;
},
else => |err| {
syscall.finish();
return -@as(i32, @backingInt(err));
},
}
}
}
}