// ========================================================================== // Class Implementation : COXWatchedDir // ========================================================================== // Source file : OXWatchedDir.cpp // Version: 9.3 // This software along with its related components, documentation and files ("The Libraries") // is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is // governed by a software license agreement ("Agreement"). Copies of the Agreement are // available at The Code Project (www.codeproject.com), as part of the package you downloaded // to obtain this file, or directly from our office. For a copy of the license governing // this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900. // ////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "OXWatchedDir.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif #define new DEBUG_NEW ///////////////////////////////////////////////////////////////////////////// // COXWatchedDir ///////////////////////////////////////////////////////////////////////////// // Definition of static members #if defined(_UNICODE) && (_WIN32_WINNT >= 0x400) DWORD COXWatchedDir::dwBytesReturned = 0; // --- Used only in the call of the ReadDirectoryChangesW() function #endif // defined(_UNICODE) && (_WIN32_WINNT >= 0x400) // Data members ------------------------------------------------------------- // protected: // CString m_sPath; // --- Directory to be watched // BOOL m_bWatchSubTree; // --- Flag for monitoring directory or directory tree // DWORD m_dwWatchFilter; // --- Filter conditions to watch for // HWND m_hwndWindowToNotify; // --- Handle of the window to be notified // BOOL m_bPost; // --- Flag for posting or sending // HANDLE m_hEvent; // --- Handle of the event to be signaled // #if defined(_UNICODE) && (_WIN32_WINNT >= 0x400) // BOOL m_bExtended; // --- Is extended info availanle // HANDLE m_hDirectory; // --- Handle to the directory to be watched // LPVOID m_lpBuffer; // --- Pointer to the buffer to receive the read results // DWORD m_nBufferLength; // --- Length of lpBuffer // OVERLAPPED* m_pOverlapped; // --- Pointer to overlapped structure // #endif // defined(_UNICODE) && (_WIN32_WINNT >= 0x400) // private: // Member functions --------------------------------------------------------- // public: // protected: COXWatchedDir::COXWatchedDir(CString sPath, BOOL bWatchSubTree, DWORD dwWatchFilter, BOOL bExtended) // --- In : sPath: the path to be watched // bWatchSubTree: indicates whether to watch subtree or not // dwWatchFilter: specifys which type of changes should be reported // For possible values see public data members Notification types // bExtended: if TRUE - extended info is available // --- Out : // --- Returns : // --- Effect : constructs the object : m_sPath(sPath), m_bWatchSubTree(bWatchSubTree), m_dwWatchFilter(dwWatchFilter), m_hwndWindowToNotify(NULL), m_bPost(TRUE), m_hEvent(NULL) #if defined(_UNICODE) && (_WIN32_WINNT >= 0x400) // Extended info is supported , m_bExtended(bExtended), m_hDirectory(NULL), m_lpBuffer(NULL), m_nBufferLength(0), m_pOverlapped(NULL) { } #else { UNUSED_ALWAYS(bExtended); } #endif // defined(_UNICODE) && (_WIN32_WINNT >= 0x400) COXWatchedDir::~COXWatchedDir() // --- In : // --- Out : // --- Returns : // --- Effect : Object destructor { #if defined(_UNICODE) && (_WIN32_WINNT >= 0x400) if(m_bExtended) { if(!HasOverlappedIoCompleted(m_pOverlapped)) { ::CancelIo(m_hDirectory); } delete m_pOverlapped; ::CloseHandle(m_hEvent); ::CloseHandle(m_hDirectory); delete [] m_lpBuffer; } else #endif // defined(_UNICODE) && (_WIN32_WINNT >= 0x400) ::FindCloseChangeNotification(m_hEvent); } BOOL COXWatchedDir::FindFirstHandle(HRESULT& rhrResult) // --- In : // --- Out : rhrResult: HERESULT of the last operation inside the function // --- Returns : TRUE if object is successfuly initialized // --- Effect : Initializes the object and creates the handle used for wait functions { rhrResult = ERROR_SUCCESS; #if defined(_UNICODE) && (_WIN32_WINNT >= 0x400) // Extended info is supported if(m_bExtended) { // Extended info will be supported m_nBufferLength = sizeof(FILE_NOTIFY_INFORMATION) + _MAX_PATH * sizeof(TCHAR) * 2; m_lpBuffer = new char[m_nBufferLength]; // Create directory handle m_hDirectory = ::CreateFile(m_sPath, // pointer to the file name FILE_LIST_DIRECTORY, // access (read-write) mode FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE, // share mode NULL, // security descriptor OPEN_EXISTING, // how to create FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, // file attributes NULL); // file with attributes to copy if(m_hDirectory != INVALID_HANDLE_VALUE) { //... Directory handle is created. m_hEvent = ::CreateEvent(NULL, // pointer to security attributes TRUE, // flag for manual-reset event FALSE, // flag for initial state NULL); // pointer to event-object name // In this case unnamed event if(m_hEvent != NULL) { // ... Event created. m_pOverlapped = new OVERLAPPED; m_pOverlapped->hEvent = m_hEvent; BOOL bRetVal = ::ReadDirectoryChangesW( m_hDirectory, // handle to the directory to be watched m_lpBuffer, // pointer to the buffer to receive the read results m_nBufferLength, // length of lpBuffer m_bWatchSubTree, // flag for monitoring directory or directory tree m_dwWatchFilter, // filter conditions to watch for &dwBytesReturned,// number of bytes returned. For asynchronous calls, this parameter is undefined m_pOverlapped, // pointer to structure needed for overlapped I/O NULL); //FileIOCompletionRoutine); // pointer to completion routine if(bRetVal != FALSE) { // It's OK return TRUE; } else { // Something wrong. Do cleanup and try FindFirstChangeNotification rhrResult = HRESULT_FROM_WIN32(::GetLastError()); } delete m_pOverlapped; m_pOverlapped = NULL; ::CloseHandle(m_hEvent); m_hEvent = NULL; } else { //if(m_hEvent != NULL) rhrResult = HRESULT_FROM_WIN32(::GetLastError()); } ::CloseHandle(m_hDirectory); m_hDirectory = NULL; } else { // if(m_hDirectory !=0 ) rhrResult = HRESULT_FROM_WIN32(::GetLastError()); } delete [] m_lpBuffer; m_lpBuffer = NULL; m_nBufferLength = 0; m_bExtended = FALSE; } #endif // defined(_UNICODE) && (_WIN32_WINNT >= 0x400) // No extended information is suported. Try FindFirstChangeNotification() m_hEvent = ::FindFirstChangeNotification(m_sPath, // pointer to name of directory to watch m_bWatchSubTree, // flag for monitoring directory or directory tree m_dwWatchFilter); // filter conditions to watch for if(m_hEvent != INVALID_HANDLE_VALUE) { // OK return TRUE; } else { rhrResult = HRESULT_FROM_WIN32(::GetLastError()); m_hEvent = NULL; } return FALSE; } BOOL COXWatchedDir::FindNextHandle(HANDLE& hHandle) // --- In : // --- Out : rhrResult: HERESULT of the last operation inside the function // --- Returns : TRUE if success // --- Effect : Reinitializes the handle used for wait functions { #if defined(_UNICODE) && (_WIN32_WINNT >= 0x400) // Extended info is supported if(m_bExtended) { ::ResetEvent(hHandle); return ::ReadDirectoryChangesW(m_hDirectory, // handle to the directory to be watched m_lpBuffer, // pointer to the buffer to receive the read results m_nBufferLength, // length of lpBuffer m_bWatchSubTree, // flag for monitoring directory or directory tree m_dwWatchFilter, // filter conditions to watch for &dwBytesReturned, // number of bytes returned. For asynchronous calls, this parameter is undefined m_pOverlapped, // pointer to structure needed for overlapped I/O NULL); // pointer to completion routine } else #endif // defined(_UNICODE) && (_WIN32_WINNT >= 0x400) return ::FindNextChangeNotification(hHandle); } // private: // //////////////////////////////////////////////////////////////////////////