| ... | @@ -2574,23 +2574,6 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C | ... | @@ -2574,23 +2574,6 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C |
| 2574 | wr.* = write; | 2574 | wr.* = write; |
| 2575 | } | 2575 | } |
| 2576 | | 2576 | |
| 2577 | pub const DeviceIoControlError = error{ | | |
| 2578 | AccessDenied, | | |
| 2579 | /// The volume does not contain a recognized file system. File system | | |
| 2580 | /// drivers might not be loaded, or the volume may be corrupt. | | |
| 2581 | UnrecognizedVolume, | | |
| 2582 | Pending, | | |
| 2583 | /// Attempted to connect a named pipe in the "closing" state, meaning a previous client has | | |
| 2584 | /// has closed their handle but we have not yet disconnected the pipe. | | |
| 2585 | PipeClosing, | | |
| 2586 | /// Attempted to connect a named pipe in the "connected" state, meaning a client has already | | |
| 2587 | /// opened the pipe; there is a good connection between client and server. | | |
| 2588 | PipeAlreadyConnected, | | |
| 2589 | /// Attempted to connect a non-blocking named pipe which is already listening for connections. | | |
| 2590 | PipeAlreadyListening, | | |
| 2591 | Unexpected, | | |
| 2592 | }; | | |
| 2593 | | | |
| 2594 | /// A Zig wrapper around `NtDeviceIoControlFile` and `NtFsControlFile` syscalls. | 2577 | /// A Zig wrapper around `NtDeviceIoControlFile` and `NtFsControlFile` syscalls. |
| 2595 | /// It implements similar behavior to `DeviceIoControl` and is meant to serve | 2578 | /// It implements similar behavior to `DeviceIoControl` and is meant to serve |
| 2596 | /// as a direct substitute for that call. | 2579 | /// as a direct substitute for that call. |
| ... | @@ -2606,9 +2589,9 @@ pub fn DeviceIoControl( | ... | @@ -2606,9 +2589,9 @@ pub fn DeviceIoControl( |
| 2606 | in: []const u8 = &.{}, | 2589 | in: []const u8 = &.{}, |
| 2607 | out: []u8 = &.{}, | 2590 | out: []u8 = &.{}, |
| 2608 | }, | 2591 | }, |
| 2609 | ) DeviceIoControlError!void { | 2592 | ) NTSTATUS { |
| 2610 | var io_status_block: IO_STATUS_BLOCK = undefined; | 2593 | var io_status_block: IO_STATUS_BLOCK = undefined; |
| 2611 | const rc = switch (io_control_code.DeviceType) { | 2594 | return switch (io_control_code.DeviceType) { |
| 2612 | .FILE_SYSTEM, .NAMED_PIPE => ntdll.NtFsControlFile( | 2595 | .FILE_SYSTEM, .NAMED_PIPE => ntdll.NtFsControlFile( |
| 2613 | device, | 2596 | device, |
| 2614 | opts.event, | 2597 | opts.event, |
| ... | @@ -2634,19 +2617,6 @@ pub fn DeviceIoControl( | ... | @@ -2634,19 +2617,6 @@ pub fn DeviceIoControl( |
| 2634 | @intCast(opts.out.len), | 2617 | @intCast(opts.out.len), |
| 2635 | ), | 2618 | ), |
| 2636 | }; | 2619 | }; |
| 2637 | switch (rc) { | | |
| 2638 | .SUCCESS => {}, | | |
| 2639 | .PIPE_CLOSING => return error.PipeClosing, | | |
| 2640 | .PIPE_CONNECTED => return error.PipeAlreadyConnected, | | |
| 2641 | .PIPE_LISTENING => return error.PipeAlreadyListening, | | |
| 2642 | .PRIVILEGE_NOT_HELD => return error.AccessDenied, | | |
| 2643 | .ACCESS_DENIED => return error.AccessDenied, | | |
| 2644 | .INVALID_DEVICE_REQUEST => return error.AccessDenied, // Not supported by the underlying filesystem | | |
| 2645 | .INVALID_PARAMETER => unreachable, | | |
| 2646 | .UNRECOGNIZED_VOLUME => return error.UnrecognizedVolume, | | |
| 2647 | .PENDING => return error.Pending, | | |
| 2648 | else => return unexpectedStatus(rc), | | |
| 2649 | } | | |
| 2650 | } | 2620 | } |
| 2651 | | 2621 | |
| 2652 | pub fn GetOverlappedResult(h: HANDLE, overlapped: *OVERLAPPED, wait: bool) !DWORD { | 2622 | pub fn GetOverlappedResult(h: HANDLE, overlapped: *OVERLAPPED, wait: bool) !DWORD { |
| ... | @@ -3037,9 +3007,6 @@ pub const CreateSymbolicLinkError = error{ | ... | @@ -3037,9 +3007,6 @@ pub const CreateSymbolicLinkError = error{ |
| 3037 | NoDevice, | 3007 | NoDevice, |
| 3038 | NetworkNotFound, | 3008 | NetworkNotFound, |
| 3039 | BadPathName, | 3009 | BadPathName, |
| 3040 | /// The volume does not contain a recognized file system. File system | | |
| 3041 | /// drivers might not be loaded, or the volume may be corrupt. | | |
| 3042 | UnrecognizedVolume, | | |
| 3043 | Unexpected, | 3010 | Unexpected, |
| 3044 | }; | 3011 | }; |
| 3045 | | 3012 | |
| ... | @@ -3139,13 +3106,14 @@ pub fn CreateSymbolicLink( | ... | @@ -3139,13 +3106,14 @@ pub fn CreateSymbolicLink( |
| 3139 | @memcpy(buffer[@sizeOf(SYMLINK_DATA)..][0 .. final_target_path.len * 2], @as([*]const u8, @ptrCast(final_target_path))); | 3106 | @memcpy(buffer[@sizeOf(SYMLINK_DATA)..][0 .. final_target_path.len * 2], @as([*]const u8, @ptrCast(final_target_path))); |
| 3140 | const paths_start = @sizeOf(SYMLINK_DATA) + final_target_path.len * 2; | 3107 | const paths_start = @sizeOf(SYMLINK_DATA) + final_target_path.len * 2; |
| 3141 | @memcpy(buffer[paths_start..][0 .. final_target_path.len * 2], @as([*]const u8, @ptrCast(final_target_path))); | 3108 | @memcpy(buffer[paths_start..][0 .. final_target_path.len * 2], @as([*]const u8, @ptrCast(final_target_path))); |
| 3142 | _ = DeviceIoControl(symlink_handle, FSCTL.SET_REPARSE_POINT, .{ .in = buffer[0..buf_len] }) catch |err| switch (err) { | 3109 | const rc = DeviceIoControl(symlink_handle, FSCTL.SET_REPARSE_POINT, .{ .in = buffer[0..buf_len] }); |
| 3143 | error.PipeClosing => unreachable, | 3110 | switch (rc) { |
| 3144 | error.PipeAlreadyConnected => unreachable, | 3111 | .SUCCESS => {}, |
| 3145 | error.PipeAlreadyListening => unreachable, | 3112 | .PRIVILEGE_NOT_HELD => return error.AccessDenied, |
| 3146 | error.Pending => unreachable, | 3113 | .ACCESS_DENIED => return error.AccessDenied, |
| 3147 | else => |e| return e, | 3114 | .INVALID_DEVICE_REQUEST => return error.AccessDenied, // Not supported by the underlying filesystem |
| 3148 | }; | 3115 | else => return unexpectedStatus(rc), |
| | 3116 | } |
| 3149 | } | 3117 | } |
| 3150 | | 3118 | |
| 3151 | pub const ReadLinkError = error{ | 3119 | pub const ReadLinkError = error{ |
| ... | @@ -3157,6 +3125,7 @@ pub const ReadLinkError = error{ | ... | @@ -3157,6 +3125,7 @@ pub const ReadLinkError = error{ |
| 3157 | BadPathName, | 3125 | BadPathName, |
| 3158 | AntivirusInterference, | 3126 | AntivirusInterference, |
| 3159 | UnsupportedReparsePointType, | 3127 | UnsupportedReparsePointType, |
| | 3128 | NotLink, |
| 3160 | }; | 3129 | }; |
| 3161 | | 3130 | |
| 3162 | /// `sub_path_w` will never be accessed after `out_buffer` has been written to, so it | 3131 | /// `sub_path_w` will never be accessed after `out_buffer` has been written to, so it |
| ... | @@ -3184,15 +3153,12 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u16) ReadLi | ... | @@ -3184,15 +3153,12 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u16) ReadLi |
| 3184 | defer CloseHandle(result_handle); | 3153 | defer CloseHandle(result_handle); |
| 3185 | | 3154 | |
| 3186 | var reparse_buf: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 align(@alignOf(REPARSE_DATA_BUFFER)) = undefined; | 3155 | var reparse_buf: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 align(@alignOf(REPARSE_DATA_BUFFER)) = undefined; |
| 3187 | _ = DeviceIoControl(result_handle, FSCTL.GET_REPARSE_POINT, .{ .out = reparse_buf[0..] }) catch |err| switch (err) { | 3156 | const rc = DeviceIoControl(result_handle, FSCTL.GET_REPARSE_POINT, .{ .out = reparse_buf[0..] }); |
| 3188 | error.PipeClosing => unreachable, | 3157 | switch (rc) { |
| 3189 | error.PipeAlreadyConnected => unreachable, | 3158 | .SUCCESS => {}, |
| 3190 | error.PipeAlreadyListening => unreachable, | 3159 | .NOT_A_REPARSE_POINT => return error.NotLink, |
| 3191 | error.AccessDenied => return error.Unexpected, | 3160 | else => return unexpectedStatus(rc), |
| 3192 | error.UnrecognizedVolume => return error.Unexpected, | 3161 | } |
| 3193 | error.Pending => unreachable, | | |
| 3194 | else => |e| return e, | | |
| 3195 | }; | | |
| 3196 | | 3162 | |
| 3197 | const reparse_struct: *const REPARSE_DATA_BUFFER = @ptrCast(@alignCast(&reparse_buf[0])); | 3163 | const reparse_struct: *const REPARSE_DATA_BUFFER = @ptrCast(@alignCast(&reparse_buf[0])); |
| 3198 | const IoReparseTagInt = @typeInfo(IO_REPARSE_TAG).@"struct".backing_integer.?; | 3164 | const IoReparseTagInt = @typeInfo(IO_REPARSE_TAG).@"struct".backing_integer.?; |
| ... | @@ -3744,14 +3710,14 @@ pub fn GetFinalPathNameByHandle( | ... | @@ -3744,14 +3710,14 @@ pub fn GetFinalPathNameByHandle( |
| 3744 | input_struct.DeviceNameLength = @intCast(volume_name_u16.len * 2); | 3710 | input_struct.DeviceNameLength = @intCast(volume_name_u16.len * 2); |
| 3745 | @memcpy(input_buf[@sizeOf(MOUNTMGR_MOUNT_POINT)..][0 .. volume_name_u16.len * 2], @as([*]const u8, @ptrCast(volume_name_u16.ptr))); | 3711 | @memcpy(input_buf[@sizeOf(MOUNTMGR_MOUNT_POINT)..][0 .. volume_name_u16.len * 2], @as([*]const u8, @ptrCast(volume_name_u16.ptr))); |
| 3746 | | 3712 | |
| 3747 | DeviceIoControl(mgmt_handle, IOCTL.MOUNTMGR.QUERY_POINTS, .{ .in = &input_buf, .out = &output_buf }) catch |err| switch (err) { | 3713 | { |
| 3748 | error.PipeClosing => unreachable, | 3714 | const rc = DeviceIoControl(mgmt_handle, IOCTL.MOUNTMGR.QUERY_POINTS, .{ .in = &input_buf, .out = &output_buf }); |
| 3749 | error.PipeAlreadyConnected => unreachable, | 3715 | switch (rc) { |
| 3750 | error.PipeAlreadyListening => unreachable, | 3716 | .SUCCESS => {}, |
| 3751 | error.AccessDenied => return error.Unexpected, | 3717 | .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, |
| 3752 | error.Pending => unreachable, | 3718 | else => return unexpectedStatus(rc), |
| 3753 | else => |e| return e, | 3719 | } |
| 3754 | }; | 3720 | } |
| 3755 | const mount_points_struct: *const MOUNTMGR_MOUNT_POINTS = @ptrCast(&output_buf[0]); | 3721 | const mount_points_struct: *const MOUNTMGR_MOUNT_POINTS = @ptrCast(&output_buf[0]); |
| 3756 | | 3722 | |
| 3757 | const mount_points = @as( | 3723 | const mount_points = @as( |
| ... | @@ -3803,14 +3769,12 @@ pub fn GetFinalPathNameByHandle( | ... | @@ -3803,14 +3769,12 @@ pub fn GetFinalPathNameByHandle( |
| 3803 | vol_input_struct.DeviceNameLength = @intCast(symlink.len * 2); | 3769 | vol_input_struct.DeviceNameLength = @intCast(symlink.len * 2); |
| 3804 | @memcpy(@as([*]WCHAR, &vol_input_struct.DeviceName)[0..symlink.len], symlink); | 3770 | @memcpy(@as([*]WCHAR, &vol_input_struct.DeviceName)[0..symlink.len], symlink); |
| 3805 | | 3771 | |
| 3806 | DeviceIoControl(mgmt_handle, IOCTL.MOUNTMGR.QUERY_DOS_VOLUME_PATH, .{ .in = &vol_input_buf, .out = &vol_output_buf }) catch |err| switch (err) { | 3772 | const rc = DeviceIoControl(mgmt_handle, IOCTL.MOUNTMGR.QUERY_DOS_VOLUME_PATH, .{ .in = &vol_input_buf, .out = &vol_output_buf }); |
| 3807 | error.PipeClosing => unreachable, | 3773 | switch (rc) { |
| 3808 | error.PipeAlreadyConnected => unreachable, | 3774 | .SUCCESS => {}, |
| 3809 | error.PipeAlreadyListening => unreachable, | 3775 | .UNRECOGNIZED_VOLUME => return error.UnrecognizedVolume, |
| 3810 | error.AccessDenied => return error.Unexpected, | 3776 | else => return unexpectedStatus(rc), |
| 3811 | error.Pending => unreachable, | 3777 | } |
| 3812 | else => |e| return e, | | |
| 3813 | }; | | |
| 3814 | const volume_paths_struct: *const MOUNTMGR_VOLUME_PATHS = @ptrCast(&vol_output_buf[0]); | 3778 | const volume_paths_struct: *const MOUNTMGR_VOLUME_PATHS = @ptrCast(&vol_output_buf[0]); |
| 3815 | const volume_path = std.mem.sliceTo(@as( | 3779 | const volume_path = std.mem.sliceTo(@as( |
| 3816 | [*]const u16, | 3780 | [*]const u16, |