Replace DeviceIoControl with FsControlFile

This commit replaces `windows.DeviceIoControl` with
`windows.FsControlFile` which is a wrapper around the NT-based
syscall `ntdll.NtFsControlFile`.
master
Jakub Konka 2020-07-27 17:08:25 +02:00 committed by Andrew Kelley
parent d1755e7f16
commit f0ed2ed67f
2 changed files with 35 additions and 20 deletions

View File

@ -215,30 +215,34 @@ pub fn CreateEventExW(attributes: ?*SECURITY_ATTRIBUTES, nameW: [*:0]const u16,
} }
} }
pub fn DeviceIoControl( pub const FsControlFileError = error{Unexpected};
// TODO work out if we need to expose other arguments to the underlying
// NtFsControlFile syscall
pub fn FsControlFile(
h: HANDLE, h: HANDLE,
ioControlCode: DWORD, fsControlCode: ULONG,
in: ?[]const u8, in: ?[]const u8,
out: ?[]u8, out: ?[]u8,
overlapped: ?*OVERLAPPED, ) FsControlFileError!void {
) !DWORD { var io: IO_STATUS_BLOCK = undefined;
var bytes: DWORD = undefined; const rc = ntdll.NtFsControlFile(
if (kernel32.DeviceIoControl(
h, h,
ioControlCode, null,
null,
null,
&io,
fsControlCode,
if (in) |i| i.ptr else null, if (in) |i| i.ptr else null,
if (in) |i| @intCast(u32, i.len) else 0, if (in) |i| @intCast(ULONG, i.len) else 0,
if (out) |o| o.ptr else null, if (out) |o| o.ptr else null,
if (out) |o| @intCast(u32, o.len) else 0, if (out) |o| @intCast(ULONG, o.len) else 0,
&bytes, );
overlapped, switch (rc) {
) == 0) { .SUCCESS => {},
switch (kernel32.GetLastError()) { .INVALID_PARAMETER => unreachable,
.IO_PENDING => if (overlapped == null) unreachable, else => return unexpectedStatus(rc),
else => |err| return unexpectedError(err),
}
} }
return bytes;
} }
pub fn GetOverlappedResult(h: HANDLE, overlapped: *OVERLAPPED, wait: bool) !DWORD { pub fn GetOverlappedResult(h: HANDLE, overlapped: *OVERLAPPED, wait: bool) !DWORD {
@ -727,8 +731,7 @@ pub fn CreateSymbolicLinkW(
@memcpy(buffer[@sizeOf(SYMLINK_DATA)..], @ptrCast([*]const u8, target_path), target_path.len * 2); @memcpy(buffer[@sizeOf(SYMLINK_DATA)..], @ptrCast([*]const u8, target_path), target_path.len * 2);
const paths_start = @sizeOf(SYMLINK_DATA) + target_path.len * 2; const paths_start = @sizeOf(SYMLINK_DATA) + target_path.len * 2;
@memcpy(buffer[paths_start..].ptr, @ptrCast([*]const u8, target_path), target_path.len * 2); @memcpy(buffer[paths_start..].ptr, @ptrCast([*]const u8, target_path), target_path.len * 2);
// TODO replace with NtDeviceIoControl _ = try FsControlFile(symlink_handle, FSCTL_SET_REPARSE_POINT, buffer[0..buf_len], null);
_ = try DeviceIoControl(symlink_handle, FSCTL_SET_REPARSE_POINT, buffer[0..buf_len], null, null);
} }
pub const ReadLinkError = error{ pub const ReadLinkError = error{
@ -806,7 +809,7 @@ pub fn ReadLinkW(dir: ?HANDLE, sub_path_w: [*:0]const u16, out_buffer: []u8) Rea
defer CloseHandle(result_handle); defer CloseHandle(result_handle);
var reparse_buf: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined; var reparse_buf: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined;
_ = try DeviceIoControl(result_handle, FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..], null); _ = try FsControlFile(result_handle, FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..]);
const reparse_struct = @ptrCast(*const REPARSE_DATA_BUFFER, @alignCast(@alignOf(REPARSE_DATA_BUFFER), &reparse_buf[0])); const reparse_struct = @ptrCast(*const REPARSE_DATA_BUFFER, @alignCast(@alignOf(REPARSE_DATA_BUFFER), &reparse_buf[0]));
switch (reparse_struct.ReparseTag) { switch (reparse_struct.ReparseTag) {

View File

@ -54,6 +54,18 @@ pub extern "NtDll" fn NtDeviceIoControlFile(
OutputBuffer: ?PVOID, OutputBuffer: ?PVOID,
OutputBufferLength: ULONG, OutputBufferLength: ULONG,
) callconv(.Stdcall) NTSTATUS; ) callconv(.Stdcall) NTSTATUS;
pub extern "NtDll" fn NtFsControlFile(
FileHandle: HANDLE,
Event: ?HANDLE,
ApcRoutine: ?IO_APC_ROUTINE,
ApcContext: ?*c_void,
IoStatusBlock: *IO_STATUS_BLOCK,
FsControlCode: ULONG,
InputBuffer: ?*const c_void,
InputBufferLength: ULONG,
OutputBuffer: ?PVOID,
OutputBufferLength: ULONG,
) callconv(.Stdcall) NTSTATUS;
pub extern "NtDll" fn NtClose(Handle: HANDLE) callconv(.Stdcall) NTSTATUS; pub extern "NtDll" fn NtClose(Handle: HANDLE) callconv(.Stdcall) NTSTATUS;
pub extern "NtDll" fn RtlDosPathNameToNtPathName_U( pub extern "NtDll" fn RtlDosPathNameToNtPathName_U(
DosPathName: [*:0]const u16, DosPathName: [*:0]const u16,