std\sys\fs\windows/
dir.rs1use crate::os::windows::io::{
2 AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, HandleOrInvalid, IntoRawHandle,
3 OwnedHandle, RawHandle,
4};
5use crate::path::Path;
6use crate::sys::api::{UnicodeStrRef, WinError};
7use crate::sys::fs::windows::debug_path_handle;
8use crate::sys::fs::{File, OpenOptions};
9use crate::sys::handle::Handle;
10use crate::sys::path::{WCStr, with_native_path};
11use crate::sys::{AsInner, FromInner, IntoInner, IoResult, c, to_u16s};
12use crate::{fmt, fs, io, ptr};
13
14pub struct Dir {
15 handle: Handle,
16}
17
18unsafe fn nt_create_file(
22 opts: &OpenOptions,
23 object_attributes: &c::OBJECT_ATTRIBUTES,
24 create_options: c::NTCREATEFILE_CREATE_OPTIONS,
25) -> io::Result<Handle> {
26 let mut handle = ptr::null_mut();
27 let mut io_status = c::IO_STATUS_BLOCK::PENDING;
28 let access = opts.get_access_mode()? | c::SYNCHRONIZE;
30 let options = create_options | c::FILE_SYNCHRONOUS_IO_NONALERT;
32 let status = unsafe {
33 c::NtCreateFile(
34 &mut handle,
35 access,
36 object_attributes,
37 &mut io_status,
38 ptr::null(),
39 c::FILE_ATTRIBUTE_NORMAL,
40 opts.share_mode,
41 opts.get_disposition()?,
42 options,
43 ptr::null(),
44 0,
45 )
46 };
47 if c::nt_success(status) {
48 unsafe { Ok(Handle::from_raw_handle(handle)) }
50 } else {
51 Err(WinError::new(unsafe { c::RtlNtStatusToDosError(status) })).io_result()
52 }
53}
54
55impl Dir {
56 pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<Self> {
57 with_native_path(path, &|path| Self::open_with_native(path, opts))
58 }
59
60 pub fn open_file(&self, path: &Path, opts: &OpenOptions) -> io::Result<File> {
61 if path.is_absolute() {
63 return File::open(path, opts);
64 }
65 let path = to_u16s(path)?;
66 let path = &path[..path.len() - 1]; self.open_file_native(&path, opts).map(|handle| File { handle })
68 }
69
70 fn open_with_native(path: &WCStr, opts: &OpenOptions) -> io::Result<Self> {
71 let creation = opts.get_creation_mode()?;
72 let sa = c::SECURITY_ATTRIBUTES {
73 nLength: size_of::<c::SECURITY_ATTRIBUTES>() as u32,
74 lpSecurityDescriptor: ptr::null_mut(),
75 bInheritHandle: opts.inherit_handle as c::BOOL,
76 };
77 let handle = unsafe {
78 c::CreateFileW(
79 path.as_ptr(),
80 opts.get_access_mode()?,
81 opts.share_mode,
82 &raw const sa,
83 creation,
84 opts.get_flags_and_attributes() | c::FILE_FLAG_BACKUP_SEMANTICS,
86 ptr::null_mut(),
87 )
88 };
89 match OwnedHandle::try_from(unsafe { HandleOrInvalid::from_raw_handle(handle) }) {
90 Ok(handle) => Ok(Self { handle: Handle::from_inner(handle) }),
91 Err(_) => Err(io::Error::last_os_error()),
92 }
93 }
94
95 fn open_file_native(&self, path: &[u16], opts: &OpenOptions) -> io::Result<Handle> {
96 let name = UnicodeStrRef::from_slice(path);
97 let object_attributes = c::OBJECT_ATTRIBUTES {
98 RootDirectory: self.handle.as_raw_handle(),
99 ObjectName: name.as_ptr(),
100 ..c::OBJECT_ATTRIBUTES::with_length()
101 };
102 unsafe { nt_create_file(opts, &object_attributes, c::FILE_NON_DIRECTORY_FILE) }
103 }
104}
105
106impl fmt::Debug for Dir {
107 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108 let mut b = debug_path_handle(self.handle.as_handle(), f, "Dir");
109 b.finish()
110 }
111}
112
113#[unstable(feature = "dirfd", issue = "120426")]
114impl AsRawHandle for fs::Dir {
115 fn as_raw_handle(&self) -> RawHandle {
116 self.as_inner().handle.as_raw_handle()
117 }
118}
119
120#[unstable(feature = "dirhandle", issue = "120426")]
121impl IntoRawHandle for fs::Dir {
122 fn into_raw_handle(self) -> RawHandle {
123 self.into_inner().handle.into_raw_handle()
124 }
125}
126
127#[unstable(feature = "dirhandle", issue = "120426")]
128impl FromRawHandle for fs::Dir {
129 unsafe fn from_raw_handle(handle: RawHandle) -> Self {
130 Self::from_inner(Dir { handle: unsafe { FromRawHandle::from_raw_handle(handle) } })
131 }
132}
133
134#[unstable(feature = "dirhandle", issue = "120426")]
135impl AsHandle for fs::Dir {
136 fn as_handle(&self) -> BorrowedHandle<'_> {
137 self.as_inner().handle.as_handle()
138 }
139}
140
141#[unstable(feature = "dirhandle", issue = "120426")]
142impl From<fs::Dir> for OwnedHandle {
143 fn from(value: fs::Dir) -> Self {
144 value.into_inner().handle.into_inner()
145 }
146}
147
148#[unstable(feature = "dirhandle", issue = "120426")]
149impl From<OwnedHandle> for fs::Dir {
150 fn from(value: OwnedHandle) -> Self {
151 Self::from_inner(Dir { handle: Handle::from_inner(value) })
152 }
153}