@@ -24,13 +24,14 @@ use windows_sys::Win32::Foundation::{
2424 INVALID_HANDLE_VALUE , WAIT_OBJECT_0 ,
2525} ;
2626use windows_sys:: Win32 :: Storage :: FileSystem :: {
27- CreateFileW , ReadDirectoryChangesW , FILE_ACTION_ADDED , FILE_ACTION_MODIFIED ,
28- FILE_ACTION_REMOVED , FILE_ACTION_RENAMED_NEW_NAME , FILE_ACTION_RENAMED_OLD_NAME ,
29- FILE_FLAG_BACKUP_SEMANTICS , FILE_FLAG_OVERLAPPED , FILE_LIST_DIRECTORY ,
30- FILE_NOTIFY_CHANGE_ATTRIBUTES , FILE_NOTIFY_CHANGE_CREATION , FILE_NOTIFY_CHANGE_DIR_NAME ,
31- FILE_NOTIFY_CHANGE_FILE_NAME , FILE_NOTIFY_CHANGE_LAST_WRITE , FILE_NOTIFY_CHANGE_SECURITY ,
32- FILE_NOTIFY_CHANGE_SIZE , FILE_NOTIFY_INFORMATION , FILE_SHARE_DELETE , FILE_SHARE_READ ,
33- FILE_SHARE_WRITE , OPEN_EXISTING ,
27+ CreateFileW , ReadDirectoryChangesExW , ReadDirectoryNotifyExtendedInformation ,
28+ FILE_ACTION_ADDED , FILE_ACTION_MODIFIED , FILE_ACTION_REMOVED , FILE_ACTION_RENAMED_NEW_NAME ,
29+ FILE_ACTION_RENAMED_OLD_NAME , FILE_ATTRIBUTE_DIRECTORY , FILE_FLAG_BACKUP_SEMANTICS ,
30+ FILE_FLAG_OVERLAPPED , FILE_LIST_DIRECTORY , FILE_NOTIFY_CHANGE_ATTRIBUTES ,
31+ FILE_NOTIFY_CHANGE_CREATION , FILE_NOTIFY_CHANGE_DIR_NAME , FILE_NOTIFY_CHANGE_FILE_NAME ,
32+ FILE_NOTIFY_CHANGE_LAST_WRITE , FILE_NOTIFY_CHANGE_SECURITY , FILE_NOTIFY_CHANGE_SIZE ,
33+ FILE_NOTIFY_EXTENDED_INFORMATION , FILE_SHARE_DELETE , FILE_SHARE_READ , FILE_SHARE_WRITE ,
34+ OPEN_EXISTING ,
3435} ;
3536use windows_sys:: Win32 :: System :: Threading :: {
3637 CreateSemaphoreW , ReleaseSemaphore , WaitForSingleObjectEx , INFINITE ,
@@ -305,7 +306,7 @@ fn start_read(
305306
306307 // This is using an asynchronous call with a completion routine for receiving notifications
307308 // An I/O completion port would probably be more performant
308- let ret = ReadDirectoryChangesW (
309+ let ret = ReadDirectoryChangesExW (
309310 handle,
310311 request. buffer . as_mut_ptr ( ) as * mut c_void ,
311312 BUF_SIZE ,
@@ -314,6 +315,7 @@ fn start_read(
314315 & mut 0u32 as * mut u32 , // not used for async reqs
315316 overlapped,
316317 Some ( handle_event) ,
318+ ReadDirectoryNotifyExtendedInformation ,
317319 ) ;
318320
319321 if ret == 0 {
@@ -382,12 +384,13 @@ unsafe extern "system" fn handle_event(
382384 // In Wine, FILE_NOTIFY_INFORMATION structs are packed placed in the buffer;
383385 // they are aligned to 16bit (WCHAR) boundary instead of 32bit required by FILE_NOTIFY_INFORMATION.
384386 // Hence, we need to use `read_unaligned` here to avoid UB.
385- let mut cur_entry = ptr:: read_unaligned ( cur_offset as * const FILE_NOTIFY_INFORMATION ) ;
387+ let mut cur_entry = ptr:: read_unaligned ( cur_offset as * const FILE_NOTIFY_EXTENDED_INFORMATION ) ;
386388 loop {
387389 // filename length is size in bytes, so / 2
388390 let len = cur_entry. FileNameLength as usize / 2 ;
389391 let encoded_path: & [ u16 ] = slice:: from_raw_parts (
390- cur_offset. offset ( std:: mem:: offset_of!( FILE_NOTIFY_INFORMATION , FileName ) as isize )
392+ cur_offset
393+ . offset ( std:: mem:: offset_of!( FILE_NOTIFY_EXTENDED_INFORMATION , FileName ) as isize )
391394 as _ ,
392395 len,
393396 ) ;
@@ -422,44 +425,49 @@ unsafe extern "system" fn handle_event(
422425
423426 let event_handler = |res| emit_event ( & request. event_handler , res) ;
424427
425- if cur_entry. Action == FILE_ACTION_RENAMED_OLD_NAME {
426- let mode = RenameMode :: From ;
427- let kind = ModifyKind :: Name ( mode) ;
428- let kind = EventKind :: Modify ( kind) ;
429- let ev = newe. set_kind ( kind) ;
430- event_handler ( Ok ( ev) )
431- } else {
432- match cur_entry. Action {
433- FILE_ACTION_RENAMED_NEW_NAME => {
434- let kind = EventKind :: Modify ( ModifyKind :: Name ( RenameMode :: To ) ) ;
435- let ev = newe. set_kind ( kind) ;
436- event_handler ( Ok ( ev) ) ;
437- }
438- FILE_ACTION_ADDED => {
439- let kind = EventKind :: Create ( CreateKind :: Any ) ;
440- let ev = newe. set_kind ( kind) ;
441- event_handler ( Ok ( ev) ) ;
442- }
443- FILE_ACTION_REMOVED => {
444- let kind = EventKind :: Remove ( RemoveKind :: Any ) ;
445- let ev = newe. set_kind ( kind) ;
446- event_handler ( Ok ( ev) ) ;
447- }
448- FILE_ACTION_MODIFIED => {
449- let kind = EventKind :: Modify ( ModifyKind :: Any ) ;
450- let ev = newe. set_kind ( kind) ;
451- event_handler ( Ok ( ev) ) ;
452- }
453- _ => ( ) ,
454- } ;
455- }
428+ match cur_entry. Action {
429+ FILE_ACTION_RENAMED_OLD_NAME => {
430+ let kind = EventKind :: Modify ( ModifyKind :: Name ( RenameMode :: From ) ) ;
431+ let ev = newe. set_kind ( kind) ;
432+ event_handler ( Ok ( ev) )
433+ }
434+ FILE_ACTION_RENAMED_NEW_NAME => {
435+ let kind = EventKind :: Modify ( ModifyKind :: Name ( RenameMode :: To ) ) ;
436+ let ev = newe. set_kind ( kind) ;
437+ event_handler ( Ok ( ev) ) ;
438+ }
439+ FILE_ACTION_ADDED => {
440+ let kind = if ( cur_entry. FileAttributes & FILE_ATTRIBUTE_DIRECTORY ) != 0 {
441+ EventKind :: Create ( CreateKind :: Folder )
442+ } else {
443+ EventKind :: Create ( CreateKind :: File )
444+ } ;
445+ let ev = newe. set_kind ( kind) ;
446+ event_handler ( Ok ( ev) ) ;
447+ }
448+ FILE_ACTION_REMOVED => {
449+ let kind = if ( cur_entry. FileAttributes & FILE_ATTRIBUTE_DIRECTORY ) != 0 {
450+ EventKind :: Remove ( RemoveKind :: Folder )
451+ } else {
452+ EventKind :: Remove ( RemoveKind :: File )
453+ } ;
454+ let ev = newe. set_kind ( kind) ;
455+ event_handler ( Ok ( ev) ) ;
456+ }
457+ FILE_ACTION_MODIFIED => {
458+ let kind = EventKind :: Modify ( ModifyKind :: Any ) ;
459+ let ev = newe. set_kind ( kind) ;
460+ event_handler ( Ok ( ev) ) ;
461+ }
462+ _ => ( ) ,
463+ } ;
456464 }
457465
458466 if cur_entry. NextEntryOffset == 0 {
459467 break ;
460468 }
461469 cur_offset = cur_offset. offset ( cur_entry. NextEntryOffset as isize ) ;
462- cur_entry = ptr:: read_unaligned ( cur_offset as * const FILE_NOTIFY_INFORMATION ) ;
470+ cur_entry = ptr:: read_unaligned ( cur_offset as * const FILE_NOTIFY_EXTENDED_INFORMATION ) ;
463471 }
464472}
465473
0 commit comments