ReadDirectoryChangesW function (Windows)

Switch View :
ScriptFree
ReadDirectoryChangesW function

Applies to: desktop apps only

Retrieves information that describes the changes within the specified directory. The function does not report changes to the specified directory itself.

To track changes on a volume, see change journals.

Syntax

BOOL WINAPI ReadDirectoryChangesW(
  __in         HANDLE hDirectory,
  __out        LPVOID lpBuffer,
  __in         DWORD nBufferLength,
  __in         BOOL bWatchSubtree,
  __in         DWORD dwNotifyFilter,
  __out_opt    LPDWORD lpBytesReturned,
  __inout_opt  LPOVERLAPPED lpOverlapped,
  __in_opt     LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

Parameters

hDirectory [in]

A handle to the directory to be monitored. This directory must be opened with the FILE_LIST_DIRECTORY access right.

lpBuffer [out]

A pointer to the DWORD-aligned formatted buffer in which the read results are to be returned. The structure of this buffer is defined by the FILE_NOTIFY_INFORMATION structure. This buffer is filled either synchronously or asynchronously, depending on how the directory is opened and what value is given to the lpOverlapped parameter. For more information, see the Remarks section.

nBufferLength [in]

The size of the buffer that is pointed to by the lpBuffer parameter, in bytes.

bWatchSubtree [in]

If this parameter is TRUE, the function monitors the directory tree rooted at the specified directory. If this parameter is FALSE, the function monitors only the directory specified by the hDirectory parameter.

dwNotifyFilter [in]

The filter criteria that the function checks to determine if the wait operation has completed. This parameter can be one or more of the following values.

ValueMeaning
FILE_NOTIFY_CHANGE_FILE_NAME
0x00000001

Any file name change in the watched directory or subtree causes a change notification wait operation to return. Changes include renaming, creating, or deleting a file.

FILE_NOTIFY_CHANGE_DIR_NAME
0x00000002

Any directory-name change in the watched directory or subtree causes a change notification wait operation to return. Changes include creating or deleting a directory.

FILE_NOTIFY_CHANGE_ATTRIBUTES
0x00000004

Any attribute change in the watched directory or subtree causes a change notification wait operation to return.

FILE_NOTIFY_CHANGE_SIZE
0x00000008

Any file-size change in the watched directory or subtree causes a change notification wait operation to return. The operating system detects a change in file size only when the file is written to the disk. For operating systems that use extensive caching, detection occurs only when the cache is sufficiently flushed.

FILE_NOTIFY_CHANGE_LAST_WRITE
0x00000010

Any change to the last write-time of files in the watched directory or subtree causes a change notification wait operation to return. The operating system detects a change to the last write-time only when the file is written to the disk. For operating systems that use extensive caching, detection occurs only when the cache is sufficiently flushed.

FILE_NOTIFY_CHANGE_LAST_ACCESS
0x00000020

Any change to the last access time of files in the watched directory or subtree causes a change notification wait operation to return.

FILE_NOTIFY_CHANGE_CREATION
0x00000040

Any change to the creation time of files in the watched directory or subtree causes a change notification wait operation to return.

FILE_NOTIFY_CHANGE_SECURITY
0x00000100

Any security-descriptor change in the watched directory or subtree causes a change notification wait operation to return.

 

lpBytesReturned [out, optional]

For synchronous calls, this parameter receives the number of bytes transferred into the lpBuffer parameter. For asynchronous calls, this parameter is undefined. You must use an asynchronous notification technique to retrieve the number of bytes transferred.

lpOverlapped [in, out, optional]

A pointer to an OVERLAPPED structure that supplies data to be used during asynchronous operation. Otherwise, this value is NULL. The Offset and OffsetHigh members of this structure are not used.

lpCompletionRoutine [in, optional]

A pointer to a completion routine to be called when the operation has been completed or canceled and the calling thread is in an alertable wait state. For more information about this completion routine, see FileIOCompletionRoutine.

Return value

If the function succeeds, the return value is nonzero. For synchronous calls, this means that the operation succeeded. For asynchronous calls, this indicates that the operation was successfully queued.

If the function fails, the return value is zero. To get extended error information, call GetLastError.

If the network redirector or the target file system does not support this operation, the function fails with ERROR_INVALID_FUNCTION.

Remarks

To obtain a handle to a directory, use the CreateFile function with the FILE_FLAG_BACKUP_SEMANTICS flag.

A call to ReadDirectoryChangesW can be completed synchronously or asynchronously. To specify asynchronous completion, open the directory with CreateFile as shown above, but additionally specify the FILE_FLAG_OVERLAPPED attribute in the dwFlagsAndAttributes parameter. Then specify an OVERLAPPED structure when you call ReadDirectoryChangesW.

When you first call ReadDirectoryChangesW, the system allocates a buffer to store change information. This buffer is associated with the directory handle until it is closed and its size does not change during its lifetime. Directory changes that occur between calls to this function are added to the buffer and then returned with the next call. If the buffer overflows, the entire contents of the buffer are discarded and the lpBytesReturned parameter contains zero.

Upon successful synchronous completion, the lpBuffer parameter is a formatted buffer and the number of bytes written to the buffer is available in lpBytesReturned. If the number of bytes transferred is zero, the buffer was either too large for the system to allocate or too small to provide detailed information on all the changes that occurred in the directory or subtree. In this case, you should compute the changes by enumerating the directory or subtree.

For asynchronous completion, you can receive notification in one of three ways:

  • Using the GetOverlappedResult function. To receive notification through GetOverlappedResult, do not specify a completion routine in the lpCompletionRoutine parameter. Be sure to set the hEvent member of the OVERLAPPED structure to a unique event.
  • Using the GetQueuedCompletionStatus function. To receive notification through GetQueuedCompletionStatus, do not specify a completion routine in lpCompletionRoutine. Associate the directory handle hDirectory with a completion port by calling the CreateIoCompletionPort function.
  • Using a completion routine. To receive notification through a completion routine, do not associate the directory with a completion port. Specify a completion routine in lpCompletionRoutine. This routine is called whenever the operation has been completed or canceled while the thread is in an alertable wait state. The hEvent member of the OVERLAPPED structure is not used by the system, so you can use it yourself.

For more information, see Synchronous and Asynchronous I/O.

ReadDirectoryChangesW fails with ERROR_INVALID_PARAMETER when the buffer length is greater than 64 KB and the application is monitoring a directory over the network. This is due to a packet size limitation with the underlying file sharing protocols.

ReadDirectoryChangesW fails with ERROR_NOACCESS when the buffer is not aligned on a DWORD boundary.

If you opened the file using the short name, you can receive change notifications for the short name.

Transacted Operations

If there is a transaction bound to the directory handle, then the notifications follow the appropriate transaction isolation rules.

Requirements

Minimum supported client

Windows XP

Minimum supported server

Windows Server 2003

Header

WinBase.h (include Windows.h)

Library

Kernel32.lib

DLL

Kernel32.dll

See also

CreateFile
CreateIoCompletionPort
Directory Management Functions
FileIOCompletionRoutine
GetOverlappedResult
GetQueuedCompletionStatus
FILE_NOTIFY_INFORMATION
OVERLAPPED

 

 

Send comments about this topic to Microsoft

Build date: 4/17/2012

Community Content

ArnoudMulder
FindFirstChangeNotification handle as input for ReadDirectoryChangesW
what undocumented is, is that you can also use a FindFirstChangeNotification handle in the call to ReadDirectoryChangesW

so this works:

lv_hDirNotify = FindFirstChangeNotification(... lv_hEvent);

...

if (WaitForSingleObject(lv_hEvent, INFINITE) == 0)
{
ReadDirectoryChangesW(lv_hDirNotify, ...);

FindNextChangeNotification(lv_hDirNotify);
}


tested on XP-SP3


.. althrough there is some mixup as Findxxx gives faster/more notifications then Readxxx and therefore the Readxxx will hang after some changes

Sven Olsen
DWORD alignment wierdness
$0$0 the docs state that if lpBuffer is not DWORD aligned, ReadDirectoryChangesW will error with ERROR_NOACCESS.  this appears to be wrong.  my own experience (using windows 7 and GetOverlappedResult), has been that non-DWORD aligned calls appear to succeed, but, subsequent GetOverlappedResult calls always return false, ERROR_IO_INCOMPLETE, regardless of how many modifications have been made to the directory.  i.e., using a non-aligned pointer causes file change notification to silently fail.

Honorary_BoT
VirtualAlloc buffer note
You will also get ERROR_NOACCESS if you use buffer given by VirtualAlloc function with MEM_RESERVE flag. Use MEM_COMMIT instead.

bobby_newmark
Is it possible to change the watch parameters after the first call to ReadDirectoryChangesW()?
Is it possible to change the watch parameters for a given directory after the first call to ReadDirectoryChangesW()?

In my program, the first ReadDirectoryChangesW() had bWatchSubtree==FALSE, and the next call has bWatchSubtree==TRUE. However, subdirectory changes are still not being returned by the function.

Details:

1. I create the handle with CreateFile() with backup semantics and the overlapped flag set.
2. I call ReadDirectoryChangesW() to issue the read operation with bWatchSubtree==FALSE and an OVERLAPPED struct
3. After a while, the user decides to change the mode for watching the directory
4. I call CancelIo() so I can issue another read request with a different mode
5. I call ReadDirectoryChangesW() again, this time with bWatchSubtree==TRUE
6. I call WaitForMultipleObjects to wait for the event handle associated with the OVERLAPPED structure

The problem here is that after step 6, I still don't receive events from a changes in subdirectories. However, events are still generated for direct children of the watched directory, indicating that the the new bWatchSubtree value given in the second call to ReadDirectoryChangesW() didn't propagate through to the watched mechanism.

So I receive changes to watchdir/file, but no changes to watchdir/subdir/file. When I issue the first call with bWatcheSubtree, things work fine.

What am I doing wrong? Or is it simply not possible to change the parameters of an open watch directory?

Cheers,

Uwe

arghhhhhhhhhhh
System buffer size clarification
"When you first call ReadDirectoryChangesW, the system allocates a buffer to store change information."
The size of the allocated kernel buffer is the same size that is specified in ReadDirectoryChangesW. The buffer is allocated by the file system driver in non-paged pooled memory, so the buffer size must be tuned: if you are watching just a few dirs, a larger buffer is ok, but if you are watching a _lot_ of dirs, a large buffer may exhaust the non-paged pool and BSOD your system.

wtheronjones
See my ReadDirectoryChangesW article on codeproject.com

For a fully working & reusable example of ReadDirectoryChangesW in C++, see my article on CodeProject.com: 

CDirectoryChangeWatcher - ReadDirectoryChangesW all wrapped up
By Wes Jones

http://www.codeproject.com/file/directorychangewatcher.asp

Uses CreateIoCompletionPort & GetQueuedCompletionStatus APIs as well.

Enjoy,
Wes