root/honeybow/trunk/mwwatcher/src/DirectoryChanges.h
| Revision 670, 22.8 kB (checked in by chengyu, 2 years ago) |
|---|
| Line | |
|---|---|
| 1 | // DirectoryChanges.h |
| 2 | // |
| 3 | // Interface for the CDirectoryChangeWatcher and CDirectoryChangeHandler classes. |
| 4 | // Copyright (C) 2001. Wes Jones (wesj@hotmail.com) |
| 5 | // |
| 6 | // This code is free for use under the following conditions: |
| 7 | // |
| 8 | // 1. You may not claim authorship of this code. |
| 9 | // 2. You may not sell or distrubute this code without author's permission. |
| 10 | // 3. You are not permitted to sell this code in it's compiled, non-compiled, executable, |
| 11 | // or any other form. |
| 12 | // 4. Executable code excepted in the case that it is not sold separately from an application |
| 13 | // which uses this it. This means you can use this code for your applications as you |
| 14 | // see fit, but this code may not be sold in any form to others for use in their applications. |
| 15 | // 5. This copyright notice may not be removed. |
| 16 | // 6. Sell this code as part of a 'Programmer's Library' is stricly prohibited. |
| 17 | // |
| 18 | // If you'd like to pay me to turn this into an ActiveX/COM object so you can use it in |
| 19 | // a Visual Basic application, feel free to contact me with an offer, and I will create |
| 20 | // it for you. Otherwise, here is the source code, and you may make your own ActiveX/COM |
| 21 | // object, providing that it is not sold separately. |
| 22 | // |
| 23 | // No guarantees or warranties are expressed or implied. |
| 24 | // This code may contain bugs. |
| 25 | // |
| 26 | // Warning: May contain matter. If this should come into contact with anti-matter, |
| 27 | // a violent explosion may occur. |
| 28 | // |
| 29 | // Please let me know of any bugs, bug fixes, or enhancements made to this code. |
| 30 | // If you have ideas for this, and/or tips or admonitions, I would be glad to hear them. |
| 31 | // |
| 32 | // See notes at top of DirectoryChanges.cpp modification history and more info. |
| 33 | // |
| 34 | //////////////////////////////////////////////////////////////////////////////////////// |
| 35 | // |
| 36 | |
| 37 | #if !defined(AFX_DIRECTORYCHANGES_H__02E53FDE_CB22_4176_B6D7_DA3675D9F1A6__INCLUDED_) |
| 38 | #define AFX_DIRECTORYCHANGES_H__02E53FDE_CB22_4176_B6D7_DA3675D9F1A6__INCLUDED_ |
| 39 | |
| 40 | #if _MSC_VER > 1000 |
| 41 | #pragma once |
| 42 | #endif // _MSC_VER > 1000 |
| 43 | |
| 44 | #include <afxmt.h> |
| 45 | #include <afxtempl.h> |
| 46 | #include <stdio.h> |
| 47 | |
| 48 | #define READ_DIR_CHANGE_BUFFER_SIZE 4096 |
| 49 | |
| 50 | class CFileNotifyInformation;//helper class |
| 51 | class CDirectoryChangeWatcher; |
| 52 | class CDelayedDirectoryChangeHandler;//helper class...used in implementation |
| 53 | |
| 54 | class CDirectoryChangeHandler |
| 55 | /*********************************** |
| 56 | A class to handle changes to files in a directory. |
| 57 | The virtual On_Filexxx() functions are called whenever changes are made to a watched directory that is being handled by this object... |
| 58 | The On_Filexxx() functions execute in the context of the main thread if true is passed to the constructor of CDirectoryChangeWatcher, |
| 59 | OR they fire in the context of a worker thread if false is passed to the constructor of CDirectoryChangeWatcher |
| 60 | |
| 61 | NOTES: |
| 62 | A CDirectoryChangeHandler can only be used by ONE CDirectoryChangeWatcher object, |
| 63 | but a CDirectoryChangeWatcher object may use multiple CDirectoryChangeHandler objects. |
| 64 | |
| 65 | When this object is destroyed, whatever directories that it was being used to handle directory changes for |
| 66 | will automatically be 'unwatched'. |
| 67 | |
| 68 | The class is reference counted. The reference count is increased every time it is used |
| 69 | in a (successfull) call to CDirectoryChangeWatcher::WatchDirectory() and is decremented whenever |
| 70 | the directory becomes 'unwatched'. |
| 71 | |
| 72 | The only notifications are File Added, Removed, Modified, and Renamed. |
| 73 | Even though the CDirectoryChangeWatcher::WatchDirectory (which'll call ReadDirectoryChangesW()) function allows you to specify flags |
| 74 | to watch for changes to last access time, last write time, attributes changed, etc, |
| 75 | these changes all map out to On_FileModified() which doesn't specify the type of modification. |
| 76 | |
| 77 | |
| 78 | NOTE: The CDirectoryChangeHandler::On_Filexxx() functions |
| 79 | are called in the context of the main thread, the thread that called CDirectoryChangeWatcher::WatchDirectory(), |
| 80 | if you pass true to the constructor of CDirectoryChangeWatcher. This is accomplished via a hidden window, |
| 81 | and REQUIRES that your app has a message pump. |
| 82 | For console applications, or applications w/out a message pump, you can pass false to the constructor |
| 83 | of CDirectoryChangeWatcher, and these notifications will fire in the context of a worker thread. By passing false |
| 84 | to the constructor of CDirectoryChangeWatcher, you do NOT NEED a message pump in your application. |
| 85 | |
| 86 | |
| 87 | |
| 88 | ************************************/ |
| 89 | { |
| 90 | public: |
| 91 | |
| 92 | CDirectoryChangeHandler(); |
| 93 | virtual ~CDirectoryChangeHandler(); |
| 94 | |
| 95 | //this class is reference counted |
| 96 | long AddRef(); |
| 97 | long Release(); |
| 98 | long CurRefCnt()const; |
| 99 | |
| 100 | |
| 101 | BOOL UnwatchDirectory();//causes CDirectoryChangeWatcher::UnwatchDirectory() to be called. |
| 102 | |
| 103 | const CString & GetChangedDirectoryName() const { return m_strChangedDirectoryName;}//WARNING: don't use this, this function will be removed in a future release. |
| 104 | //returns the directory name where the change occured. This contains |
| 105 | //the last directory to have changed if the same CDirectoryChangeHandler is |
| 106 | //being used to watch multiple directories. It will return an empty string |
| 107 | //if no changes have been made to a directory yet. It will always be the |
| 108 | //name of the currently changed directory(as specified in CDirectoryChangeWatcher::WatchDirectory()) |
| 109 | //if called in the context of one of the |
| 110 | //On_Filexxx() functions. |
| 111 | protected: |
| 112 | // |
| 113 | // Override these functions: |
| 114 | // These functions are called when the directory to watch has had a change made to it |
| 115 | virtual void On_FileAdded(const CString & strFileName); //=0; |
| 116 | // |
| 117 | // On_FileAdded() |
| 118 | // |
| 119 | // This function is called when a file in one of the watched folders(or subfolders) |
| 120 | // has been created. |
| 121 | // |
| 122 | // For this function to execute you'll need to specify FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME(for directories) |
| 123 | // when you call CDirectoryChangeWatcher::WatchDirectory() |
| 124 | // |
| 125 | virtual void On_FileRemoved(const CString & strFileName);// = 0; |
| 126 | // |
| 127 | // On_FileRemoved() |
| 128 | // |
| 129 | // This function is called when a file in one of the watched folders(or subfolders) |
| 130 | // has been deleted(or moved to another directory) |
| 131 | // |
| 132 | // For this function to execute you'll need to specify FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME(for directories) |
| 133 | // when you call CDirectoryChangeWatcher::WatchDirecotry() |
| 134 | // |
| 135 | |
| 136 | virtual void On_FileNameChanged(const CString & strOldFileName, const CString & strNewFileName);// = 0; |
| 137 | // |
| 138 | // On_FileNameChanged() |
| 139 | // |
| 140 | // This function is called when a file in one of the watched folders(or subfolders) |
| 141 | // has been renamed. |
| 142 | // |
| 143 | // |
| 144 | // You'll need to specify FILE_NOTIFY_CHANGE_FILE_NAME (or FILE_NOTIFY_CHANGE_DIR_NAME(for directories)) |
| 145 | // when you call CDirectoryChangeWatcher::WatchDirectory() |
| 146 | // |
| 147 | // |
| 148 | |
| 149 | virtual void On_FileModified(const CString & strFileName);// = 0; |
| 150 | // |
| 151 | // On_FileModified() |
| 152 | // |
| 153 | // This function is called whenever an attribute specified by the watch |
| 154 | // filter has changed on a file in the watched directory or |
| 155 | // |
| 156 | // Specify any of the following flags when you call CDirectoryChangeWatcher::WatchDirectory() |
| 157 | // |
| 158 | // |
| 159 | // FILE_NOTIFY_CHANGE_ATTRIBUTES |
| 160 | // FILE_NOTIFY_CHANGE_SIZE |
| 161 | // FILE_NOTIFY_CHANGE_LAST_WRITE |
| 162 | // FILE_NOTIFY_CHANGE_LAST_ACCESS |
| 163 | // FILE_NOTIFY_CHANGE_CREATION (* See Note # 1* ) |
| 164 | // FILE_NOTIFY_CHANGE_SECURITY |
| 165 | // |
| 166 | // |
| 167 | // General Note) Windows tries to optimize some of these notifications. You may not get |
| 168 | // a notification every single time a file is accessed for example. |
| 169 | // There's a MS KB article or something on this(sorry forgot which one). |
| 170 | // |
| 171 | // Note #1 ) This notification isn't what you might think(FILE_NOTIFY_CHANGE_CREATION). |
| 172 | // See the help files for ReadDirectoryChangesW... |
| 173 | // This notifies you of a change to the file's |
| 174 | // creation time, not when the file is created. |
| 175 | // Use FILE_NOTIFY_CHANGE_FILE_NAME to know about newly created files. |
| 176 | // |
| 177 | |
| 178 | virtual void On_ReadDirectoryChangesError(DWORD dwError, const CString & strDirectoryName); |
| 179 | // |
| 180 | // On_ReadDirectoryChangesError() |
| 181 | // |
| 182 | // This function is called when ReadDirectoryChangesW() fails during normal |
| 183 | // operation (ie: some time after you've called CDirectoryChangeWatcher::WatchDirectory()) |
| 184 | // |
| 185 | // |
| 186 | // NOTE: *** READ THIS *** READ THIS *** READ THIS *** READ THIS *** |
| 187 | // |
| 188 | // NOTE: If this function has been called, the watched directory has been automatically unwatched. |
| 189 | // You will not receive any further notifications for that directory until |
| 190 | // you call CDirectoryChangeWatcher::WatchDirectory() again. |
| 191 | // |
| 192 | // On_WatchStopped() will not be called. |
| 193 | |
| 194 | |
| 195 | virtual void On_WatchStarted(DWORD dwError, const CString & strDirectoryName); |
| 196 | // |
| 197 | // void On_WatchStarted() |
| 198 | // |
| 199 | // This function is called when a directory watch has begun. |
| 200 | // It will be called whether CDirectoryChangeWatcher::WatchDirectory() is successful or not. Check the dwError parameter. |
| 201 | // |
| 202 | // PARAMETERS: |
| 203 | // DWORD dwError -- 0 if successful, else it's the return value of GetLastError() |
| 204 | // indicating why the watch failed. |
| 205 | // const CString & strDirectoryName -- The full path and name of the directory being watched. |
| 206 | |
| 207 | virtual void On_WatchStopped(const CString & strDirectoryName); |
| 208 | // |
| 209 | // void On_WatchStopped() |
| 210 | // |
| 211 | // This function is called when a directory is unwatched (except on the case of the direcotry being unwatched due to an error) |
| 212 | // |
| 213 | // WARNING: *** READ THIS *** READ THIS *** READ THIS *** READ THIS *** |
| 214 | // |
| 215 | // This function MAY be called before the destructor of CDirectoryChangeWatcher |
| 216 | // finishes. |
| 217 | // |
| 218 | // Be careful if your implementation of this fuction |
| 219 | // interacts with some sort of a window handle or other object(a class, a file, etc.). |
| 220 | // It's possible that that object/window handle will NOT be valid anymore the very last time |
| 221 | // that On_WatchStopped() is called. |
| 222 | // This scenario is likely if the CDirectoryChangeWatcher instance is currently watching a |
| 223 | // directory, and it's destructor is called some time AFTER these objects/windows |
| 224 | // your change handler interacts with have been destroyed. |
| 225 | // |
| 226 | // If your CDirectoryChangeHandler derived class interacts w/ a window or other |
| 227 | // object, it's a good idea to unwatch any directories before the object/window is destroyed. |
| 228 | // Otherwise, place tests for valid objects/windows in the implementation of this function. |
| 229 | // |
| 230 | // Failure to follow either tip can result in a mysterious RTFM error, or a 'Run time errors' |
| 231 | // |
| 232 | |
| 233 | virtual bool On_FilterNotification(DWORD dwNotifyAction, LPCTSTR szFileName, LPCTSTR szNewFileName); |
| 234 | // |
| 235 | // bool On_FilterNotification(DWORD dwNotifyAction, LPCTSTR szFileName, LPCTSTR szNewFileName); |
| 236 | // |
| 237 | // This function gives your class a chance to filter unwanted notifications. |
| 238 | // |
| 239 | // PARAMETERS: |
| 240 | // DWORD dwNotifyAction -- specifies the event to filter |
| 241 | // LPCTSTR szFileName -- specifies the name of the file for the event. |
| 242 | // LPCTSTR szNewFileName -- specifies the new file name of a file that has been renamed. |
| 243 | // |
| 244 | // ** szFileName and szNewFileName will always be the full path and file name with extention. |
| 245 | // |
| 246 | // RETURN VALUE: |
| 247 | // return true , and you will receive the notification. |
| 248 | // return false, and your class will NOT receive the notification. |
| 249 | // |
| 250 | // Valid values of dwNotifyAction: |
| 251 | // FILE_ACTION_ADDED -- On_FileAdded() is about to be called. |
| 252 | // FILE_ACTION_REMOVED -- On_FileRemoved() is about to be called. |
| 253 | // FILE_ACTION_MODIFIED -- On_FileModified() is about to be called. |
| 254 | // FILE_ACTION_RENAMED_OLD_NAME-- On_FileNameChanged() is about to be call. |
| 255 | // |
| 256 | // |
| 257 | // NOTE: When the value of dwNotifyAction is FILE_ACTION_RENAMED_OLD_NAME, |
| 258 | // szFileName will be the old name of the file, and szNewFileName will |
| 259 | // be the new name of the renamed file. |
| 260 | // |
| 261 | // The default implementation always returns true, indicating that all notifications will |
| 262 | // be sent. |
| 263 | // |
| 264 | // NOTE: This function may or may not be called depending upon the flags you specify to control |
| 265 | // filter behavior. |
| 266 | // If you are specifying filters when watching the directory, you will not get this notification |
| 267 | // if the file name does not pass the filter test, even if this function returns true. |
| 268 | // |
| 269 | virtual void On_FileUploaded(const CString & strFileName); |
| 270 | |
| 271 | // |
| 272 | // |
| 273 | // End Override these functions (ie: don't worry about the rest of this class) |
| 274 | // |
| 275 | |
| 276 | void SetChangedDirectoryName(const CString & strChangedDirName);//please don't use this function, it will be removed in future releases. |
| 277 | |
| 278 | BOOL FtpAddFile(const CString &strFileName); |
| 279 | |
| 280 | BOOL isInBlackList(const CString &strFileName); |
| 281 | BOOL isInWhiteList(const CString &strFileName); |
| 282 | |
| 283 | private: |
| 284 | long m_nRefCnt; |
| 285 | |
| 286 | CString m_strChangedDirectoryName;//will be removed in a future release. |
| 287 | |
| 288 | friend class CDirectoryChangeWatcher; |
| 289 | friend class CDelayedDirectoryChangeHandler; |
| 290 | // |
| 291 | // This class keeps a reference to the CDirectoryChangeHandler |
| 292 | // that was used when an object of this type is passed |
| 293 | // to CDirectoryChangeWatcher::WatchDirectory(). |
| 294 | // |
| 295 | // This way, when the CDirectoryChangeWatcher object is destroyed(or if CDirectoryChangeHandler::UnwatchDirectory() is called) |
| 296 | // AFTER CDirectoryChangeWatcher::UnwatchDirecotry() or CDirectoryChangeWatcher::UnwatchAllDirectories() is called |
| 297 | // the directory(or direcotries) that this |
| 298 | // CDirectoryChangeWatcher object is handling will be automatically unwatched |
| 299 | // If the CDirectoryChangeWatcher object is destroyed before the CDirectoryChangeHandler objects |
| 300 | // that are being used with that watcher are destroyed, the reference counting prevents |
| 301 | // this class from referencing a destructed object. |
| 302 | // Basically, neither class needs to worry about the lifetime of the other(CDirectoryChangeWatcher && CDirectoryChangeHandler) |
| 303 | // |
| 304 | |
| 305 | long ReferencesWatcher(CDirectoryChangeWatcher * pDirChangeWatcher); |
| 306 | long ReleaseReferenceToWatcher(CDirectoryChangeWatcher * pDirChangeWatcher); |
| 307 | CDirectoryChangeWatcher * m_pDirChangeWatcher; |
| 308 | long m_nWatcherRefCnt; //<-- when this reaches 0, m_pDirChangeWatcher is set to NULL |
| 309 | CCriticalSection m_csWatcher; |
| 310 | }; |
| 311 | |
| 312 | /////////////////////////////////////////////////////////// |
| 313 | |
| 314 | class CDirectoryChangeWatcher |
| 315 | /*************************************** |
| 316 | A class to monitor a directory for changes made to files in it, or it's subfolders. |
| 317 | The class CDirectoryChangeHandler handles the changes. You derive a class from CDirectoryChangeHandler to handle them. |
| 318 | |
| 319 | |
| 320 | This class uses the Win32 API ReadDirectoryChangesW() to watch a directory for file changes. |
| 321 | |
| 322 | Multiple directories can be watched simultaneously using a single instance of CDirectoryChangeWatcher. |
| 323 | Single or multiple instances of CDirectoryChangeHandler object(s) can be used to handle changes to watched directories. |
| 324 | Directories can be added and removed from the watch dynamically at run time without destroying |
| 325 | the CDirectoryChangeWatcher object (or CDirectoryChangeHandler object(s). |
| 326 | |
| 327 | This class uses a worker thread, an io completion port, and ReadDirectoryChangesW() to monitor changes to a direcory (or subdirectories). |
| 328 | There will always only be a single thread no matter how many directories are being watched(per instance of CDirectoryChangeHandler) |
| 329 | |
| 330 | THREAD ISSUES: |
| 331 | This class uses worker threads. |
| 332 | Notifications (calling CDirectoryChangeHandler's virtual functions) are executed |
| 333 | in the context of either the main thread, OR in a worker thread. |
| 334 | |
| 335 | The 'main' thread is the thread that first calls CDirectoryChangeWatcher::WatchDirectory(). |
| 336 | For notifications to execute in the main thread, it's required that the calling thread(usually the main thread) |
| 337 | has a message pump in order to process the notifications. |
| 338 | |
| 339 | For applications w/out a message pump, notifications are executed in the context of a worker thread. |
| 340 | |
| 341 | See the constructor for CDirectoryChangeWatcher. |
| 342 | |
| 343 | |
| 344 | ****************************************/ |
| 345 | { |
| 346 | public: |
| 347 | |
| 348 | enum { //options for determining the behavior of the filter tests. |
| 349 | // |
| 350 | FILTERS_DONT_USE_FILTERS = 1, //never test the include/exclude filters. CDirectoryChangeHandler::On_FilterNotification() is still called. |
| 351 | FILTERS_CHECK_FULL_PATH = 2, //For the file path: "C:\FolderName\SubFolder\FileName.xyz", the entire path is checked for the filter pattern. |
| 352 | FILTERS_CHECK_PARTIAL_PATH = 4, //For the file path: "C:\FolderName\SubFolder\FileName.xyz", only "SubFolder\FileName.xyz" is checked against the filter pattern, provided that you are watching the folder "C:\FolderName", and you are also watching subfolders. |
| 353 | FILTERS_CHECK_FILE_NAME_ONLY = 8, //For the file path: "C:\FolderName\SubFolder\FileName.xyz", only "FileName.xyz" is checked against the filter pattern. |
| 354 | FILTERS_TEST_HANDLER_FIRST = 16, //test CDirectoryChangeHandler::On_FilterNotification() before checking the include/exclude filters. the default is to check the include/exclude filters first. |
| 355 | FILTERS_DONT_USE_HANDLER_FILTER = 32, //CDirectoryChangeHander::On_FilterNotification() won't be called. |
| 356 | FILTERS_NO_WATCHSTART_NOTIFICATION = 64,//CDirectoryChangeHander::On_WatchStarted() won't be called. |
| 357 | FILTERS_NO_WATCHSTOP_NOTIFICATION = 128,//CDirectoryChangeHander::On_WatchStopped() won't be called. |
| 358 | FILTERS_DEFAULT_BEHAVIOR = (FILTERS_CHECK_FILE_NAME_ONLY ), |
| 359 | FILTERS_DONT_USE_ANY_FILTER_TESTS = (FILTERS_DONT_USE_FILTERS | FILTERS_DONT_USE_HANDLER_FILTER), |
| 360 | FILTERS_NO_WATCH_STARTSTOP_NOTIFICATION = (FILTERS_NO_WATCHSTART_NOTIFICATION | FILTERS_NO_WATCHSTOP_NOTIFICATION) |
| 361 | }; |
| 362 | |
| 363 | //ctor/dtor |
| 364 | CDirectoryChangeWatcher(bool bAppHasGUI = true, DWORD dwFilterFlags = FILTERS_DEFAULT_BEHAVIOR);//see comments in ctor .cpp file. |
| 365 | virtual ~CDirectoryChangeWatcher(); |
| 366 | |
| 367 | // |
| 368 | // Starts a watch on a directory: |
| 369 | // |
| 370 | DWORD WatchDirectory(const CString & strDirToWatch, |
| 371 | DWORD dwChangesToWatchFor, |
| 372 | CDirectoryChangeHandler * pChangeHandler, |
| 373 | BOOL bWatchSubDirs = FALSE, |
| 374 | LPCTSTR szIncludeFilter = NULL, |
| 375 | LPCTSTR szExcludeFilter = NULL); |
| 376 | |
| 377 | BOOL IsWatchingDirectory (const CString & strDirName)const; |
| 378 | int NumWatchedDirectories()const; //counts # of directories being watched. |
| 379 | |
| 380 | |
| 381 | BOOL UnwatchDirectory(const CString & strDirToStopWatching);//stops watching specified directory. |
| 382 | BOOL UnwatchAllDirectories();//stops watching ALL watched directories. |
| 383 | |
| 384 | DWORD SetFilterFlags(DWORD dwFilterFlags);//sets filter behavior for directories watched AFTER this function has been called. |
| 385 | DWORD GetFilterFlags()const{return m_dwFilterFlags;} |
| 386 | |
| 387 | protected: |
| 388 | |
| 389 | virtual void On_ThreadInitialize(){}//All file change notifications has taken place in the context of a worker thread...do any thread initialization here.. |
| 390 | virtual void On_ThreadExit(){}//do thread cleanup here |
| 391 | |
| 392 | private: |
| 393 | friend class CDirectoryChangeHandler; |
| 394 | BOOL UnwatchDirectory(CDirectoryChangeHandler * pChangeHandler);//called in CDirectoryChangeHandler::~CDirectoryChangeHandler() |
| 395 | |
| 396 | |
| 397 | UINT static MonitorDirectoryChanges(LPVOID lpvThis );//the worker thread that monitors directories. |
| 398 | |
| 399 | class CDirWatchInfo |
| 400 | //this class is used internally by CDirectoryChangeWatcher |
| 401 | //to help manage the watched directories |
| 402 | { |
| 403 | private: |
| 404 | CDirWatchInfo(); //private & not implemented |
| 405 | CDirWatchInfo & operator=(const CDirWatchInfo & rhs);//so that they're aren't accidentally used. -- you'll get a linker error |
| 406 | public: |
| 407 | CDirWatchInfo(HANDLE hDir, const CString & strDirectoryName, |
| 408 | CDirectoryChangeHandler * pChangeHandler, |
| 409 | DWORD dwChangeFilter, BOOL bWatchSubDir, |
| 410 | bool bAppHasGUI, |
| 411 | LPCTSTR szIncludeFilter, |
| 412 | LPCTSTR szExcludeFilter, |
| 413 | DWORD dwFilterFlags); |
| 414 | private: |
| 415 | ~CDirWatchInfo( );//only I can delete myself....use DeleteSelf() |
| 416 | public: |
| 417 | void DeleteSelf(CDirectoryChangeWatcher * pWatcher); |
| 418 | |
| 419 | DWORD StartMonitor(HANDLE hCompPort); |
| 420 | BOOL UnwatchDirectory( HANDLE hCompPort ); |
| 421 | protected: |
| 422 | BOOL SignalShutdown( HANDLE hCompPort ); |
| 423 | BOOL WaitForShutdown(); |
| 424 | public: |
| 425 | BOOL LockProperties() { return m_cs.Lock(); } |
| 426 | BOOL UnlockProperties(){ return m_cs.Unlock(); } |
| 427 | |
| 428 | CDelayedDirectoryChangeHandler* GetChangeHandler() const; |
| 429 | CDirectoryChangeHandler * GetRealChangeHandler() const;//the 'real' change handler is your CDirectoryChangeHandler derived class. |
| 430 | CDirectoryChangeHandler * SetRealDirectoryChangeHandler(CDirectoryChangeHandler * pChangeHandler); |
| 431 | |
| 432 | BOOL CloseDirectoryHandle(); |
| 433 | |
| 434 | //CDirectoryChangeHandler * m_pChangeHandler; |
| 435 | CDelayedDirectoryChangeHandler * m_pChangeHandler; |
| 436 | HANDLE m_hDir;//handle to directory that we're watching |
| 437 | DWORD m_dwChangeFilter; |
| 438 | BOOL m_bWatchSubDir; |
| 439 | CString m_strDirName;//name of the directory that we're watching |
| 440 | CHAR m_Buffer[ READ_DIR_CHANGE_BUFFER_SIZE ];//buffer for ReadDirectoryChangesW |
| 441 | DWORD m_dwBufLength;//length or returned data from ReadDirectoryChangesW -- ignored?... |
| 442 | OVERLAPPED m_Overlapped; |
| 443 | DWORD m_dwReadDirError;//indicates the success of the call to ReadDirectoryChanges() |
| 444 | CCriticalSection m_cs; |
| 445 | CEvent m_StartStopEvent; |
| 446 | enum eRunningState{ |
| 447 | RUNNING_STATE_NOT_SET, RUNNING_STATE_START_MONITORING, RUNNING_STATE_STOP, RUNNING_STATE_STOP_STEP2, |
| 448 | RUNNING_STATE_STOPPED, RUNNING_STATE_NORMAL |
| 449 | }; |
| 450 | eRunningState m_RunningState; |
| 451 | };//end nested class CDirWatchInfo |
| 452 | |
| 453 | void ProcessChangeNotifications(IN CFileNotifyInformation & notify_info, |
| 454 | IN CDirWatchInfo * pdi, |
| 455 | OUT DWORD & ref_dwReadBuffer_Offset); |
| 456 | friend class CDirWatchInfo;//so that CDirWatchInfo can call the following function. |
| 457 | long ReleaseReferenceToWatcher(CDirectoryChangeHandler * pChangeHandler); |
| 458 | |
| 459 | BOOL UnwatchDirectoryBecauseOfError(CDirWatchInfo * pWatchInfo);//called in case of error. |
| 460 | int AddToWatchInfo(CDirWatchInfo * pWatchInfo); |
| 461 | // |
| 462 | // functions for retrieving the directory watch info based on different parameters |
| 463 | // |
| 464 | CDirWatchInfo * GetDirWatchInfo(IN const CString & strDirName, OUT int & ref_nIdx)const; |
| 465 | CDirWatchInfo * GetDirWatchInfo(IN CDirWatchInfo * pWatchInfo, OUT int & ref_nIdx)const; |
| 466 | CDirWatchInfo * GetDirWatchInfo(IN CDirectoryChangeHandler * pChangeHandler, OUT int & ref_nIdx)const; |
| 467 | |
| 468 | |
| 469 | HANDLE m_hCompPort; //i/o completion port |
| 470 | HANDLE m_hThread; //MonitorDirectoryChanges() thread handle |
| 471 | DWORD m_dwThreadID; |
| 472 | CTypedPtrArray<CPtrArray, CDirWatchInfo*> m_DirectoriesToWatch; //holds info about the directories that we're watching. |
| 473 | CCriticalSection m_csDirWatchInfo; |
| 474 | |
| 475 | bool m_bAppHasGUI; //dispatch to main thread, or a worker thread? |
| 476 | DWORD m_dwFilterFlags;//options for determining the behavior of the filter tests. |
| 477 | }; |
| 478 | |
| 479 | |
| 480 | #endif // !defined(AFX_DIRECTORYCHANGES_H__02E53FDE_CB22_4176_B6D7_DA3675D9F1A6__INCLUDED_) |
Note: See TracBrowser for help on using the browser.
