authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-07-28 14:21:33+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-29 01:19:10+00:00
log4fdfaf69c8c55ebac4c5b3c00025c0ac51281b5b
treeb72a3971bb8ec0076ff94b19eab38e78586b41ee
parent606b6462ceaaeb2d993df684829a27db16eea18a

Add Zig wrapper for kernel32.DeviceIoControl

This commit adds a Zig wrapper for `kernel32.DeviceIoControl` which applies ReactOS logic for deciding whether to use `ntdll.NtDeviceIoControlFile` or `ntdll.NtFsControlFile` based on the value of passed `IO_CONTROL_CODE`. The decision logic is based on the logic found in ReactOS found in the following [link]. Thanks to Daurnimator for finding this bit in ReactOS! [link]: https://doxygen.reactos.org/d3/d74/deviceio_8c.html

1 files changed, 14 insertions(+), 10 deletions(-)

lib/std/os/windows.zig+14-10
......@@ -215,24 +215,28 @@ pub fn CreateEventExW(attributes: ?*SECURITY_ATTRIBUTES, nameW: [*:0]const u16,
215215 }
216216}
217217
218pub const FsControlFileError = error{Unexpected};
218pub const DeviceIoControlError = error{Unexpected};
219219
220// TODO work out if we need to expose other arguments to the underlying
221// NtFsControlFile syscall
222pub fn FsControlFile(
220/// A Zig wrapper around `NtDeviceIoControlFile` and `NtFsControlFile` syscalls.
221/// It implements similar behavior to `DeviceIoControl` and is meant to serve
222/// as a direct substitute for that call.
223/// TODO work out if we need to expose other arguments to the underlying syscalls.
224pub fn DeviceIoControl(
223225 h: HANDLE,
224 fsControlCode: ULONG,
226 ioControlCode: ULONG,
225227 in: ?[]const u8,
226228 out: ?[]u8,
227) FsControlFileError!void {
229) DeviceIoControlError!void {
230 // Logic from: https://doxygen.reactos.org/d3/d74/deviceio_8c.html
231 const syscall = if ((ioControlCode >> 16) == FILE_DEVICE_FILE_SYSTEM) ntdll.NtFsControlFile else ntdll.NtDeviceIoControlFile;
228232 var io: IO_STATUS_BLOCK = undefined;
229 const rc = ntdll.NtFsControlFile(
233 const rc = syscall(
230234 h,
231235 null,
232236 null,
233237 null,
234238 &io,
235 fsControlCode,
239 ioControlCode,
236240 if (in) |i| i.ptr else null,
237241 if (in) |i| @intCast(ULONG, i.len) else 0,
238242 if (out) |o| o.ptr else null,
......@@ -731,7 +735,7 @@ pub fn CreateSymbolicLinkW(
731735 @memcpy(buffer[@sizeOf(SYMLINK_DATA)..], @ptrCast([*]const u8, target_path), target_path.len * 2);
732736 const paths_start = @sizeOf(SYMLINK_DATA) + target_path.len * 2;
733737 @memcpy(buffer[paths_start..].ptr, @ptrCast([*]const u8, target_path), target_path.len * 2);
734 _ = try FsControlFile(symlink_handle, FSCTL_SET_REPARSE_POINT, buffer[0..buf_len], null);
738 _ = try DeviceIoControl(symlink_handle, FSCTL_SET_REPARSE_POINT, buffer[0..buf_len], null);
735739}
736740
737741pub const ReadLinkError = error{
......@@ -809,7 +813,7 @@ pub fn ReadLinkW(dir: ?HANDLE, sub_path_w: [*:0]const u16, out_buffer: []u8) Rea
809813 defer CloseHandle(result_handle);
810814
811815 var reparse_buf: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined;
812 _ = try FsControlFile(result_handle, FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..]);
816 _ = try DeviceIoControl(result_handle, FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..]);
813817
814818 const reparse_struct = @ptrCast(*const REPARSE_DATA_BUFFER, @alignCast(@alignOf(REPARSE_DATA_BUFFER), &reparse_buf[0]));
815819 switch (reparse_struct.ReparseTag) {