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