Monitoring directory using ReadDirectoryChangesW API

4.5k views Asked by At

I am trying to monitor a directory e:\test using ReadDirectoryChangesW API.

My Code :

#define UNICODE
#define WIN32_WINNT 0x0500
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>


HANDLE hDir;


int _tmain(int argc, _TCHAR* argv[])
{
    FILE_NOTIFY_INFORMATION fniDir;
    DWORD i = 0;

    hDir = CreateFile(_T("e:\\test"), GENERIC_READ , FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

    ReadDirectoryChangesW(hDir, &fniDir, sizeof(fniDir), TRUE, FILE_NOTIFY_CHANGE_FILE_NAME, &i, NULL, NULL);
    while(TRUE)
    {


    if(i>0)
        wprintf(L"%s", fniDir.FileName);
    }

    CloseHandle(hDir);

    return 0;
}

I don't know what's wrong with my code as I haven't understood ReadDirectoryChangesW documentation completely, specially the LPOVERLAPPED parameters.

When I run the code I don't get any output, except for a blank console window. Can someone point me in a right direction?

Thanks.

1

There are 1 answers

4
RedX On BEST ANSWER

You only need the overlapped struct if you plan on catching the changes notifications asynchronously. In your code you don't need it.

Here's how you do it.

HANDLE hDir = CreateFile( 
        p.string().c_str(), /* pointer to the file name */
        FILE_LIST_DIRECTORY,                /* (this is important to be FILE_LIST_DIRECTORY!) access (read-write) mode */
        FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,  /* (file share write is needed, or else user is not able to rename file while you hold it) share mode */
        NULL, /* security descriptor */
        OPEN_EXISTING, /* how to create */
        FILE_FLAG_BACKUP_SEMANTICS, /* file attributes */
        NULL /* file with attributes to copy */
        );

    if(hDir == INVALID_HANDLE_VALUE){
        throw runtime_error(string("Could not open ").append(p.string()).append(" for watching!"));
    }

    FILE_NOTIFY_INFORMATION buffer[1024];
    DWORD BytesReturned;
    while( ReadDirectoryChangesW(
        hDir, /* handle to directory */
        &buffer, /* read results buffer */
        sizeof(buffer), /* length of buffer */
        TRUE, /* monitoring option */           
        FILE_NOTIFY_CHANGE_LAST_WRITE, /* filter conditions */
        &BytesReturned, /* bytes returned */
        NULL, /* overlapped buffer */
        NULL)){
            do{
                            //CANT DO THIS! FileName is NOT \0 terminated
                //wprintf("file: %s\n",buffer.FileName);
                            buffer += buffer.NextEntryOffset;
            }while(buffer.NextEntryOffset);
    }