May 8th, 2026
heartintriguinglike4 reactions

Developing more confidence when tracking renames via Read­Directory­ChangesW

A customer was using Read­Directory­ChangesW to monitor the contents of a directory, and they were concerned about the FILE_ACTION_RENAMED_OLD_FILE and FILE_ACTION_RENAMED_NEW_FILE pair of actions. The documentation doesn’t guarantee that the two always occur consecutively, or even that they always appear in pairs. For peace of mind, the customer was looking for a way to match up each FILE_ACTION_RENAMED_OLD_FILE with a FILE_ACTION_RENAMED_NEW_FILE to make sure they were tracking the rename properly.

Yes, you can do it by switching from Read­Directory­ChangesW. to Read­Directory­Changes­ExW and asking for Read­Directory­Notify­Extended­Information. This produces the FILE_NOTIFY_EXTENDED_INFORMATION structure, and that structure includes the FileId of the affected file. You can then match that up between the FILE_ACTION_RENAMED_OLD_FILE and FILE_ACTION_RENAMED_NEW_FILE to confirm that they are the two halves of the same rename operation.

Topics

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

8 comments

Discussion is closed. Login to edit/delete existing comments.

Sort by :
  • Solomon Ucko

    Maybe it was considered unnecessary?

    https://devblogs.microsoft.com/oldnewthing/20110812-00/?p=9913 says, “The intended purpose of the Read­Directory­ChangesW function is to assist programs like Windows Explorer which display the contents of a directory.”

    So I would assume that Explorer does something like this:
    – FILE_ACTION_RENAMED_OLD_FILE => remove the old entry (unless already filtered out)
    – FILE_ACTION_RENAMED_NEW_FILE => check the file’s metadata and add a new entry accordingly (unless filtered out)

    • LB

      Maybe, but usually Explorer tries to keep the set of selected files stable despite renames. Try it: open the same folder in two different Explorer windows, select some of the files in one window, rename some of the files in the other window, see what happens. I haven’t bothered to check how far back this behavior exists though.

  • LB

    Worth noting, Read­Directory­ChangesW is supported in UWP but Read­Directory­Changes­ExW is not, at least according to the documentation.

  • Brian Dellisanti

    Any insight into why Read­Directory­ChangesW provides the two events without the ability to correlate them? Lack of design review? It required rewriting some part of the kernel, so out of scope?

    • Gunnar Dalsnes

      FAT/FAT32 does not have a FileId. NTFS has. I guess FAT was the s*** back then? I guess they did not want the pain with all the FAT issues and complaints that it does not work on FAT (I assume FileId is always 0 on FAT?)

      • Me Gusta · Edited

        GetFileInformationByHandle gives interesting information on this. The BY_HANDLE_FILE_INFORMATION structure contains two fields, nFileIndexLow and nFileIndexHigh, what's more, it states that the volume serial number and the combined file index uniquely identify a file on a single computer. Without double checking, I would guess that the file ID given by ReadDirectoryChangesExW is this combined file index. GetFileInformationByHandle will also give a file id when you use this with a file on a FAT32 formatted drive. The only quirk that I noticed is that you need to use GetFileInformationByHandle to get the FAT32 file id. GetFileInformationByHandleEx will give an invalid parameter error...

        Read more
    • Me Gusta · Edited

      It could have easily been design considerations based upon when it was introduced.

      ReadDirectoryChangesW was introduced with Windows NT 4. It is in the WinBase.h file found in Visual C++ 5. So any considerations for this function would have been decided upon in the early to mid 90s.

      The other big thing is that in 1996, not only were we still using ATA (not retroactively renamed to PATA, since SATA didn't exist at that point), but the variants that sped things up, like the UDMA modes hadn't been standardised. Even the SCSI standards weren't that much better. So it was very unlikely...

      Read more
    • Tom Lint

      Could be an oversight, just like how AMD forgot to provide a way to retrieve the kernel stack pointer when it created its fast syscall instruction for x86, rendering the instruction virtually unusable, until it was supplemented by the swapgs instruction in the new x86_64 architecture.