Function OpenFile [src]

Prototype

pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HANDLE

Parameters

sub_path_w: []const u16options: OpenFileOptions

Possible Errors

AccessDenied
AntivirusInterference
BadPathName
FileNotFound
IsDir
NameTooLong
NetworkNotFound
NoDevice
NotDir
PathAlreadyExists
PipeBusy
Unexpected
WouldBlock

Source

pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HANDLE { if (mem.eql(u16, sub_path_w, &[_]u16{'.'}) and options.filter == .file_only) { return error.IsDir; } if (mem.eql(u16, sub_path_w, &[_]u16{ '.', '.' }) and options.filter == .file_only) { return error.IsDir; } var result: HANDLE = undefined; const path_len_bytes = math.cast(u16, sub_path_w.len * 2) orelse return error.NameTooLong; var nt_name = UNICODE_STRING{ .Length = path_len_bytes, .MaximumLength = path_len_bytes, .Buffer = @constCast(sub_path_w.ptr), }; var attr = OBJECT_ATTRIBUTES{ .Length = @sizeOf(OBJECT_ATTRIBUTES), .RootDirectory = if (std.fs.path.isAbsoluteWindowsWTF16(sub_path_w)) null else options.dir, .Attributes = if (options.sa) |ptr| blk: { // Note we do not use OBJ_CASE_INSENSITIVE here. const inherit: ULONG = if (ptr.bInheritHandle == TRUE) OBJ_INHERIT else 0; break :blk inherit; } else 0, .ObjectName = &nt_name, .SecurityDescriptor = if (options.sa) |ptr| ptr.lpSecurityDescriptor else null, .SecurityQualityOfService = null, }; var io: IO_STATUS_BLOCK = undefined; const blocking_flag: ULONG = FILE_SYNCHRONOUS_IO_NONALERT; const file_or_dir_flag: ULONG = switch (options.filter) { .file_only => FILE_NON_DIRECTORY_FILE, .dir_only => FILE_DIRECTORY_FILE, .any => 0, }; // If we're not following symlinks, we need to ensure we don't pass in any synchronization flags such as FILE_SYNCHRONOUS_IO_NONALERT. const flags: ULONG = if (options.follow_symlinks) file_or_dir_flag | blocking_flag else file_or_dir_flag | FILE_OPEN_REPARSE_POINT; while (true) { const rc = ntdll.NtCreateFile( &result, options.access_mask, &attr, &io, null, FILE_ATTRIBUTE_NORMAL, options.share_access, options.creation, flags, null, 0, ); switch (rc) { .SUCCESS => return result, .OBJECT_NAME_INVALID => return error.BadPathName, .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, .BAD_NETWORK_PATH => return error.NetworkNotFound, // \\server was not found .BAD_NETWORK_NAME => return error.NetworkNotFound, // \\server was found but \\server\share wasn't .NO_MEDIA_IN_DEVICE => return error.NoDevice, .INVALID_PARAMETER => unreachable, .SHARING_VIOLATION => return error.AccessDenied, .ACCESS_DENIED => return error.AccessDenied, .PIPE_BUSY => return error.PipeBusy, .PIPE_NOT_AVAILABLE => return error.NoDevice, .OBJECT_PATH_SYNTAX_BAD => unreachable, .OBJECT_NAME_COLLISION => return error.PathAlreadyExists, .FILE_IS_A_DIRECTORY => return error.IsDir, .NOT_A_DIRECTORY => return error.NotDir, .USER_MAPPED_FILE => return error.AccessDenied, .INVALID_HANDLE => unreachable, .DELETE_PENDING => { // This error means that there *was* a file in this location on // the file system, but it was deleted. However, the OS is not // finished with the deletion operation, and so this CreateFile // call has failed. There is not really a sane way to handle // this other than retrying the creation after the OS finishes // the deletion. std.time.sleep(std.time.ns_per_ms); continue; }, .VIRUS_INFECTED, .VIRUS_DELETED => return error.AntivirusInterference, else => return unexpectedStatus(rc), } } }