2012年9月12日星期三

ReadDirectoryChangesW.Cpp


/*
监控目录的变化的办法有:
1.SHChangeNotifyRegister,SHChangeNotify,没有路径信息。
2.FindFirstChangeNotification和FindNextChangeNotification没有变化的类型。
3.ReadDirectoryChangesW有时会遗漏信息,可以结合使用完成例程,i/o端口(CreateIoCompletionPort)等异步多线程措施。
4.Change Journal(USN Journal)只能在NTFS,REFS上。
5.文件系统过滤驱动
6.hook api and messages.
7.其他(如备份一份,周期的比较).
8.ICopyHokk接口的回调函数.
*/

#include <Windows.h>
#include <locale.h>

int _tmain(int argc, _TCHAR* argv[])
{
    setlocale(LC_CTYPE, ".936");
 
    int nBufferSize = 1024;
    char* buffer = new char[nBufferSize];

    HANDLE hDirectoryHandle = CreateFile(L"e:\\test",FILE_LIST_DIRECTORY,FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        0,OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,0);
    if(!hDirectoryHandle)    return 0;

    while(1)
    {
        memset(buffer, 0, nBufferSize);

        DWORD dwBytes = 0;
        if(!::ReadDirectoryChangesW(hDirectoryHandle,buffer,nBufferSize,1,          
            FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SIZE,
            &dwBytes,NULL,NULL) || GetLastError() == ERROR_INVALID_HANDLE) {
                break;
        }

        if(!dwBytes)   {
            printf("Buffer overflow\r\n");
        }

        PFILE_NOTIFY_INFORMATION record = (PFILE_NOTIFY_INFORMATION)buffer;
        DWORD cbOffset = 0;

        do
        {
            switch (record->Action)
            {
            case FILE_ACTION_ADDED:
                printf("添加:");
                break;
            case FILE_ACTION_REMOVED:
                printf("移除:");
                break;
            case FILE_ACTION_MODIFIED:
                printf("修改:");
                break;
            case FILE_ACTION_RENAMED_OLD_NAME:
                printf("旧名字:");
                break;
            case FILE_ACTION_RENAMED_NEW_NAME:
                printf("新名字:");
                break;
            default:
                break;
            }

            wprintf(record->FileName); printf("\r\n");

            cbOffset = record->NextEntryOffset;
            record = (PFILE_NOTIFY_INFORMATION)((LPBYTE) record + cbOffset);
        }while(cbOffset);
    }

    delete buffer;
    if(hDirectoryHandle)   CloseHandle(hDirectoryHandle);

    return 0;
}