10166
10167
10168
10169
10170
10171
10172
10173
10174
10175
10176
10177
10178
10179
10180
10181
10182
10183
10184
10185
10186
10187
10188
10189
10190
10191
10192
10193
10194
10195
10196
10197
10198
10199
10200
10201
10202
10203
10204
10205
10206
10207
10208
10209
10210
10211
10212
10213
10214
10215
10216
10217
10218
10219
10220
10221
10222
10223
10224
10225
10226
fn readFilePositionalWindows(file: File, buffer: []u8, offset: u64) File.ReadPositionalError!usize {
var iosb: windows.IO_STATUS_BLOCK = undefined;
const short_buffer_len = std.math.lossyCast(u32, buffer.len);
const signed_offset: windows.LARGE_INTEGER = @intCast(offset);
if (file.flags.nonblocking) {
var done: bool = false;
switch (windows.ntdll.NtReadFile(
file.handle,
null, // event
flagApc,
&done, // APC context
&iosb,
buffer.ptr,
short_buffer_len,
&signed_offset,
null, // key
)) {
// We must wait for the APC routine.
.PENDING, .SUCCESS => while (!done) {
// Once we get here we must not return from the function until the
// operation completes, thereby releasing reference to the iosb.
const alertable_syscall = AlertableSyscall.start() catch |err| switch (err) {
error.Canceled => |e| {
var cancel_iosb: windows.IO_STATUS_BLOCK = undefined;
_ = windows.ntdll.NtCancelIoFileEx(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 (windows.ntdll.NtReadFile(
file.handle,
null, // event
null, // APC routine
null, // APC context
&iosb,
buffer.ptr,
short_buffer_len,
&signed_offset,
null, // key
)) {
.PENDING => unreachable, // unrecoverable: wrong File nonblocking flag
.CANCELLED => try syscall.checkCancel(),
else => |status| {
syscall.finish();
iosb.u.Status = status;
break;
},
};
}
return ntReadFileResult(&iosb) catch |err| switch (err) {
error.EndOfStream => 0,
else => |e| e,
};
}