Saturday, 9 September 2017

How to monitor a folder in windows using c++

A folder monitor can be used for the surveillance of files/folders and will notify you of file/folder changes, access, deletions, modifications, new files and inactivity in real-time. Users and processes making the changes can also be detected. A c++ code is given below to show how we can monitor a folder in windows operating system.

Source Code:

#define _CRT_SECURE_NO_WARNINGS
#define MAX_DIRS 25
#define MAX_FILES 255
#define MAX_BUFFER 4096

#include <Windows.h>
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <string> 

extern "C" {
       WINBASEAPI BOOL WINAPI
              ReadDirectoryChangesW(HANDLE hDirectory,
              LPVOID lpBuffer, DWORD nBufferLength,
              BOOL bWatchSubtree, DWORD dwNotifyFilter,
              LPDWORD lpBytesReturned,
              LPOVERLAPPED lpOverlapped,
              LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
              );
}

// all purpose structure to contain directory information and provide
// the input buffer that is filled with file change data

typedef struct _DIRECTORY_INFO {
       HANDLE hDir;
       TCHAR lpszDirName[MAX_PATH];
       CHAR lpBuffer[MAX_BUFFER];
       DWORD dwBufLength;
       OVERLAPPED Overlapped;
}DIRECTORY_INFO, *PDIRECTORY_INFO, *LPDIRECTORY_INFO;

DIRECTORY_INFO DirInfo[MAX_DIRS];   // Buffer for of the directory


void WatchDirectory(LPCWSTR path)
{
       char buf[2048];
       DWORD nRet;
       BOOL result = TRUE;
       char filename[MAX_PATH];
       DirInfo[0].hDir = CreateFileW(
              path,
              GENERIC_READ | FILE_LIST_DIRECTORY,
              FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
              NULL,
              OPEN_EXISTING,
              FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
              NULL
              );

       if (DirInfo[0].hDir == INVALID_HANDLE_VALUE)
       {
              return//cannot open folder
       }

       lstrcpy(DirInfo[0].lpszDirName, path);
       OVERLAPPED PollingOverlap;

       FILE_NOTIFY_INFORMATION* pNotify;
       int offset;
       PollingOverlap.OffsetHigh = 0;
       PollingOverlap.hEvent = CreateEvent(NULLTRUEFALSENULL);
       while (result)
       {
              result = ReadDirectoryChangesW(
                     DirInfo[0].hDir,// handle to the directory to be watched
                     &buf,// pointer to the buffer to receive the read results
                     sizeof(buf),// length of lpBuffer
                     TRUE,// flag for monitoring directory or directory tree
                     FILE_NOTIFY_CHANGE_FILE_NAME |
                     FILE_NOTIFY_CHANGE_DIR_NAME |
                     FILE_NOTIFY_CHANGE_SIZE |
                     FILE_NOTIFY_CHANGE_LAST_WRITE |
                     FILE_NOTIFY_CHANGE_LAST_ACCESS |
                     FILE_NOTIFY_CHANGE_CREATION,
                     &nRet,// number of bytes returned
                     &PollingOverlap,// pointer to structure needed for overlapped I/O
                     NULL);

              WaitForSingleObject(PollingOverlap.hEvent, INFINITE);
              offset = 0;
              int rename = 0;

              do
              {
                     pNotify = (FILE_NOTIFY_INFORMATION*)((char*)buf + offset);
                     strcpy(filename, "");
                     int filenamelen = WideCharToMultiByte(
                           CP_ACP,
                           0,
                           pNotify->FileName,
                           pNotify->FileNameLength / 2,
                           filename,
                           sizeof(filename),
                           NULL,
                           NULL
                           );
                     //filename[pNotify->FileNameLength / 2] = ` `;

                     for (size_t i = pNotify->FileNameLength / 2; i < 260; i++)
                     {
                           filename[i] = `\0`;
                     }

                     switch (pNotify->Action)
                     {
                     case FILE_ACTION_ADDED:
printf("\nThe file is added to the directory: [%s] \n", filename);
                           break;
                     case FILE_ACTION_REMOVED:
printf("\nThe file is removed from the directory: [%s] \n", filename);
                           break;
                     case FILE_ACTION_MODIFIED:
printf("\nThe file is modified. This can be a change in the time stamp or attributes: [%s]\n", filename);
                           break;
                     case FILE_ACTION_RENAMED_OLD_NAME:
printf("\nThe file was renamed and this is the old name: [%s]\n", filename);
                           break;
                     case FILE_ACTION_RENAMED_NEW_NAME:
printf("\nThe file was renamed and this is the new name: [%s]\n", filename);
                           break;
                     default:
                           printf("\nDefault error.\n");
                           break;
                     }

                     offset += pNotify->NextEntryOffset;

              } while (pNotify->NextEntryOffset); //(offset != 0);
       }

       CloseHandle(DirInfo[0].hDir);

}

int main()
{
       WatchDirectory(L"c:\\");
       return 0;
}

Output: