From 911f74e93b15024c7a2a15ca6845bd0ddbdf9b3c Mon Sep 17 00:00:00 2001 From: xEgoist Date: Sun, 16 Apr 2023 00:38:25 -0500 Subject: windows: use NtSetInformationFile in DeleteFile. Using `FILE_DELETE_ON_CLOSE` can silently succeed without reporting any error on non-empty directory. This commit adds usage of NtSetInformationFile which will report `DIRECTORY_NOT_EMPTY`. --- lib/std/os/windows.zig | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index f8672bc58d..e195989e7e 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -870,6 +870,7 @@ pub const DeleteFileError = error{ Unexpected, NotDir, IsDir, + DirNotEmpty, }; pub const DeleteFileOptions = struct { @@ -879,9 +880,9 @@ pub const DeleteFileOptions = struct { pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFileError!void { const create_options_flags: ULONG = if (options.remove_dir) - FILE_DELETE_ON_CLOSE | FILE_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT + FILE_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT else - FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT; // would we ever want to delete the target instead? + FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT; // would we ever want to delete the target instead? const path_len_bytes = @intCast(u16, sub_path_w.len * 2); var nt_name = UNICODE_STRING{ @@ -924,7 +925,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil 0, ); switch (rc) { - .SUCCESS => return CloseHandle(tmp_handle), + .SUCCESS => {}, .OBJECT_NAME_INVALID => unreachable, .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, @@ -935,6 +936,22 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil .CANNOT_DELETE => return error.AccessDenied, else => return unexpectedStatus(rc), } + var file_dispo = FILE_DISPOSITION_INFORMATION{ + .DeleteFile = TRUE, + }; + rc = ntdll.NtSetInformationFile( + tmp_handle, + &io, + &file_dispo, + @sizeOf(FILE_DISPOSITION_INFORMATION), + .FileDispositionInformation, + ); + CloseHandle(tmp_handle); + switch (rc) { + .SUCCESS => return, + .DIRECTORY_NOT_EMPTY => return error.DirNotEmpty, + else => return unexpectedStatus(rc), + } } pub const MoveFileError = error{ FileNotFound, AccessDenied, Unexpected }; @@ -2470,6 +2487,10 @@ pub const FILE_INFORMATION_CLASS = enum(c_int) { FileMaximumInformation, }; +pub const FILE_DISPOSITION_INFORMATION = extern struct { + DeleteFile: BOOLEAN, +}; + pub const FILE_FS_DEVICE_INFORMATION = extern struct { DeviceType: DEVICE_TYPE, Characteristics: ULONG, -- cgit v1.2.3