@@ -4,7 +4,6 @@ use std::{
44 io,
55 marker:: PhantomPinned ,
66 net:: Shutdown ,
7- os:: windows:: io:: { AsRawHandle , FromRawHandle , OwnedHandle } ,
87 pin:: Pin ,
98 ptr:: { null, null_mut} ,
109 task:: Poll ,
@@ -15,14 +14,12 @@ use compio_buf::{BufResult, IntoInner, IoBuf, IoBufMut, IoVectoredBuf, IoVectore
1514#[ cfg( not( feature = "once_cell_try" ) ) ]
1615use once_cell:: sync:: OnceCell as OnceLock ;
1716use socket2:: SockAddr ;
18- use widestring:: U16CString ;
1917use windows_sys:: {
2018 core:: GUID ,
2119 Win32 :: {
2220 Foundation :: {
23- CloseHandle , GetLastError , ERROR_ACCESS_DENIED , ERROR_HANDLE_EOF , ERROR_IO_INCOMPLETE ,
24- ERROR_IO_PENDING , ERROR_NOT_FOUND , ERROR_NO_DATA , ERROR_PIPE_CONNECTED ,
25- ERROR_SHARING_VIOLATION , FILETIME , INVALID_HANDLE_VALUE ,
21+ CloseHandle , GetLastError , ERROR_HANDLE_EOF , ERROR_IO_INCOMPLETE , ERROR_IO_PENDING ,
22+ ERROR_NOT_FOUND , ERROR_NO_DATA , ERROR_PIPE_CONNECTED ,
2623 } ,
2724 Networking :: WinSock :: {
2825 closesocket, setsockopt, shutdown, socklen_t, WSAIoctl , WSARecv , WSARecvFrom , WSASend ,
@@ -31,15 +28,7 @@ use windows_sys::{
3128 SOL_SOCKET , SO_UPDATE_ACCEPT_CONTEXT , SO_UPDATE_CONNECT_CONTEXT , WSAID_ACCEPTEX ,
3229 WSAID_CONNECTEX , WSAID_GETACCEPTEXSOCKADDRS ,
3330 } ,
34- Security :: SECURITY_ATTRIBUTES ,
35- Storage :: FileSystem :: {
36- CreateFileW , FileAttributeTagInfo , FindClose , FindFirstFileW , FlushFileBuffers ,
37- GetFileInformationByHandle , GetFileInformationByHandleEx , ReadFile , WriteFile ,
38- BY_HANDLE_FILE_INFORMATION , FILE_ATTRIBUTE_REPARSE_POINT , FILE_ATTRIBUTE_TAG_INFO ,
39- FILE_CREATION_DISPOSITION , FILE_FLAGS_AND_ATTRIBUTES , FILE_FLAG_BACKUP_SEMANTICS ,
40- FILE_FLAG_OPEN_REPARSE_POINT , FILE_SHARE_DELETE , FILE_SHARE_MODE , FILE_SHARE_READ ,
41- FILE_SHARE_WRITE , OPEN_EXISTING , WIN32_FIND_DATAW ,
42- } ,
31+ Storage :: FileSystem :: { FlushFileBuffers , ReadFile , WriteFile } ,
4332 System :: {
4433 Pipes :: ConnectNamedPipe ,
4534 IO :: { CancelIoEx , OVERLAPPED } ,
@@ -136,69 +125,6 @@ impl<
136125 }
137126}
138127
139- /// Open or create a file with flags and mode.
140- pub struct OpenFile {
141- pub ( crate ) path : U16CString ,
142- pub ( crate ) access_mode : u32 ,
143- pub ( crate ) share_mode : FILE_SHARE_MODE ,
144- pub ( crate ) security_attributes : * const SECURITY_ATTRIBUTES ,
145- pub ( crate ) creation_mode : FILE_CREATION_DISPOSITION ,
146- pub ( crate ) flags_and_attributes : FILE_FLAGS_AND_ATTRIBUTES ,
147- pub ( crate ) error_code : u32 ,
148- }
149-
150- impl OpenFile {
151- /// Create [`OpenFile`].
152- pub fn new (
153- path : U16CString ,
154- access_mode : u32 ,
155- share_mode : FILE_SHARE_MODE ,
156- security_attributes : * const SECURITY_ATTRIBUTES ,
157- creation_mode : FILE_CREATION_DISPOSITION ,
158- flags_and_attributes : FILE_FLAGS_AND_ATTRIBUTES ,
159- ) -> Self {
160- Self {
161- path,
162- access_mode,
163- share_mode,
164- security_attributes,
165- creation_mode,
166- flags_and_attributes,
167- error_code : 0 ,
168- }
169- }
170-
171- /// The result of [`GetLastError`]. It may not be 0 even if the operation is
172- /// successful.
173- pub fn last_os_error ( & self ) -> u32 {
174- self . error_code
175- }
176- }
177-
178- impl OpCode for OpenFile {
179- fn op_type ( & self ) -> OpType {
180- OpType :: Blocking
181- }
182-
183- unsafe fn operate ( mut self : Pin < & mut Self > , _optr : * mut OVERLAPPED ) -> Poll < io:: Result < usize > > {
184- let handle = CreateFileW (
185- self . path . as_ptr ( ) ,
186- self . access_mode ,
187- self . share_mode ,
188- self . security_attributes ,
189- self . creation_mode ,
190- self . flags_and_attributes ,
191- 0 ,
192- ) ;
193- self . error_code = GetLastError ( ) ;
194- if handle == INVALID_HANDLE_VALUE {
195- Poll :: Ready ( Err ( io:: Error :: from_raw_os_error ( self . error_code as _ ) ) )
196- } else {
197- Poll :: Ready ( Ok ( handle as _ ) )
198- }
199- }
200- }
201-
202128impl OpCode for CloseFile {
203129 fn op_type ( & self ) -> OpType {
204130 OpType :: Blocking
@@ -209,222 +135,6 @@ impl OpCode for CloseFile {
209135 }
210136}
211137
212- /// A mixture of [`BY_HANDLE_FILE_INFORMATION`], [`FILE_ATTRIBUTE_TAG_INFO`] and
213- /// [`WIN32_FIND_DATAW`]. The field names follows Hungarian case, to make it
214- /// look like Windows API.
215- #[ derive( Default , Clone ) ]
216- #[ allow( non_snake_case, missing_docs) ]
217- pub struct FileMetadata {
218- pub dwFileAttributes : u32 ,
219- pub ftCreationTime : u64 ,
220- pub ftLastAccessTime : u64 ,
221- pub ftLastWriteTime : u64 ,
222- pub nFileSize : u64 ,
223- pub dwReparseTag : u32 ,
224- pub dwVolumeSerialNumber : Option < u32 > ,
225- pub nNumberOfLinks : Option < u32 > ,
226- pub nFileIndex : Option < u64 > ,
227- }
228-
229- impl FileMetadata {
230- fn is_reparse_point ( & self ) -> bool {
231- self . dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT != 0
232- }
233- }
234-
235- const fn create_u64 ( high : u32 , low : u32 ) -> u64 {
236- ( ( high as u64 ) << 32 ) | ( low as u64 )
237- }
238-
239- const fn filetime_u64 ( t : FILETIME ) -> u64 {
240- create_u64 ( t. dwHighDateTime , t. dwLowDateTime )
241- }
242-
243- impl From < BY_HANDLE_FILE_INFORMATION > for FileMetadata {
244- fn from ( value : BY_HANDLE_FILE_INFORMATION ) -> Self {
245- Self {
246- dwFileAttributes : value. dwFileAttributes ,
247- ftCreationTime : filetime_u64 ( value. ftCreationTime ) ,
248- ftLastAccessTime : filetime_u64 ( value. ftLastAccessTime ) ,
249- ftLastWriteTime : filetime_u64 ( value. ftLastWriteTime ) ,
250- nFileSize : create_u64 ( value. nFileSizeHigh , value. nFileSizeLow ) ,
251- dwReparseTag : 0 ,
252- dwVolumeSerialNumber : Some ( value. dwVolumeSerialNumber ) ,
253- nNumberOfLinks : Some ( value. nNumberOfLinks ) ,
254- nFileIndex : Some ( create_u64 ( value. nFileIndexHigh , value. nFileIndexLow ) ) ,
255- }
256- }
257- }
258-
259- impl From < WIN32_FIND_DATAW > for FileMetadata {
260- fn from ( value : WIN32_FIND_DATAW ) -> Self {
261- let mut this = Self {
262- dwFileAttributes : value. dwFileAttributes ,
263- ftCreationTime : filetime_u64 ( value. ftCreationTime ) ,
264- ftLastAccessTime : filetime_u64 ( value. ftLastAccessTime ) ,
265- ftLastWriteTime : filetime_u64 ( value. ftLastWriteTime ) ,
266- nFileSize : create_u64 ( value. nFileSizeHigh , value. nFileSizeLow ) ,
267- dwReparseTag : 0 ,
268- dwVolumeSerialNumber : None ,
269- nNumberOfLinks : None ,
270- nFileIndex : None ,
271- } ;
272- if this. is_reparse_point ( ) {
273- this. dwReparseTag = value. dwReserved0 ;
274- }
275- this
276- }
277- }
278-
279- /// Get metadata of an opened file.
280- pub struct FileStat {
281- pub ( crate ) fd : RawFd ,
282- pub ( crate ) stat : FileMetadata ,
283- }
284-
285- impl FileStat {
286- /// Create [`FileStat`].
287- pub fn new ( fd : RawFd ) -> Self {
288- Self {
289- fd,
290- stat : Default :: default ( ) ,
291- }
292- }
293- }
294-
295- impl OpCode for FileStat {
296- fn op_type ( & self ) -> OpType {
297- OpType :: Blocking
298- }
299-
300- unsafe fn operate ( mut self : Pin < & mut Self > , _optr : * mut OVERLAPPED ) -> Poll < io:: Result < usize > > {
301- let mut stat = unsafe { std:: mem:: zeroed ( ) } ;
302- syscall ! ( BOOL , GetFileInformationByHandle ( self . fd as _, & mut stat) ) ?;
303- self . stat = stat. into ( ) ;
304- if self . stat . is_reparse_point ( ) {
305- let mut tag: FILE_ATTRIBUTE_TAG_INFO = std:: mem:: zeroed ( ) ;
306- syscall ! (
307- BOOL ,
308- GetFileInformationByHandleEx (
309- self . fd as _,
310- FileAttributeTagInfo ,
311- & mut tag as * mut _ as _,
312- std:: mem:: size_of:: <FILE_ATTRIBUTE_TAG_INFO >( ) as _
313- )
314- ) ?;
315- debug_assert_eq ! ( self . stat. dwFileAttributes, tag. FileAttributes ) ;
316- self . stat . dwReparseTag = tag. ReparseTag ;
317- }
318- Poll :: Ready ( Ok ( 0 ) )
319- }
320-
321- unsafe fn cancel ( self : Pin < & mut Self > , _optr : * mut OVERLAPPED ) -> io:: Result < ( ) > {
322- Ok ( ( ) )
323- }
324- }
325-
326- impl IntoInner for FileStat {
327- type Inner = FileMetadata ;
328-
329- fn into_inner ( self ) -> Self :: Inner {
330- self . stat
331- }
332- }
333-
334- /// Get metadata from path.
335- pub struct PathStat {
336- pub ( crate ) path : U16CString ,
337- pub ( crate ) follow_symlink : bool ,
338- pub ( crate ) stat : FileMetadata ,
339- }
340-
341- impl PathStat {
342- /// Create [`PathStat`].
343- pub fn new ( path : U16CString , follow_symlink : bool ) -> Self {
344- Self {
345- path,
346- follow_symlink,
347- stat : Default :: default ( ) ,
348- }
349- }
350-
351- unsafe fn open_and_stat ( & self , optr : * mut OVERLAPPED ) -> io:: Result < FileMetadata > {
352- let mut flags = FILE_FLAG_BACKUP_SEMANTICS ;
353- if !self . follow_symlink {
354- flags |= FILE_FLAG_OPEN_REPARSE_POINT ;
355- }
356- let handle = syscall ! (
357- HANDLE ,
358- CreateFileW (
359- self . path. as_ptr( ) ,
360- 0 ,
361- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
362- null( ) ,
363- OPEN_EXISTING ,
364- flags,
365- 0
366- )
367- ) ?;
368- let handle = OwnedHandle :: from_raw_handle ( handle as _ ) ;
369- let mut op = FileStat :: new ( handle. as_raw_handle ( ) ) ;
370- let op_pin = std:: pin:: Pin :: new ( & mut op) ;
371- let res = op_pin. operate ( optr) ;
372- if let Poll :: Ready ( res) = res {
373- res. map ( |_| op. into_inner ( ) )
374- } else {
375- unreachable ! ( "FileStat could not return Poll::Pending" )
376- }
377- }
378- }
379-
380- impl OpCode for PathStat {
381- fn op_type ( & self ) -> OpType {
382- OpType :: Blocking
383- }
384-
385- unsafe fn operate ( mut self : Pin < & mut Self > , optr : * mut OVERLAPPED ) -> Poll < io:: Result < usize > > {
386- let res = match self . open_and_stat ( optr) {
387- Ok ( stat) => {
388- self . stat = stat;
389- Ok ( 0 )
390- }
391- Err ( e)
392- if [
393- Some ( ERROR_SHARING_VIOLATION as _ ) ,
394- Some ( ERROR_ACCESS_DENIED as _ ) ,
395- ]
396- . contains ( & e. raw_os_error ( ) ) =>
397- {
398- let mut wfd: WIN32_FIND_DATAW = std:: mem:: zeroed ( ) ;
399- let handle = syscall ! ( HANDLE , FindFirstFileW ( self . path. as_ptr( ) , & mut wfd) ) ?;
400- FindClose ( handle) ;
401- self . stat = wfd. into ( ) ;
402- let is_reparse = self . stat . is_reparse_point ( ) ;
403- let surrogate = self . stat . dwReparseTag & 0x20000000 != 0 ;
404- if self . follow_symlink && is_reparse && surrogate {
405- Err ( e)
406- } else {
407- Ok ( 0 )
408- }
409- }
410- Err ( e) => Err ( e) ,
411- } ;
412- Poll :: Ready ( res)
413- }
414-
415- unsafe fn cancel ( self : Pin < & mut Self > , _optr : * mut OVERLAPPED ) -> io:: Result < ( ) > {
416- Ok ( ( ) )
417- }
418- }
419-
420- impl IntoInner for PathStat {
421- type Inner = FileMetadata ;
422-
423- fn into_inner ( self ) -> Self :: Inner {
424- self . stat
425- }
426- }
427-
428138impl < T : IoBufMut > OpCode for ReadAt < T > {
429139 unsafe fn operate ( self : Pin < & mut Self > , optr : * mut OVERLAPPED ) -> Poll < io:: Result < usize > > {
430140 if let Some ( overlapped) = optr. as_mut ( ) {
0 commit comments