| ... | @@ -937,25 +937,50 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil | ... | @@ -937,25 +937,50 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil |
| 937 | .DELETE_PENDING => return, | 937 | .DELETE_PENDING => return, |
| 938 | else => return unexpectedStatus(rc), | 938 | else => return unexpectedStatus(rc), |
| 939 | } | 939 | } |
| 940 | var file_dispo = FILE_DISPOSITION_INFORMATION{ | 940 | defer CloseHandle(tmp_handle); |
| 941 | .DeleteFile = TRUE, | 941 | if (comptime builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs1)) { |
| 942 | }; | 942 | // Deletion with posix semantics. |
| 943 | rc = ntdll.NtSetInformationFile( | 943 | var info = FILE_DISPOSITION_INFORMATION_EX{ |
| 944 | tmp_handle, | 944 | .Flags = FILE_DISPOSITION_DELETE | |
| 945 | &io, | 945 | FILE_DISPOSITION_POSIX_SEMANTICS | |
| 946 | &file_dispo, | 946 | FILE_DISPOSITION_ON_CLOSE | |
| 947 | @sizeOf(FILE_DISPOSITION_INFORMATION), | 947 | FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE, |
| 948 | .FileDispositionInformation, | 948 | }; |
| 949 | ); | 949 | |
| 950 | CloseHandle(tmp_handle); | 950 | rc = ntdll.NtSetInformationFile( |
| 951 | switch (rc) { | 951 | tmp_handle, |
| 952 | .SUCCESS => return, | 952 | &io, |
| 953 | .DIRECTORY_NOT_EMPTY => return error.DirNotEmpty, | 953 | &info, |
| 954 | .INVALID_PARAMETER => unreachable, | 954 | @sizeOf(FILE_DISPOSITION_INFORMATION_EX), |
| 955 | .CANNOT_DELETE => return error.AccessDenied, | 955 | .FileDispositionInformationEx, |
| 956 | .MEDIA_WRITE_PROTECTED => return error.AccessDenied, | 956 | ); |
| 957 | .ACCESS_DENIED => return error.AccessDenied, | 957 | switch (rc) { |
| 958 | else => return unexpectedStatus(rc), | 958 | .SUCCESS => {}, |
| | 959 | .CANNOT_DELETE => return error.FileBusy, // file is currently mapped |
| | 960 | else => return unexpectedStatus(rc), |
| | 961 | } |
| | 962 | } else { |
| | 963 | // Deletion with file pending semantics, which requires waiting or moving |
| | 964 | // files to get them removed (from here). |
| | 965 | var file_dispo = FILE_DISPOSITION_INFORMATION{ |
| | 966 | .DeleteFile = TRUE, |
| | 967 | }; |
| | 968 | rc = ntdll.NtSetInformationFile( |
| | 969 | tmp_handle, |
| | 970 | &io, |
| | 971 | &file_dispo, |
| | 972 | @sizeOf(FILE_DISPOSITION_INFORMATION), |
| | 973 | .FileDispositionInformation, |
| | 974 | ); |
| | 975 | switch (rc) { |
| | 976 | .SUCCESS => {}, |
| | 977 | .DIRECTORY_NOT_EMPTY => return error.DirNotEmpty, |
| | 978 | .INVALID_PARAMETER => unreachable, |
| | 979 | .CANNOT_DELETE => return error.AccessDenied, |
| | 980 | .MEDIA_WRITE_PROTECTED => return error.AccessDenied, |
| | 981 | .ACCESS_DENIED => return error.AccessDenied, |
| | 982 | else => return unexpectedStatus(rc), |
| | 983 | } |
| 959 | } | 984 | } |
| 960 | } | 985 | } |
| 961 | | 986 | |
| ... | @@ -2397,6 +2422,18 @@ pub const FILE_NAME_INFORMATION = extern struct { | ... | @@ -2397,6 +2422,18 @@ pub const FILE_NAME_INFORMATION = extern struct { |
| 2397 | FileName: [1]WCHAR, | 2422 | FileName: [1]WCHAR, |
| 2398 | }; | 2423 | }; |
| 2399 | | 2424 | |
| | 2425 | pub const FILE_DISPOSITION_INFORMATION_EX = extern struct { |
| | 2426 | /// combination of FILE_DISPOSITION_* flags |
| | 2427 | Flags: ULONG, |
| | 2428 | }; |
| | 2429 | |
| | 2430 | const FILE_DISPOSITION_DO_NOT_DELETE: ULONG = 0x00000000; |
| | 2431 | const FILE_DISPOSITION_DELETE: ULONG = 0x00000001; |
| | 2432 | const FILE_DISPOSITION_POSIX_SEMANTICS: ULONG = 0x00000002; |
| | 2433 | const FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK: ULONG = 0x00000004; |
| | 2434 | const FILE_DISPOSITION_ON_CLOSE: ULONG = 0x00000008; |
| | 2435 | const FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE: ULONG = 0x00000010; |
| | 2436 | |
| 2400 | pub const FILE_RENAME_INFORMATION = extern struct { | 2437 | pub const FILE_RENAME_INFORMATION = extern struct { |
| 2401 | ReplaceIfExists: BOOLEAN, | 2438 | ReplaceIfExists: BOOLEAN, |
| 2402 | RootDirectory: ?HANDLE, | 2439 | RootDirectory: ?HANDLE, |