summaryrefslogtreecommitdiff
path: root/Bus/IvyFileMon/DelayedDirectoryChangeHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Bus/IvyFileMon/DelayedDirectoryChangeHandler.cpp')
-rw-r--r--Bus/IvyFileMon/DelayedDirectoryChangeHandler.cpp1414
1 files changed, 0 insertions, 1414 deletions
diff --git a/Bus/IvyFileMon/DelayedDirectoryChangeHandler.cpp b/Bus/IvyFileMon/DelayedDirectoryChangeHandler.cpp
deleted file mode 100644
index 1c4daf0..0000000
--- a/Bus/IvyFileMon/DelayedDirectoryChangeHandler.cpp
+++ /dev/null
@@ -1,1414 +0,0 @@
-// DelayedDirectoryChangeHandler.cpp: implementation of the CDelayedDirectoryChangeHandler2 class.
-//
-//////////////////////////////////////////////////////////////////////
-
-#include "stdafx.h"
-#include "DirectoryChanges.h"
-#include "DelayedDirectoryChangeHandler.h"
-#include <process.h>//for _beginthreadex
-
-#include <shlwapi.h> // for PathMatchSpec
-#pragma comment( lib, "shlwapi.lib") // function
-
-
-#ifdef _DEBUG
-#undef THIS_FILE
-static char THIS_FILE[]=__FILE__;
-#define new DEBUG_NEW
-#endif
-
-#define UWM_DELAYED_DIRECTORY_NOTIFICATION (WM_APP+1024)
-
-
-HINSTANCE GetInstanceHandle()
-{
- return (HINSTANCE)GetModuleHandle(NULL);
- // ASSERT( AfxGetInstanceHandle() == (HINSTANCE)GetModuleHandle(NULL) ); <-- true for building .exe's
- //NOTE: In Dll's using shared MFC, AfxGetInstanceHandle() != (HINSTANCE)GetModuleHandle(NULL)...
- //don't know if this is the case for dll's using static MFC
-}
-static inline bool IsEmptyString(LPCTSTR sz)
-{
- return (bool)(sz==NULL || *sz == 0);
-}
-/*********************************************************
- PathMatchSpec() requires IE 4.0 or greater on NT...
- if running on NT 4.0 w/ out IE 4.0, then uses this function instead.
-
- Based on code by Jack Handy:
- http://www.codeproject.com/string/wildcmp.asp
-
- Changed slightly to match the PathMatchSpec signature, be unicode compliant & to ignore case by myself.
-
-*********************************************************/
-
-#define _TESTING_WILDCMP_ONLY_
-
-BOOL STDAPICALLTYPE wildcmp(LPCTSTR string, LPCTSTR wild )
-{
- const TCHAR *cp, *mp;
- cp = mp = NULL;
-
- while ((*string) && (*wild != _T('*')))
- {
- if ((_toupper(*wild) != _toupper(*string)) && (*wild != _T('?')))
- {
- return FALSE;
- }
- wild++;
- string++;
- }
-
- while (*string)
- {
- if (*wild == _T('*'))
- {
- if (!*++wild)
- {
- return TRUE;
- }
- mp = wild;
- cp = string+1;
- }
- else
- if ((_toupper(*wild) == _toupper(*string)) || (*wild == _T('?')))
- {
- wild++;
- string++;
- }
- else
- {
- wild = mp;
- string = cp++;
- }
- }
-
- while (*wild == _T('*'))
- {
- wild++;
- }
- return (!*wild)? TRUE : FALSE;
-}
-
-//////////////////////////////////////////////////////////////////////////
-//
-//CDirChangeNotification member functions:
-//
-CDirChangeNotification::CDirChangeNotification(CDelayedDirectoryChangeHandler * pDelayedHandler, DWORD dwPartialPathOffset)
-:m_pDelayedHandler( pDelayedHandler )
-,m_szFileName1(NULL)
-,m_szFileName2(NULL)
-,m_dwError(0UL)
-,m_dwPartialPathOffset(dwPartialPathOffset)
-{
- ASSERT( pDelayedHandler );
-}
-
-CDirChangeNotification::~CDirChangeNotification()
-{
- if( m_szFileName1 ) free(m_szFileName1), m_szFileName1 = NULL;
- if( m_szFileName2 ) free(m_szFileName2), m_szFileName2 = NULL;
-}
-
-void CDirChangeNotification::DispatchNotificationFunction()
-{
- ASSERT( m_pDelayedHandler );
- if( m_pDelayedHandler )
- m_pDelayedHandler->DispatchNotificationFunction( this );
-}
-
-void CDirChangeNotification::PostOn_FileAdded(LPCTSTR szFileName)
-{
- ASSERT( szFileName );
- m_eFunctionToDispatch = eOn_FileAdded;
- m_szFileName1 = _tcsdup( szFileName) ;
- //
- // post the message so it'll be dispatch by another thread.
- PostNotification();
-
-}
-void CDirChangeNotification::PostOn_FileRemoved(LPCTSTR szFileName)
-{
- ASSERT( szFileName );
- m_eFunctionToDispatch = eOn_FileRemoved;
- m_szFileName1 = _tcsdup( szFileName) ;
- //
- // post the message so it'll be dispatched by another thread.
- PostNotification();
-
-}
-void CDirChangeNotification::PostOn_FileNameChanged(LPCTSTR szOldName, LPCTSTR szNewName)
-{
- ASSERT( szOldName && szNewName );
-
- m_eFunctionToDispatch = eOn_FileNameChanged;
- m_szFileName1 = _tcsdup( szOldName) ;
- m_szFileName2 = _tcsdup( szNewName) ;
- //
- // post the message so it'll be dispatched by another thread.
- PostNotification();
-
-}
-
-void CDirChangeNotification::PostOn_FileModified(LPCTSTR szFileName)
-{
- ASSERT( szFileName );
-
- m_eFunctionToDispatch = eOn_FileModified;
- m_szFileName1 = _tcsdup( szFileName );
- //
- // post the message so it'll be dispatched by another thread.
- PostNotification();
-}
-
-void CDirChangeNotification::PostOn_ReadDirectoryChangesError(DWORD dwError, LPCTSTR szDirectoryName)
-{
- ASSERT( szDirectoryName );
-
- m_eFunctionToDispatch = eOn_ReadDirectoryChangesError;
- m_dwError = dwError;
- m_szFileName1 = _tcsdup(szDirectoryName);
- //
- // post the message so it'll be dispatched by the another thread.
- PostNotification();
-
-}
-
-void CDirChangeNotification::PostOn_WatchStarted(DWORD dwError, LPCTSTR szDirectoryName)
-{
- ASSERT( szDirectoryName );
-
- m_eFunctionToDispatch = eOn_WatchStarted;
- m_dwError = dwError;
- m_szFileName1 = _tcsdup(szDirectoryName);
-
- PostNotification();
-}
-
-void CDirChangeNotification::PostOn_WatchStopped(LPCTSTR szDirectoryName)
-{
- ASSERT( szDirectoryName );
-
- m_eFunctionToDispatch = eOn_WatchStopped;
- m_szFileName1 = _tcsdup(szDirectoryName);
-
- PostNotification();
-}
-
-void CDirChangeNotification::PostNotification()
-{
- ASSERT( m_pDelayedHandler );
- if( m_pDelayedHandler )
- m_pDelayedHandler->PostNotification( this );
-}
-
-static LRESULT CALLBACK DelayedNotificationWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-//
-// This is the wndproc for the notification window
-//
-// it's here to dispatch the notifications to the client
-//
-{
- if( message == UWM_DELAYED_DIRECTORY_NOTIFICATION )
- {
- CDirChangeNotification * pNotification = reinterpret_cast<CDirChangeNotification*>(lParam);
- ASSERT( pNotification );
- if( pNotification )
- {
- DWORD dwEx(0);
- __try{
- pNotification->DispatchNotificationFunction();
- }
- __except(dwEx = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER){
- //An exception was raised:
- //
- // Likely cause: there was a problem creating the CDelayedDirectoryChangeHandler::m_hWatchStoppedDispatchedEvent object
- // and the change handler object was deleted before the notification could be dispatched to this function.
- //
- // or perhaps, somebody's implementation of an overridden function caused an exception
- TRACE(_T("Following exception occurred: %d -- File: %s Line: %d\n"), dwEx, _T(__FILE__), __LINE__);
- }
- }
-
- return 0UL;
- }
- else
- return DefWindowProc(hWnd,message,wParam,lParam);
-}
-
-//////////////////////////////////////////////////////////////////////
-// Construction/Destruction
-//////////////////////////////////////////////////////////////////////
-//
-//CDelayedNotificationWindow static member vars:
-//
-long CDelayedNotificationWindow::s_nRefCnt = 0L;
-HWND CDelayedNotificationWindow::s_hWnd = NULL;
-BOOL CDelayedNotificationWindow::s_bRegisterWindow = FALSE;
-//
-//
-long CDelayedNotificationWindow::AddRef()//creates window for first time if necessary
-{
- if( InterlockedIncrement(&s_nRefCnt) == 1
- || !::IsWindow( s_hWnd ) )
- {
- TRACE(_T("CDelayedNotificationWindow -- Creating the notification window\n"));
- VERIFY( CreateNotificationWindow() );
- }
- return s_nRefCnt;
-}
-
-long CDelayedNotificationWindow::Release()//destroys window for last time if necessary
-{
- long nRefCnt = -1;
- if( (nRefCnt = InterlockedDecrement(&s_nRefCnt)) == 0 )
- {
- //no body else using the window so destroy it?
- TRACE(_T("CDelayedNotificationWindow -- Destroying the notification window\n"));
- DestroyWindow( s_hWnd );
- s_hWnd = NULL;
- }
- return nRefCnt;
-}
-BOOL CDelayedNotificationWindow::RegisterWindowClass(LPCTSTR szClassName)
-//
-// registers our own window class to use as the hidden notification window.
-//
-{
- WNDCLASS wc = {0};
-
- wc.style = 0;
- wc.hInstance = GetInstanceHandle();
- wc.lpszClassName = szClassName;
- wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
- wc.lpfnWndProc = DelayedNotificationWndProc;
-
- ATOM ant = RegisterClass( &wc );
- if( ant == NULL )
- {
- TRACE(_T("CDirChangeNotification::RegisterWindowClass - RegisterClass failed: %d\n"), GetLastError());
- }
- return (BOOL)(ant!= NULL);
-
-}
-
-BOOL CDelayedNotificationWindow::CreateNotificationWindow()
-//
-// Create the hidden notification windows.
-//
-{
- TCHAR szClassName[] = _T("Delayed_Message_Sender");
- if( !s_bRegisterWindow )
- s_bRegisterWindow = RegisterWindowClass(szClassName);
- s_hWnd = CreateWindowEx(0, szClassName, _T("DelayedWnd"),0,0,0,0,0, NULL, 0,
- GetInstanceHandle(), NULL);
- if( s_hWnd == NULL )
- {
- TRACE(_T("Unable to create notification window! GetLastError(): %d\n"), GetLastError());
- TRACE(_T("File: %s Line: %d\n"), _T(__FILE__), __LINE__);
- }
-
- return (BOOL)(s_hWnd != NULL);
-}
-void CDelayedNotificationWindow::PostNotification(CDirChangeNotification * pNotification)
-//
-// Posts a message to a window created in the main
-// thread.
-// The main thread catches this message, and dispatches it in
-// the context of the main thread.
-//
-{
- ASSERT( pNotification );
- ASSERT( s_hWnd );
- ASSERT( ::IsWindow( s_hWnd ) );
-
- PostMessage(s_hWnd,
- UWM_DELAYED_DIRECTORY_NOTIFICATION,
- 0,
- reinterpret_cast<LPARAM>( pNotification ));
-
-// if you don't want the notification delayed,
-//
-// if( false )
-// {
-// pNotification->DispatchNotificationFunction();
-// }
-}
-
-/////////////////////////////////////////////////////////
-// CDelayedNoticationThread
-//
-long CDelayedNotificationThread::s_nRefCnt = 0L;
-HANDLE CDelayedNotificationThread::s_hThread = NULL;
-DWORD CDelayedNotificationThread::s_dwThreadID = 0UL;
-
-void CDelayedNotificationThread::PostNotification(CDirChangeNotification * pNotification)
-{
- ASSERT( s_hThread != NULL );
- ASSERT( s_dwThreadID != 0 );
-
- if(
- !PostThreadMessage(s_dwThreadID,
- UWM_DELAYED_DIRECTORY_NOTIFICATION,
- 0,
- reinterpret_cast<LPARAM>(pNotification))
- )
- {
- //Note, this can sometimes fail.
- //Will fail if: s_dwThreadID references a invalid thread id(the thread has died for example)
- // OR will fail if the thread doesn't have a message queue.
- //
- // This was failing because the thread had not been fully started by the time PostThreadMessage had been called
- //
- //Note: if this fails, it creates a memory leak because
- //the CDirChangeNotification object that was allocated and posted
- //to the thread is actually never going to be dispatched and then deleted.... it's
- //hanging in limbo.....
-
- //
- // The fix for this situation was to force the thread that starts
- // this worker thread to wait until the worker thread was fully started before
- // continueing. accomplished w/ an event... also.. posting a message to itself before signalling the
- // 'spawning' thread that it was started ensured that there was a message pump
- // associated w/ the worker thread by the time PostThreadMessage was called.
- TRACE(_T("PostThreadMessage() failed while posting to thread id: %d! GetLastError(): %d%s\n"), s_dwThreadID, GetLastError(), GetLastError() == ERROR_INVALID_THREAD_ID? _T("(ERROR_INVALID_THREAD_ID)") : _T(""));
- }
-}
-
-bool CDelayedNotificationThread::StartThread()
-{
- TRACE(_T("CDelayedNotificationThread::StartThread()\n"));
- ASSERT( s_hThread == NULL
- && s_dwThreadID == 0 );
- s_hThread = (HANDLE)_beginthreadex(NULL,0,
- ThreadFunc, this, 0, (UINT*) &s_dwThreadID);
- if( s_hThread )
- WaitForThreadStartup();
-
- return s_hThread == NULL ? false : true;
-
-}
-
-bool CDelayedNotificationThread::StopThread()
-{
- TRACE(_T("CDelayedNotificationThread::StopThread()\n"));
- if( s_hThread != NULL
- && s_dwThreadID != 0 )
- {
- PostThreadMessage(s_dwThreadID, WM_QUIT, 0,0);
-
- WaitForSingleObject(s_hThread, INFINITE);
- CloseHandle(s_hThread);
- s_hThread = NULL;
- s_dwThreadID = 0UL;
- return true;
- }
- return true;//already shutdown
-}
-
-UINT __stdcall CDelayedNotificationThread::ThreadFunc(LPVOID lpvThis)
-{
- //UNREFERENCED_PARAMETER( lpvThis );
- //
- // Implements a simple message pump
- //
- CDelayedNotificationThread * pThis = reinterpret_cast<CDelayedNotificationThread*>(lpvThis);
- ASSERT( pThis );
-
- //
- // Insure that this thread has a message queue by the time another
- // thread gets control and tries to use PostThreadMessage
- // problems can happen if someone tries to use PostThreadMessage
- // in between the time pThis->SignalThreadStartup() is called,
- // and the first call to GetMessage();
-
- ::PostMessage(NULL, WM_NULL, 0,0);//if this thread didn't have a message queue before this, it does now.
-
-
- //
- //
- // Signal that this thread has started so that StartThread can continue.
- //
- if( pThis ) pThis->SignalThreadStartup();
-
- TRACE(_T("CDelayedNotificationThread::ThreadFunc() ThreadID: %d -- Starting\n"), GetCurrentThreadId());
- MSG msg;
- do{
- while( GetMessage(&msg, NULL, 0,0) )//note GetMessage() can return -1, but only if i give it a bad HWND.(HWND for another thread for example)..i'm not giving an HWND, so no problemo here.
- {
- if( msg.message == UWM_DELAYED_DIRECTORY_NOTIFICATION )
- {
- CDirChangeNotification * pNotification =
- reinterpret_cast<CDirChangeNotification *>( msg.lParam );
- DWORD dwEx(0UL);
-
- __try{
- if( pNotification )
- pNotification->DispatchNotificationFunction();
- }
- __except(dwEx = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER){
- //An exception was raised:
- //
- // Likely causes:
- // * There was a problem creating the CDelayedDirectoryChangeHandler::m_hWatchStoppedDispatchedEvent object
- // and the change handler object was deleted before the notification could be dispatched to this function.
- //
- // * Somebody's implementation of an overridden virtual function caused an exception
- TRACE(_T("The following exception occurred: %d -- File: %s Line: %d\n"), dwEx, _T(__FILE__), __LINE__);
- }
- }
- else
- if( msg.message == WM_QUIT )
- {
- break;
- }
- }
- }while( msg.message != WM_QUIT );
- TRACE(_T("CDelayedNotificationThread::ThreadFunc() exiting. ThreadID: %d\n"), GetCurrentThreadId());
- return 0;
-}
-
-long CDelayedNotificationThread::AddRef()
-{
- if( InterlockedIncrement(&s_nRefCnt) == 1 )
- {
- VERIFY( StartThread() );
- }
- return s_nRefCnt;
-}
-long CDelayedNotificationThread::Release()
-{
- if( InterlockedDecrement(&s_nRefCnt) <= 0 )
- {
- s_nRefCnt = 0;
- VERIFY( StopThread() );
- }
- return s_nRefCnt;
-}
-
-///////////////////////////////////////////////////////
-//static member data for CDelayedDirectoryChangeHandler
-HINSTANCE CDelayedDirectoryChangeHandler::s_hShlwapi_dll = NULL;//for the PathMatchSpec() function
-BOOL CDelayedDirectoryChangeHandler::s_bShlwapi_dllExists = TRUE;
-long CDelayedDirectoryChangeHandler::s_nRefCnt_hShlwapi = 0L;
-FUNC_PatternMatchSpec CDelayedDirectoryChangeHandler::s_fpPatternMatchSpec = wildcmp;//default
-///////////////////////////////////////////////////////
-//construction destruction
-CDelayedDirectoryChangeHandler::CDelayedDirectoryChangeHandler(CDirectoryChangeHandler * pRealHandler, bool bAppHasGUI, LPCTSTR szIncludeFilter, LPCTSTR szExcludeFilter, DWORD dwFilterFlags)
-: m_pDelayNotifier( NULL )
- ,m_pRealHandler( pRealHandler )
- ,m_szIncludeFilter(NULL)
- ,m_szExcludeFilter(NULL)
- ,m_dwFilterFlags( dwFilterFlags )
- ,m_dwPartialPathOffset( 0UL )
- ,m_hWatchStoppedDispatchedEvent(NULL)
- ,m_nNumIncludeFilterSpecs(0)
- ,m_nNumExcludeFilterSpecs(0)
-{
-
-
- ASSERT( m_pRealHandler );
-
- InitializePathMatchFunc( szIncludeFilter, szExcludeFilter );
-
- //
- // See that we're
- //
-
-
- m_hWatchStoppedDispatchedEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);//AUTO-RESET, not initially signalled
- ASSERT( m_hWatchStoppedDispatchedEvent );
-
- if( bAppHasGUI )
- {
- //
- // The value true was passed to the CDirectoryChangeWatcher constructor.
- // It's assumed that your app has a gui, that is, it implements
- // a message pump. To delay the notification to another thread,
- // we'll use a hidden notification window.
- //
- m_pDelayNotifier = new CDelayedNotificationWindow();
- }
- else
- {
- // The value 'false' was passed to the CDirectoryChangeWatcher constructor.
- //
- // Your app has no message pump... use a class that implements one for you
- // in a worker thread.
- //
- // Notifications will be executed in this worker thread.
- //
- m_pDelayNotifier = new CDelayedNotificationThread();
- }
-}
-
-CDelayedDirectoryChangeHandler::~CDelayedDirectoryChangeHandler()
-{
- if( m_pRealHandler )
- delete m_pRealHandler, m_pRealHandler = NULL;
- if( m_pDelayNotifier )
- delete m_pDelayNotifier, m_pDelayNotifier = NULL;
-
- if( m_hWatchStoppedDispatchedEvent )
- CloseHandle(m_hWatchStoppedDispatchedEvent), m_hWatchStoppedDispatchedEvent = NULL;
-
- if( m_szIncludeFilter ){
- if( m_nNumIncludeFilterSpecs == 1 )
- free(m_szIncludeFilter);
- else
- {
- TCHAR ** ppTmp = (TCHAR**)m_szIncludeFilter;
- for(int i(0); i < m_nNumIncludeFilterSpecs; ++i)
- {
- free( *ppTmp++ );
- }
- free( m_szIncludeFilter );
- }
- m_szIncludeFilter = NULL;
- m_nNumIncludeFilterSpecs;
- }
- if( m_szExcludeFilter ) {
- if( m_nNumExcludeFilterSpecs == 1 )
- free(m_szExcludeFilter);
- else{
- TCHAR ** ppTmp = (TCHAR**)m_szExcludeFilter;
- for(int i(0); i < m_nNumExcludeFilterSpecs; ++i)
- {
- free( *ppTmp++ );
- }
- free( m_szExcludeFilter );
- }
- m_szExcludeFilter = NULL;
- m_nNumExcludeFilterSpecs = 0;
- }
-
- UninitializePathMatchFunc();
-}
-
-BOOL CDelayedDirectoryChangeHandler::_PathMatchSpec(LPCTSTR szPath, LPCTSTR szPattern)
-{
- if( s_fpPatternMatchSpec )
- {
- return s_fpPatternMatchSpec(szPath, szPattern);
- }
- ASSERT( FALSE );
- return TRUE;//everything matches.
-}
-
-BOOL CDelayedDirectoryChangeHandler::InitializePathMatchFunc(LPCTSTR szIncludeFilter, LPCTSTR szExcludeFilter)
-//
-//
-// To support the Include and Exclude filters, the PathMatchSpec function is used.
-// PathMatchSpec is only supported on NT4.0 if IE 4.0 is installed.
-//
-// for the case where this code is running on NT 4.0 w/out IE 4.0, we use
-// a different function: wildcmp ()
-//
-//
-// This function attempts to load shlwapi.dll dynamically and find the PathMatchSpec function.
-//
-// if the function PathMatchSpec can't be found, the function pointer s_fpPathMatchSpec is set to wildcmp.
-//
-//
-// Note: wildcmp doesn't support multiple file specs separated by a semi-colon
-// as PathMatchSpec does.... we'll support it by parsing them
-// when we want to test the filters, we'll call the pattern matching functions multiple times...
-//
-{
-
- //
- // Copy the include/exclude filters if specified...
- //
- //
- if( IsEmptyString(szIncludeFilter)
- && IsEmptyString(szExcludeFilter) )
- {
- return TRUE;//both the include && exclude filters aren't specified
- //no need to initialize the pattern matching function....
- //if filters are never used, then
- //one less dll is loaded.
- }
-
-#ifdef _TESTING_WILDCMP_ONLY_
- s_hShlwapi_dll = NULL;
- s_bShlwapi_dllExists = FALSE;
- return InitializePatterns(szIncludeFilter, szExcludeFilter);
-#endif
-
-
- if( s_hShlwapi_dll != NULL )
- {
- ASSERT( s_fpPatternMatchSpec != NULL );
- InterlockedIncrement(&s_nRefCnt_hShlwapi);
-
- return InitializePatterns(szIncludeFilter, szExcludeFilter);
- }
- else{
- if( s_bShlwapi_dllExists == TRUE )//either the dll exists, or we haven't tried loading it yet...
- {
- //The pattern match function hasn't been initialized yet....
- //
-
- s_hShlwapi_dll = ::LoadLibrary(_T("Shlwapi.dll"));
- if( s_hShlwapi_dll == NULL )
- {
- s_bShlwapi_dllExists = FALSE;//don't try loading this dll again.
- s_fpPatternMatchSpec = wildcmp;//even though it's set buy default, and this code will only get here once, set it just for fun.
-
- return InitializePatterns(szIncludeFilter, szExcludeFilter);
-
- }
- else
- {
- //Shlwapi.dll was found....check it for PathMatchSpec()
-#ifdef UNICODE
- s_fpPatternMatchSpec = (FUNC_PatternMatchSpec)::GetProcAddress(s_hShlwapi_dll, "PathMatchSpecW");
-#else
- s_fpPatternMatchSpec = (FUNC_PatternMatchSpec)::GetProcAddress(s_hShlwapi_dll, "PathMatchSpecA");
-#endif
-
- if( s_fpPatternMatchSpec != NULL )
- {
- //UsesRealPathMatchSpec() will now return true.
- //we're on NT w/ IE 4.0 or greater...(or Win2k/XP)
- InterlockedIncrement(&s_nRefCnt_hShlwapi);
- return InitializePatterns(szIncludeFilter, szExcludeFilter);
- }
- else
- {
- //we found shlwapi.dll, but it didn't have PathMatchSpec()
- ::FreeLibrary( s_hShlwapi_dll );
- s_hShlwapi_dll = NULL;
- s_bShlwapi_dllExists = FALSE;
-
- //instead of using PathMatchSpec()
- //we'll use wildcmp()
- s_fpPatternMatchSpec = wildcmp;
- //UsesRealPathMatchSpec() will now return false w/out asserting.
-
- return InitializePatterns(szIncludeFilter, szExcludeFilter);
- }
- }
-
- }
- }
- return (s_fpPatternMatchSpec != NULL);
-}
-
-BOOL CDelayedDirectoryChangeHandler::InitializePatterns(LPCTSTR szIncludeFilter, LPCTSTR szExcludeFilter)
-{
- ASSERT( !IsEmptyString(szIncludeFilter) //one of these must have something in it,
- || !IsEmptyString(szExcludeFilter) );//or else this function shouldn't be called.
-
- if( s_hShlwapi_dll != NULL )
- {
- //we're using Shlwapi.dll's PathMatchSpec function....
- //we're running on NT4.0 w/ IE 4.0 installed, or win2k/winXP(or greater)
- //
- // Copy the include/exclude filters if specified...
- //
- //
- // we're using the real PathMatchSpec() function which
- // supports multiple pattern specs...(separated by a semi-colon)
- // so there's only one filter spec as far as my code is concerned.
- //
- if( !IsEmptyString(szIncludeFilter) )
- {
- m_szIncludeFilter = _tcsdup(szIncludeFilter);
- ASSERT( m_szIncludeFilter );
- m_nNumIncludeFilterSpecs = 1;
- }
- if( !IsEmptyString(szExcludeFilter) )
- {
- m_szExcludeFilter = _tcsdup(szExcludeFilter);
- ASSERT( m_szExcludeFilter );
- m_nNumExcludeFilterSpecs = 1;
- }
- }
- else
- {
- //shlwapi.dll isn't on this machine.... can happen on NT4.0 w/ out IE 4.0 installed.
- ASSERT( s_bShlwapi_dllExists == FALSE );
-
- //
- // we're using the function wildcmp() instead of PathMatchSpec..
- //
- // this means that multiple pattern specs aren't supported...
- // in order to support them, we'll tokenize the string into multiple
- // pattern specs and test the string multiple times(once per pattern spec)
- // in order to support multiple patterns.
- //
- //
- // m_szIncludeFilter & m_szExclude filter will be used like TCHAR**'s instead of TCHAR*'s
- //
-
- m_nNumIncludeFilterSpecs = 0;
- if( !IsEmptyString(szIncludeFilter) )
- {
- TCHAR * szTmpFilter = _tcsdup(szIncludeFilter);
- TCHAR * pTok = _tcstok( szTmpFilter, _T(";"));
- while( pTok )
- {
- m_nNumIncludeFilterSpecs++;
- pTok = _tcstok(NULL, _T(";"));
- }
- if( m_nNumIncludeFilterSpecs == 1 )
- m_szIncludeFilter = _tcsdup(szIncludeFilter);
- else
- { //allocate room for pointers .. one for each token...
- m_szIncludeFilter = (TCHAR*)malloc( m_nNumIncludeFilterSpecs * sizeof(TCHAR*));
-
- free(szTmpFilter);
- szTmpFilter = _tcsdup(szIncludeFilter);
- pTok = _tcstok(szTmpFilter, _T(";"));
- TCHAR ** ppTmp = (TCHAR**)m_szIncludeFilter;
- while(pTok)
- {
- *ppTmp = _tcsdup(pTok);
- ppTmp++;
- pTok = _tcstok(NULL, _T(";"));
- }
- }
-
- free(szTmpFilter);
- }
-
- //
- // Do the same for the Exclude filter...
- //
- m_nNumExcludeFilterSpecs = 0;
- if( !IsEmptyString(szExcludeFilter) )
- {
- TCHAR * szTmpFilter = _tcsdup(szExcludeFilter);
- TCHAR * pTok = _tcstok( szTmpFilter, _T(";"));
- while( pTok )
- {
- m_nNumExcludeFilterSpecs++;
- pTok = _tcstok(NULL, _T(";"));
- }
- if( m_nNumExcludeFilterSpecs == 1 )
- m_szExcludeFilter = _tcsdup(szExcludeFilter);
- else
- { //allocate room for pointers .. one for each token...
- m_szExcludeFilter = (TCHAR*)malloc( m_nNumExcludeFilterSpecs * sizeof(TCHAR*));
-
- free(szTmpFilter);
- szTmpFilter = _tcsdup(szExcludeFilter);
-
- pTok = _tcstok(szTmpFilter, _T(";"));
- TCHAR ** ppTmp = (TCHAR**)m_szExcludeFilter;
- while(pTok)
- {
- *ppTmp = _tcsdup(pTok);
- ppTmp++;
- pTok = _tcstok(NULL, _T(";"));
- }
- }
- free(szTmpFilter);
- }
-
- }
-
- return (m_szExcludeFilter!= NULL || (m_szIncludeFilter != NULL));
-}
-void CDelayedDirectoryChangeHandler::UninitializePathMatchFunc()
-{
- if( s_bShlwapi_dllExists == TRUE
- && s_hShlwapi_dll != NULL )
- {
- if( InterlockedDecrement(&s_nRefCnt_hShlwapi) <= 0)
- {
- s_nRefCnt_hShlwapi = 0;
- FreeLibrary( s_hShlwapi_dll );
- s_hShlwapi_dll = NULL;
- s_fpPatternMatchSpec = wildcmp;
- }
- }
-}
-
-bool CDelayedDirectoryChangeHandler::UsesRealPathMatchSpec() const
-//are we using PathMatchSpec() or wildcmp()?
-{
- if( s_hShlwapi_dll != NULL && s_fpPatternMatchSpec != NULL )
- return true;
- if( s_hShlwapi_dll == NULL && s_fpPatternMatchSpec != NULL )
- return false;
-
- ASSERT( FALSE );//this function was called before InitializePathMatchFunc()
- //oops!
- return false;
-}
-static inline bool HasTrailingBackslash(const CString & str )
-{
- if( str.GetLength() > 0
- && str[ str.GetLength() - 1 ] == _T('\\') )
- return true;
- return false;
-}
-void CDelayedDirectoryChangeHandler::SetPartialPathOffset(const CString & strWatchedDirName)
-{
- if( m_dwFilterFlags & CDirectoryChangeWatcher::FILTERS_CHECK_PARTIAL_PATH )
- {
- //set the offset to
- if( HasTrailingBackslash( strWatchedDirName ) )
- m_dwPartialPathOffset = strWatchedDirName.GetLength();
- else
- m_dwPartialPathOffset = strWatchedDirName.GetLength() + 1;
- }
- else
- m_dwPartialPathOffset = 0;
-}
-
-CDirChangeNotification * CDelayedDirectoryChangeHandler::GetNotificationObject()
-//
-// Maybe in future I'll keep a pool of these
-// objects around to increase performance...
-// using objects from a cache will be faster
-// than allocated and destroying a new one each time.
-//
-//
-{
- ASSERT( m_pRealHandler );
- return new CDirChangeNotification(this, m_dwPartialPathOffset);//helps support FILTERS_CHECK_PARTIAL_PATH
-}
-
-void CDelayedDirectoryChangeHandler::DisposeOfNotification(CDirChangeNotification * pNotification)
-{
- delete pNotification;
-}
-
-//These functions are called when the directory to watch has had a change made to it
-void CDelayedDirectoryChangeHandler::On_FileAdded(const CString & strFileName)
-{
- CDirChangeNotification * p = GetNotificationObject();
- ASSERT( p );
- if( p ) p->PostOn_FileAdded( strFileName );
-}
-
-void CDelayedDirectoryChangeHandler::On_FileRemoved(const CString & strFileName)
-{
- CDirChangeNotification * p = GetNotificationObject();
- ASSERT( p );
- if( p ) p->PostOn_FileRemoved( strFileName );
-}
-
-void CDelayedDirectoryChangeHandler::On_FileModified(const CString & strFileName)
-{
- CDirChangeNotification * p = GetNotificationObject();
- ASSERT( p );
- if( p ) p->PostOn_FileModified( strFileName );
-}
-
-void CDelayedDirectoryChangeHandler::On_FileNameChanged(const CString & strOldFileName, const CString & strNewFileName)
-{
- CDirChangeNotification * p = GetNotificationObject();
- ASSERT( p );
- if( p ) p->PostOn_FileNameChanged( strOldFileName, strNewFileName );
-}
-
-void CDelayedDirectoryChangeHandler::On_ReadDirectoryChangesError(DWORD dwError, const CString & strDirectoryName)
-{
- CDirChangeNotification * p = GetNotificationObject();
- ASSERT( p );
- if( p ) p->PostOn_ReadDirectoryChangesError( dwError, strDirectoryName );
-}
-
-void CDelayedDirectoryChangeHandler::On_WatchStarted(DWORD dwError, const CString & strDirectoryName)
-{
- if( !(m_dwFilterFlags & CDirectoryChangeWatcher::FILTERS_NO_WATCHSTART_NOTIFICATION))
- {
- CDirChangeNotification * p = GetNotificationObject();
-
- if( p ) p->PostOn_WatchStarted(dwError, strDirectoryName);
- }
-}
-
-void CDelayedDirectoryChangeHandler::On_WatchStopped(const CString & strDirectoryName)
-{
- if( !(m_dwFilterFlags & CDirectoryChangeWatcher::FILTERS_NO_WATCHSTOP_NOTIFICATION))
- {
- CDirChangeNotification * p = GetNotificationObject();
-
- if( p ){
- if( m_hWatchStoppedDispatchedEvent )
- ::ResetEvent(m_hWatchStoppedDispatchedEvent);
-
- p->PostOn_WatchStopped( strDirectoryName );
-
- // Wait that this function has been dispatched to the other thread
- // before continueing. This object may be getting deleted
- // soon after this function returns, and before the function can be
- // dispatched to the other thread....
- WaitForOnWatchStoppedDispatched();
- }
- }
-}
-
-
-void CDelayedDirectoryChangeHandler::PostNotification(CDirChangeNotification * pNotification)
-{
- if( m_pDelayNotifier )
- m_pDelayNotifier->PostNotification( pNotification );
-}
-
-inline bool IsNonFilterableEvent( CDirChangeNotification::eFunctionToDispatch eEvent)
-// Helper function
-// For filtering events..... these functions can not be filtered out.
-//
-{
- if( eEvent == CDirChangeNotification::eOn_WatchStarted
- || eEvent == CDirChangeNotification::eOn_WatchStopped
- || eEvent == CDirChangeNotification::eOn_ReadDirectoryChangesError )
- {
- return true;
- }
- else
- return false;
-}
-DWORD GetPathOffsetBasedOnFilterFlags(CDirChangeNotification * pNot, DWORD dwFilterFlags)
-{
-
- ASSERT( pNot && dwFilterFlags != 0 );
- //helps support the filter options FILTERS_CHECK_FULL_PATH, FILTERS_CHECK_PARTIAL_PATH, and FILTERS_CHECK_FILE_NAME_ONLY
-
- DWORD dwFileNameOffset = 0;//offset needed to support FILTERS_CHECK_FULL_PATH
- if( dwFilterFlags & CDirectoryChangeWatcher::FILTERS_CHECK_FILE_NAME_ONLY )
- {
- //set the offset to support FILTERS_CHECK_FILE_NAME_ONLY
- TCHAR * pSlash = _tcsrchr(pNot->m_szFileName1, _T('\\'));
- if( pSlash )
- dwFileNameOffset = (++pSlash - pNot->m_szFileName1);
-
- //
- // Because file name change notifications take place in the same directory,
- // the same dwFileNameOffset can be used for the szNewFileName(pNot->m_szFileName2)
- // when checking the filter against the new file name.
- //
- }
- else
- if( dwFilterFlags & CDirectoryChangeWatcher::FILTERS_CHECK_PARTIAL_PATH)
- {
- //
- // partial path offset is the offset
- // from the beginning of the file name,
- // to the end of the watched directory path...
- // ie: If you're watching "C:\Temp"
- // and the file C:\Temp\SubFolder\FileName.txt" is changed,
- // the partial path offset will give you "SubFolder\FileName.txt"
- // when this is checked against the include/exclude filter.
- //
- dwFileNameOffset = pNot->m_dwPartialPathOffset;
- }
- //else
- //if( m_dwFilterFlags & CDirectoryChangeWatcher::FILTERS_CHECK_FULL_PATH )
- // dwFileNameOffset = 0;
-
- return dwFileNameOffset;
-}
-
-bool CDelayedDirectoryChangeHandler::NotifyClientOfFileChange(CDirChangeNotification * pNot)
-//
-//
-// Perform the tests to see if the client wants to be notified of this
-// file change notification.
-//
-// Tests performed:
-//
-// Event test: Not all events can be filtered out.
-// On_ReadDirectoryChangesError
-// cannot be filtered out.
-// Filter flags test: User can specify flags so that no tests are performed....all notifications are sent to the user.
-//
-// Filter test: Test the notification file name against include and exclude filters.
-//
-// Only files changes matching the INCLUDE filter will be passed to the client.
-// By not specifying an include filter, all file changes are passed to the client.
-//
-// Any files matching the EXCLUDE filter will not be passed to the client.
-//
-//
-// Note: For the file name change event:
-// If the old file name does not pass the tests for the include and exclude filter
-// but the NEW file name does pass the test for the filters, then the client IS notified.
-//
-// Client test: The CDirectoryChangeHandler derived class is given a chance to filter the event by calling
-// CDirectoryChangeHandler::On_FilterNotification()
-//
-// RETURN VALUE:
-// If this function returns true, the notification function is called.
-// If it returns false, the notification is ignored.
-// The client is notified by calling CDirectoryChangeHandler's virtual functions On_FileAdded(),On_FileRemoved(), etc.
-{
- ASSERT( pNot );
- ASSERT( m_pRealHandler );
-
- //
- // Some events can't be ignored, or filtered out.
- //
-
- if( ((m_dwFilterFlags & CDirectoryChangeWatcher::FILTERS_DONT_USE_ANY_FILTER_TESTS) == CDirectoryChangeWatcher::FILTERS_DONT_USE_ANY_FILTER_TESTS)
- || IsNonFilterableEvent( pNot->m_eFunctionToDispatch ) )
- {
- // Either this is a non-filterable event, or we're not using any filters...
- // client is notified of all events..
- return true;
- }
-
- //
- // See if user wants to test CDirectoryChangeHandler::On_FilterNotification()
- // before tests are performed against the file name, and filter specifications
- //
- if( (m_dwFilterFlags & CDirectoryChangeWatcher::FILTERS_TEST_HANDLER_FIRST )//specified that CDirectoryChangeHandler::On_FilterNotification is to be called before any other filter tests
- && !(m_dwFilterFlags & CDirectoryChangeWatcher::FILTERS_DONT_USE_HANDLER_FILTER)//and did not specify that this CDirectoryChangeHandler::On_FilterNotification is not to be called..
- && !m_pRealHandler->On_FilterNotification(pNot->m_eFunctionToDispatch, pNot->m_szFileName1, pNot->m_szFileName2) )
- {
- //
- // Client specified to test handler first, and it didn't pass the test... don't notify the client.
- //
- return false;
- }
- //else
- //
- // this file change passed the user test, continue testing
- // to see if it passes the filter tests.
-
- DWORD dwFileNameOffset = GetPathOffsetBasedOnFilterFlags(pNot, m_dwFilterFlags);
-
- //
- // See if the changed file matches the include or exclude filter
- // Only allow notifications for included files
- // that have not been exluded.
- //
- if(!(m_dwFilterFlags & CDirectoryChangeWatcher::FILTERS_DONT_USE_FILTERS) )
- {
- if( false == IncludeThisNotification(pNot->m_szFileName1 + dwFileNameOffset)
- || true == ExcludeThisNotification(pNot->m_szFileName1 + dwFileNameOffset) )
- {
- if( pNot->m_eFunctionToDispatch != CDirChangeNotification::eOn_FileNameChanged )
- return false;
- else{
- //Special case for file name change:
- //
- // the old file name didn't pass the include/exclude filter
- // but if the new name passes the include/exclude filter,
- // we will pass it on to the client...
-
- if( false == IncludeThisNotification(pNot->m_szFileName2 + dwFileNameOffset)
- || true == ExcludeThisNotification(pNot->m_szFileName2 + dwFileNameOffset) )
- {
- // the new file name didn't pass the include/exclude filter test either
- // so don't pass the notification on...
- return false;
- }
-
- }
- }
-
- }
-
- //
- // Finally, let the client determine whether or not it wants this file notification
- // if this test has not already been performed...
- //
-
- if( (m_dwFilterFlags & CDirectoryChangeWatcher::FILTERS_TEST_HANDLER_FIRST)
- || (m_dwFilterFlags & CDirectoryChangeWatcher::FILTERS_DONT_USE_HANDLER_FILTER) )
- {
- // if we got this far, and this flag was specified,
- // it's already passed this test,
- // or we're not checking it based on the filter flag FILTERS_DONT_USE_HANDLER_FILTER....
- return true;
- }
- else
- {
- if( m_pRealHandler->On_FilterNotification(pNot->m_eFunctionToDispatch,
- pNot->m_szFileName1,
- pNot->m_szFileName2) )
- {
- return true;
- }
- else
- {
- //else client's derived CDirectoryChangeHandler class chose
- // not to be notified of this file change
- return false;
- }
- }
-
-
-}
-
-bool CDelayedDirectoryChangeHandler::IncludeThisNotification(LPCTSTR szFileName)
-//
-// The Include filter specifies which file names we should allow to notifications
-// for... otherwise these notifications are not dispatched to the client's code.
-//
-// Tests the file name to see if it matches a filter specification
-//
-// RETURN VALUES:
-//
-// true : notifications for this file are to be included...
-// notifiy the client by calling the appropriate CDirectoryChangeHandler::On_Filexxx() function.
-// false: this file is not included.... do not notifiy the client...
-//
-{
- ASSERT( szFileName );
-
- if( m_szIncludeFilter == NULL ) // no filter specified, all files pass....
- return true;
- if( m_nNumIncludeFilterSpecs == 1 )
- {
- return _PathMatchSpec(szFileName, m_szIncludeFilter)? true : false;
- }
- else
- {
- TCHAR ** ppTmp = (TCHAR**)m_szIncludeFilter;
- for(int i(0); i < m_nNumIncludeFilterSpecs; ++i )
- {
- if( _PathMatchSpec(szFileName, *ppTmp++) )
- return true;
- }
- return false;
- }
-
- return false;
-}
-
-bool CDelayedDirectoryChangeHandler::ExcludeThisNotification(LPCTSTR szFileName)
-//
-// Tests the file name to see if it matches a filter specification
-// if this function returns true, it means that this notification
-// is NOT to be passed to the client.... changes to this kind of file
-// are not
-//
-// RETURN VALUES:
-//
-// true : notifications for this file are to be filtered out(EXCLUDED)...
-// do not notifify the client code.
-// false: notifications for this file are NOT to be filtered out
-//
-//
-{
-
- ASSERT( szFileName );
-
- if( m_szExcludeFilter == NULL ) // no exclude filter... nothing is excluded...
- return false;
- if( m_nNumExcludeFilterSpecs == 1 )
- {
- if( _PathMatchSpec(szFileName, m_szExcludeFilter) )
- return true;//exclude this notification...
- return false;
- }
- else
- {
- TCHAR ** ppTmp = (TCHAR**)m_szExcludeFilter;
- for(int i(0); i < m_nNumExcludeFilterSpecs; ++i )
- {
- if( _PathMatchSpec(szFileName, *ppTmp++) )
- return true;//exclude this one...
- }
- return false;//didn't match any exclude filters...don't exclude it
- }
-/**
- if( m_szExcludeFilter == NULL //no exclude filter specified, not excluding anything....
- || !PathMatchSpec(szFileName, m_szExcludeFilter) )//or didn't match filter pattern.. this is not excluded...
- {
- return false;
- }
- return true;
-***/
-
-}
-
-void CDelayedDirectoryChangeHandler::DispatchNotificationFunction(CDirChangeNotification * pNotification)
-/*****************************************************
- This function is called when we want the notification to execute.
-
-
-******************************************************/
-{
- ASSERT( m_pRealHandler );
- ASSERT( pNotification );
- if( pNotification && m_pRealHandler )
- {
- //
- // Allow the client to ignore the notification
- //
- //
- if( NotifyClientOfFileChange(pNotification))
- {
- switch( pNotification->m_eFunctionToDispatch )
- {
- case CDirChangeNotification::eOn_FileAdded:
-
- m_pRealHandler->On_FileAdded( pNotification->m_szFileName1 );
- break;
-
- case CDirChangeNotification::eOn_FileRemoved:
-
- m_pRealHandler->On_FileRemoved( pNotification->m_szFileName1 );
- break;
-
- case CDirChangeNotification::eOn_FileNameChanged:
-
- m_pRealHandler->On_FileNameChanged( pNotification->m_szFileName1, pNotification->m_szFileName2 );
- break;
-
- case CDirChangeNotification::eOn_FileModified:
-
- m_pRealHandler->On_FileModified( pNotification->m_szFileName1 );
- break;
-
- case CDirChangeNotification::eOn_ReadDirectoryChangesError:
-
- m_pRealHandler->On_ReadDirectoryChangesError( pNotification->m_dwError, pNotification->m_szFileName1 );
- break;
-
- case CDirChangeNotification::eOn_WatchStarted:
-
- m_pRealHandler->On_WatchStarted(pNotification->m_dwError, pNotification->m_szFileName1);
- break;
-
- case CDirChangeNotification::eOn_WatchStopped:
-
- try{
- //
- // The exception handler is just in case of the condition described in DirectoryChanges.h
- // in the comments for On_WatchStopped()
- //
- m_pRealHandler->On_WatchStopped(pNotification->m_szFileName1);
-
- }catch(...){
- MessageBeep( 0xffff );
- MessageBeep( 0xffff );
- #ifdef DEBUG
- MessageBox(NULL,_T("An RTFM Exception was raised in On_WatchStopped() -- see Comments for CDirectoryChangeHandler::On_WatchStopped() in DirectoryChanges.h."), _T("Programmer Note(DEBUG INFO):"), MB_ICONEXCLAMATION | MB_OK);
- #endif
- }
- //
- // Signal that the On_WatchStopped() function has been dispatched.
- //
- if( m_hWatchStoppedDispatchedEvent )
- SetEvent(m_hWatchStoppedDispatchedEvent);
- break;
- case CDirChangeNotification::eFunctionNotDefined:
- default:
- break;
- }//end switch()
- }
- }
- if( pNotification ) //
- DisposeOfNotification(pNotification);// deletes or releases the notification object from memory/use
- //
-}
-
-BOOL CDelayedDirectoryChangeHandler::WaitForOnWatchStoppedDispatched( )
-//
-// When shutting down, m_pRealHandler->On_WatchStopped() will be called.
-// Because it's possible that this object will be deleted before the notification
-// can be dispatched to the other thread, we have to wait until we know that it's been executed
-// before returning control.
-//
-// This function signals that the function has been dispatched to the other
-// thread and it will be safe to delete this object once this has returned.
-//
-{
- ASSERT( m_hWatchStoppedDispatchedEvent );
- DWORD dwWait = WAIT_FAILED;
- if( m_hWatchStoppedDispatchedEvent )
- {
-
- if( m_bAppHasGUI == false )
- {
- //
- // The function will be dispatched to another thread...
- // just wait for the event to be signalled....
- do{
- dwWait = WaitForSingleObject(m_hWatchStoppedDispatchedEvent, 5000);//wait five seconds
- if( dwWait != WAIT_OBJECT_0 )
- {
- TRACE(_T("WARNING: Possible Deadlock detected! ThreadID: %d File: %s Line: %d\n"), GetCurrentThreadId(), _T(__FILE__), __LINE__);
- }
- }while( dwWait != WAIT_OBJECT_0 );
- }
- else
- {
- //
- // Note to self: This thread doesn't have a message Q, and therefore can't attach to
- // receive messages and process them... MsgWaitForMultipleObjects won't wake up for messages
- // unless i attach myself the the other threads input Q....
- // just use MsgWaitForMultipleObjects() in place of WaitForSingleObject in the places where it's used...
- //
- do{
- dwWait = MsgWaitForMultipleObjects(1, &m_hWatchStoppedDispatchedEvent,
- FALSE, 5000,
- QS_ALLEVENTS);//wake up for all events, sent messages, posted messages etc.
- switch(dwWait)
- {
- case WAIT_OBJECT_0:
- {
- //
- // The event has become signalled
- //
-
- }break;
- case WAIT_OBJECT_0 + 1:
- {
- //
- // There is a message in this thread's queue, so
- // MsgWaitForMultipleObjects returned.
- // Process those messages, and wait again.
-
- MSG msg;
- while( PeekMessage(&msg, NULL, 0,0, PM_REMOVE ) )
- {
- if( msg.message != WM_QUIT)
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- else
- {
- /****
- NOTE: putting WM_QUIT back in the Q caused problems. forget about it.
- ****/
- break;
- }
- }
- }break;
- case WAIT_TIMEOUT:
- {
- TRACE(_T("WARNING: Possible Deadlock detected! ThreadID: %d File: %s Line: %d\n"), GetCurrentThreadId(), _T(__FILE__), __LINE__);
- }break;
- }
- }while( dwWait != WAIT_OBJECT_0 );
- ASSERT( dwWait == WAIT_OBJECT_0 );
- }
-
- }
- else
- {
- TRACE(_T("WARNING: Unable to wait for notification that the On_WatchStopped function has been dispatched to another thread.\n"));
- TRACE(_T("An Exception may occur shortly.\n"));
- TRACE(_T("File: %s Line: %d"), _T( __FILE__ ), __LINE__);
-
- }
-
-
- return (dwWait == WAIT_OBJECT_0 );
-}
-
-void CDelayedDirectoryChangeHandler::SetChangedDirectoryName(const CString & strChangedDirName)
-{
- ASSERT( m_pRealHandler );
- CDirectoryChangeHandler::SetChangedDirectoryName(strChangedDirName);
- if( m_pRealHandler )
- m_pRealHandler->SetChangedDirectoryName( strChangedDirName );
-}
-const CString & CDelayedDirectoryChangeHandler::GetChangedDirectoryName() const
-{
- if( m_pRealHandler )
- return m_pRealHandler->GetChangedDirectoryName();
- return CDirectoryChangeHandler::GetChangedDirectoryName();
-} \ No newline at end of file