| ... | ... | @@ -215,30 +215,34 @@ pub fn CreateEventExW(attributes: ?*SECURITY_ATTRIBUTES, nameW: [*:0]const u16, |
| 215 | 215 | } |
| 216 | 216 | } |
| 217 | 217 | |
| 218 | | pub fn DeviceIoControl( |
| 218 | pub const FsControlFileError = error{Unexpected}; |
| 219 | |
| 220 | // TODO work out if we need to expose other arguments to the underlying |
| 221 | // NtFsControlFile syscall |
| 222 | pub fn FsControlFile( |
| 219 | 223 | h: HANDLE, |
| 220 | | ioControlCode: DWORD, |
| 224 | fsControlCode: ULONG, |
| 221 | 225 | in: ?[]const u8, |
| 222 | 226 | out: ?[]u8, |
| 223 | | overlapped: ?*OVERLAPPED, |
| 224 | | ) !DWORD { |
| 225 | | var bytes: DWORD = undefined; |
| 226 | | if (kernel32.DeviceIoControl( |
| 227 | ) FsControlFileError!void { |
| 228 | var io: IO_STATUS_BLOCK = undefined; |
| 229 | const rc = ntdll.NtFsControlFile( |
| 227 | 230 | h, |
| 228 | | ioControlCode, |
| 231 | null, |
| 232 | null, |
| 233 | null, |
| 234 | &io, |
| 235 | fsControlCode, |
| 229 | 236 | if (in) |i| i.ptr else null, |
| 230 | | if (in) |i| @intCast(u32, i.len) else 0, |
| 237 | if (in) |i| @intCast(ULONG, i.len) else 0, |
| 231 | 238 | if (out) |o| o.ptr else null, |
| 232 | | if (out) |o| @intCast(u32, o.len) else 0, |
| 233 | | &bytes, |
| 234 | | overlapped, |
| 235 | | ) == 0) { |
| 236 | | switch (kernel32.GetLastError()) { |
| 237 | | .IO_PENDING => if (overlapped == null) unreachable, |
| 238 | | else => |err| return unexpectedError(err), |
| 239 | | } |
| 239 | if (out) |o| @intCast(ULONG, o.len) else 0, |
| 240 | ); |
| 241 | switch (rc) { |
| 242 | .SUCCESS => {}, |
| 243 | .INVALID_PARAMETER => unreachable, |
| 244 | else => return unexpectedStatus(rc), |
| 240 | 245 | } |
| 241 | | return bytes; |
| 242 | 246 | } |
| 243 | 247 | |
| 244 | 248 | pub fn GetOverlappedResult(h: HANDLE, overlapped: *OVERLAPPED, wait: bool) !DWORD { |
| ... | ... | @@ -727,8 +731,7 @@ pub fn CreateSymbolicLinkW( |
| 727 | 731 | @memcpy(buffer[@sizeOf(SYMLINK_DATA)..], @ptrCast([*]const u8, target_path), target_path.len * 2); |
| 728 | 732 | const paths_start = @sizeOf(SYMLINK_DATA) + target_path.len * 2; |
| 729 | 733 | @memcpy(buffer[paths_start..].ptr, @ptrCast([*]const u8, target_path), target_path.len * 2); |
| 730 | | // TODO replace with NtDeviceIoControl |
| 731 | | _ = try DeviceIoControl(symlink_handle, FSCTL_SET_REPARSE_POINT, buffer[0..buf_len], null, null); |
| 734 | _ = try FsControlFile(symlink_handle, FSCTL_SET_REPARSE_POINT, buffer[0..buf_len], null); |
| 732 | 735 | } |
| 733 | 736 | |
| 734 | 737 | pub const ReadLinkError = error{ |
| ... | ... | @@ -806,7 +809,7 @@ pub fn ReadLinkW(dir: ?HANDLE, sub_path_w: [*:0]const u16, out_buffer: []u8) Rea |
| 806 | 809 | defer CloseHandle(result_handle); |
| 807 | 810 | |
| 808 | 811 | var reparse_buf: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined; |
| 809 | | _ = try DeviceIoControl(result_handle, FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..], null); |
| 812 | _ = try FsControlFile(result_handle, FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..]); |
| 810 | 813 | |
| 811 | 814 | const reparse_struct = @ptrCast(*const REPARSE_DATA_BUFFER, @alignCast(@alignOf(REPARSE_DATA_BUFFER), &reparse_buf[0])); |
| 812 | 815 | switch (reparse_struct.ReparseTag) { |