Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Spying a file system

0.00/5 (No votes)
22 Sep 2003 19  
Article describes how to create a file system spy application

Introduction

Windows applications can do dynamic monitoring of any specified directory. Once changes have occurred and are detected, the spy application can run various tasks ( run antivirus, log activity, determine more information about changes, call other tasks etc).

Win 32 API provides three functions that are based on the events:

  • FindFirstChangeNotification
  • FindNextChangeNotification
  • FindCloseChangeNotification
  • ReadDirectoryChangesW

These allow creating watchdog or spying applications.

How to create

First of all spy application should call FindFirstChangeNotification to create event handler to monitor changes specified as the functions parameters.

HANDLE h = FindFirtsChangeNotification("C:\\Program Files�, TRUE, mask); 

This function allows to handle following types of notifications:

  • FILE_NOTIFY_CHANGE_FILE_NAME � File creating, deleting and file name changing

  • FILE_NOTIFY_CHANGE_DIR_NAME � Directories creating, deleting and file name changing

  • FILE_NOTIFY_CHANGE_ATTRIBUTES � File or Directory attributes changing

  • FILE_NOTIFY_CHANGE_SIZE � File size changing

  • FILE_NOTIFY_CHANGE_LAST_WRITE � Changing time of write of the files

  • FILE_NOTIFY_CHANGE_SECURITY � Changing in security descriptors

The result of FindFirstChangeNotification can be passed as parameter in to WaitForSingleObject and when specified event has occurred, application can do various actions such as: antivirus starting, adding record to the log file, and so on. Note that this function does not detect changes, it only creates synchronization event and marks it if changes are made. After our spy application handles changes, it should call FindNextChangeNotification to continue monitoring or FindCloseChangeNotification to finish it.

Win32 API provides also ReadDirectoryChangesW that can operate with following filters (MSDN) :

FILE_NOTIFY_CHANGE_FILE_NAME

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

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

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

FILE_NOTIFY_CHANGE_SIZE

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

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

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

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

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

Sample

Give your attention to the following code in the demo project:

void ThreadRoute( void* arg )
{
 HANDLE file = FindFirstChangeNotification("c:\\Program Files", 
     FALSE, (DWORD)((Param*)arg)->parameter);
 WaitForSingleObject(file, INFINITE);
 CTime tm = CTime::GetCurrentTime();
 m_Sec.Lock(); // Enter to Critical section for display notification

 int item = pList->InsertItem(pList->GetItemCount(), ((Param*)arg)->message);
 pList->SetItemText(item, 1, tm.Format("%Y/%m/%d - %H:%M:%S"));
 m_Sec.Unlock();

 while (true)
 {
   FindNextChangeNotification(file);
   WaitForSingleObject(file, INFINITE);
   tm = CTime::GetCurrentTime();
   m_Sec.Lock(); // Enter to Critical section for display notification

   item = pList->InsertItem(pList->GetItemCount(), ((Param*)arg)->message);
   pList->SetItemText(item, 1, tm.Format("%Y/%m/%d/ - %H:%M:%S"));
   m_Sec.Unlock();
  }
}

and here is the fragment using ReadDirectoryChangesW

void ThreadRoute1( void* arg ) 
 {
  USES_CONVERSION;
  HANDLE hDir = CreateFile( 
    CString("c:\\Program Files"), /* pointer to the file name */
    FILE_LIST_DIRECTORY,                /* access (read-write) mode */
    FILE_SHARE_READ|FILE_SHARE_DELETE,  /* share mode */
    NULL, /* security descriptor */
    OPEN_EXISTING, /* how to create */
    FILE_FLAG_BACKUP_SEMANTICS, /* file attributes */
    NULL /* file with attributes to copy */
  );

  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_SECURITY|
     FILE_NOTIFY_CHANGE_CREATION|
     FILE_NOTIFY_CHANGE_LAST_ACCESS|
     FILE_NOTIFY_CHANGE_LAST_WRITE|
     FILE_NOTIFY_CHANGE_SIZE|
     FILE_NOTIFY_CHANGE_ATTRIBUTES|
     FILE_NOTIFY_CHANGE_DIR_NAME|
     FILE_NOTIFY_CHANGE_FILE_NAME, /* filter conditions */
     &BytesReturned, /* bytes returned */
     NULL, /* overlapped buffer */
     NULL))... /* completion routine */

These are thread functions that do the described spying actions.

Conclusion

The attached Demo application starts separate threads to monitor all possible changes in the "c:\\Program Files" directory and shows occurred notifications and its date/time in the List control. Demo application shows also how to use ReadDirectoryChangesW and compare both methods visually.

Functionality of the Demo application can be extended to determine concrete changes, to log changes in to file, run external applications or tasks on the specified event, use described methods as system service and so on. Readers have full freedom to modify and use the demo project.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here