| ... | ... | @@ -2574,23 +2574,6 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C |
| 2574 | 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 | 2577 | /// A Zig wrapper around `NtDeviceIoControlFile` and `NtFsControlFile` syscalls. |
| 2595 | 2578 | /// It implements similar behavior to `DeviceIoControl` and is meant to serve |
| 2596 | 2579 | /// as a direct substitute for that call. |
| ... | ... | @@ -2606,9 +2589,9 @@ pub fn DeviceIoControl( |
| 2606 | 2589 | in: []const u8 = &.{}, |
| 2607 | 2590 | out: []u8 = &.{}, |
| 2608 | 2591 | }, |
| 2609 | | ) DeviceIoControlError!void { |
| 2592 | ) NTSTATUS { |
| 2610 | 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 | 2595 | .FILE_SYSTEM, .NAMED_PIPE => ntdll.NtFsControlFile( |
| 2613 | 2596 | device, |
| 2614 | 2597 | opts.event, |
| ... | ... | @@ -2634,19 +2617,6 @@ pub fn DeviceIoControl( |
| 2634 | 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 | 2622 | pub fn GetOverlappedResult(h: HANDLE, overlapped: *OVERLAPPED, wait: bool) !DWORD { |
| ... | ... | @@ -3037,9 +3007,6 @@ pub const CreateSymbolicLinkError = error{ |
| 3037 | 3007 | NoDevice, |
| 3038 | 3008 | NetworkNotFound, |
| 3039 | 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 | 3010 | Unexpected, |
| 3044 | 3011 | }; |
| 3045 | 3012 | |
| ... | ... | @@ -3139,13 +3106,14 @@ pub fn CreateSymbolicLink( |
| 3139 | 3106 | @memcpy(buffer[@sizeOf(SYMLINK_DATA)..][0 .. final_target_path.len * 2], @as([*]const u8, @ptrCast(final_target_path))); |
| 3140 | 3107 | const paths_start = @sizeOf(SYMLINK_DATA) + final_target_path.len * 2; |
| 3141 | 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) { |
| 3143 | | error.PipeClosing => unreachable, |
| 3144 | | error.PipeAlreadyConnected => unreachable, |
| 3145 | | error.PipeAlreadyListening => unreachable, |
| 3146 | | error.Pending => unreachable, |
| 3147 | | else => |e| return e, |
| 3148 | | }; |
| 3109 | const rc = DeviceIoControl(symlink_handle, FSCTL.SET_REPARSE_POINT, .{ .in = buffer[0..buf_len] }); |
| 3110 | switch (rc) { |
| 3111 | .SUCCESS => {}, |
| 3112 | .PRIVILEGE_NOT_HELD => return error.AccessDenied, |
| 3113 | .ACCESS_DENIED => return error.AccessDenied, |
| 3114 | .INVALID_DEVICE_REQUEST => return error.AccessDenied, // Not supported by the underlying filesystem |
| 3115 | else => return unexpectedStatus(rc), |
| 3116 | } |
| 3149 | 3117 | } |
| 3150 | 3118 | |
| 3151 | 3119 | pub const ReadLinkError = error{ |
| ... | ... | @@ -3184,15 +3152,11 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u16) ReadLi |
| 3184 | 3152 | defer CloseHandle(result_handle); |
| 3185 | 3153 | |
| 3186 | 3154 | 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) { |
| 3188 | | error.PipeClosing => unreachable, |
| 3189 | | error.PipeAlreadyConnected => unreachable, |
| 3190 | | error.PipeAlreadyListening => unreachable, |
| 3191 | | error.AccessDenied => return error.Unexpected, |
| 3192 | | error.UnrecognizedVolume => return error.Unexpected, |
| 3193 | | error.Pending => unreachable, |
| 3194 | | else => |e| return e, |
| 3195 | | }; |
| 3155 | const rc = DeviceIoControl(result_handle, FSCTL.GET_REPARSE_POINT, .{ .out = reparse_buf[0..] }); |
| 3156 | switch (rc) { |
| 3157 | .SUCCESS => {}, |
| 3158 | else => return unexpectedStatus(rc), |
| 3159 | } |
| 3196 | 3160 | |
| 3197 | 3161 | const reparse_struct: *const REPARSE_DATA_BUFFER = @ptrCast(@alignCast(&reparse_buf[0])); |
| 3198 | 3162 | const IoReparseTagInt = @typeInfo(IO_REPARSE_TAG).@"struct".backing_integer.?; |
| ... | ... | @@ -3744,14 +3708,14 @@ pub fn GetFinalPathNameByHandle( |
| 3744 | 3708 | input_struct.DeviceNameLength = @intCast(volume_name_u16.len * 2); |
| 3745 | 3709 | @memcpy(input_buf[@sizeOf(MOUNTMGR_MOUNT_POINT)..][0 .. volume_name_u16.len * 2], @as([*]const u8, @ptrCast(volume_name_u16.ptr))); |
| 3746 | 3710 | |
| 3747 | | DeviceIoControl(mgmt_handle, IOCTL.MOUNTMGR.QUERY_POINTS, .{ .in = &input_buf, .out = &output_buf }) catch |err| switch (err) { |
| 3748 | | error.PipeClosing => unreachable, |
| 3749 | | error.PipeAlreadyConnected => unreachable, |
| 3750 | | error.PipeAlreadyListening => unreachable, |
| 3751 | | error.AccessDenied => return error.Unexpected, |
| 3752 | | error.Pending => unreachable, |
| 3753 | | else => |e| return e, |
| 3754 | | }; |
| 3711 | { |
| 3712 | const rc = DeviceIoControl(mgmt_handle, IOCTL.MOUNTMGR.QUERY_POINTS, .{ .in = &input_buf, .out = &output_buf }); |
| 3713 | switch (rc) { |
| 3714 | .SUCCESS => {}, |
| 3715 | .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, |
| 3716 | else => return unexpectedStatus(rc), |
| 3717 | } |
| 3718 | } |
| 3755 | 3719 | const mount_points_struct: *const MOUNTMGR_MOUNT_POINTS = @ptrCast(&output_buf[0]); |
| 3756 | 3720 | |
| 3757 | 3721 | const mount_points = @as( |
| ... | ... | @@ -3803,14 +3767,12 @@ pub fn GetFinalPathNameByHandle( |
| 3803 | 3767 | vol_input_struct.DeviceNameLength = @intCast(symlink.len * 2); |
| 3804 | 3768 | @memcpy(@as([*]WCHAR, &vol_input_struct.DeviceName)[0..symlink.len], symlink); |
| 3805 | 3769 | |
| 3806 | | DeviceIoControl(mgmt_handle, IOCTL.MOUNTMGR.QUERY_DOS_VOLUME_PATH, .{ .in = &vol_input_buf, .out = &vol_output_buf }) catch |err| switch (err) { |
| 3807 | | error.PipeClosing => unreachable, |
| 3808 | | error.PipeAlreadyConnected => unreachable, |
| 3809 | | error.PipeAlreadyListening => unreachable, |
| 3810 | | error.AccessDenied => return error.Unexpected, |
| 3811 | | error.Pending => unreachable, |
| 3812 | | else => |e| return e, |
| 3813 | | }; |
| 3770 | const rc = DeviceIoControl(mgmt_handle, IOCTL.MOUNTMGR.QUERY_DOS_VOLUME_PATH, .{ .in = &vol_input_buf, .out = &vol_output_buf }); |
| 3771 | switch (rc) { |
| 3772 | .SUCCESS => {}, |
| 3773 | .UNRECOGNIZED_VOLUME => return error.UnrecognizedVolume, |
| 3774 | else => return unexpectedStatus(rc), |
| 3775 | } |
| 3814 | 3776 | const volume_paths_struct: *const MOUNTMGR_VOLUME_PATHS = @ptrCast(&vol_output_buf[0]); |
| 3815 | 3777 | const volume_path = std.mem.sliceTo(@as( |
| 3816 | 3778 | [*]const u16, |