@@ -24,12 +24,13 @@ 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 ,
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_NOTIFY_INFORMATION , FILE_SHARE_DELETE , FILE_SHARE_READ ,
3334 FILE_SHARE_WRITE , OPEN_EXISTING ,
3435} ;
3536use windows_sys:: Win32 :: System :: Threading :: {
@@ -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,7 +384,7 @@ 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 ;
@@ -422,44 +424,49 @@ unsafe extern "system" fn handle_event(
422424
423425 let event_handler = |res| emit_event ( & request. event_handler , res) ;
424426
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- }
427+ match cur_entry. Action {
428+ FILE_ACTION_RENAMED_OLD_NAME => {
429+ let kind = EventKind :: Modify ( ModifyKind :: Name ( RenameMode :: From ) ) ;
430+ let ev = newe. set_kind ( kind) ;
431+ event_handler ( Ok ( ev) )
432+ }
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 = if ( cur_entry. FileAttributes & FILE_ATTRIBUTE_DIRECTORY ) != 0 {
440+ EventKind :: Create ( CreateKind :: Folder )
441+ } else {
442+ EventKind :: Create ( CreateKind :: File )
443+ } ;
444+ let ev = newe. set_kind ( kind) ;
445+ event_handler ( Ok ( ev) ) ;
446+ }
447+ FILE_ACTION_REMOVED => {
448+ let kind = if ( cur_entry. FileAttributes & FILE_ATTRIBUTE_DIRECTORY ) != 0 {
449+ EventKind :: Remove ( RemoveKind :: Folder )
450+ } else {
451+ EventKind :: Remove ( RemoveKind :: File )
452+ } ;
453+ let ev = newe. set_kind ( kind) ;
454+ event_handler ( Ok ( ev) ) ;
455+ }
456+ FILE_ACTION_MODIFIED => {
457+ let kind = EventKind :: Modify ( ModifyKind :: Any ) ;
458+ let ev = newe. set_kind ( kind) ;
459+ event_handler ( Ok ( ev) ) ;
460+ }
461+ _ => ( ) ,
462+ } ;
456463 }
457464
458465 if cur_entry. NextEntryOffset == 0 {
459466 break ;
460467 }
461468 cur_offset = cur_offset. offset ( cur_entry. NextEntryOffset as isize ) ;
462- cur_entry = ptr:: read_unaligned ( cur_offset as * const FILE_NOTIFY_INFORMATION ) ;
469+ cur_entry = ptr:: read_unaligned ( cur_offset as * const FILE_NOTIFY_EXTENDED_INFORMATION ) ;
463470 }
464471}
465472
0 commit comments