⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 directorychanges.cpp

📁 局域网来访者IP监视以及文件修改监视: 1.监听常用的局域网访问工具
💻 CPP
📖 第 1 页 / 共 5 页
字号:
			//
			// This sometimes happens if the watched directory becomes deleted... remove the FILE_SHARE_DELETE flag when using CreateFile() to get the handle to the directory...
			m_pCurrentRecord = pOld;
		}
					
		return (BOOL)(m_pCurrentRecord != pOld);
	}
	return FALSE;
}

BOOL CFileNotifyInformation::CopyCurrentRecordToBeginningOfBuffer(OUT DWORD & ref_dwSizeOfCurrentRecord)
/*****************************************
   Copies the FILE_NOTIFY_INFORMATION record to the beginning of the buffer
   specified in the constructor.

   The size of the current record is returned in DWORD & dwSizeOfCurrentRecord.
   
*****************************************/
{
	ASSERT( m_pBuffer && m_pCurrentRecord );
	if( !m_pCurrentRecord ) return FALSE;

	BOOL bRetVal = TRUE;

	//determine the size of the current record.
	ref_dwSizeOfCurrentRecord = sizeof( FILE_NOTIFY_INFORMATION );
	//subtract out sizeof FILE_NOTIFY_INFORMATION::FileName[1]
	WCHAR FileName[1];//same as is defined for FILE_NOTIFY_INFORMATION::FileName
	UNREFERENCED_PARAMETER(FileName);
	ref_dwSizeOfCurrentRecord -= sizeof(FileName);   
	//and replace it w/ value of FILE_NOTIFY_INFORMATION::FileNameLength
	ref_dwSizeOfCurrentRecord += m_pCurrentRecord->FileNameLength;

	ASSERT( (DWORD)((LPBYTE)m_pCurrentRecord + ref_dwSizeOfCurrentRecord) <= m_dwBufferSize );

	ASSERT( (void*)m_pBuffer != (void*)m_pCurrentRecord );//if this is the case, your buffer is way too small
	if( (void*)m_pBuffer != (void*) m_pCurrentRecord )
	{//copy the m_pCurrentRecord to the beginning of m_pBuffer
		
		ASSERT( (DWORD)m_pCurrentRecord > (DWORD)m_pBuffer + ref_dwSizeOfCurrentRecord);//will it overlap?
		__try{
			memcpy(m_pBuffer, m_pCurrentRecord, ref_dwSizeOfCurrentRecord);
			bRetVal = TRUE;
		}
		__except(EXCEPTION_EXECUTE_HANDLER)
		{
			TRACE(_T("EXCEPTION!  CFileNotifyInformation::CopyCurrentRecordToBeginningOfBuffer() -- probably because bytes overlapped in a call to memcpy()"));
			bRetVal = FALSE;
		}
	}
	//else
	//there was only one record in this buffer, and m_pCurrentRecord is already at the beginning of the buffer
	return bRetVal;
}

DWORD CFileNotifyInformation::GetAction() const
{ 
	ASSERT( m_pCurrentRecord );
	if( m_pCurrentRecord )
		return m_pCurrentRecord->Action;
	return 0UL;
}

CString CFileNotifyInformation::GetFileName() const
{
	//
	//BUG FIX:
	//		File Name's longer than 130 characters are truncated
	//
	//		Thanks Edric @ uo_edric@hotmail.com for pointing this out.
	if( m_pCurrentRecord )
	{
		WCHAR wcFileName[ MAX_PATH + 1] = {0};//L"";
		memcpy(	wcFileName, 
				m_pCurrentRecord->FileName, 
				//min( MAX_PATH, m_pCurrentRecord->FileNameLength) <-- buggy line
				min( (MAX_PATH * sizeof(WCHAR)), m_pCurrentRecord->FileNameLength));
		

		return CString( wcFileName );
	}
	return CString();
}		

static inline bool HasTrailingBackslash(const CString & str )
{
	if( str.GetLength() > 0 
	&&	str[ str.GetLength() - 1 ] == _T('\\') )
		return true;
	return false;
}
CString CFileNotifyInformation::GetFileNameWithPath(const CString & strRootPath) const
{
	CString strFileName( strRootPath );
	//if( strFileName.Right(1) != _T("\\") )
	if( !HasTrailingBackslash( strRootPath ) )
		strFileName += _T("\\");

	strFileName += GetFileName();
	return strFileName;
}
/////////////////////////////////////////////////////////////////////////////////
class CPrivilegeEnabler
//
//	Enables privileges for this process
//	first time CDirectoryChangeWatcher::WatchDirectory() is called.
//
//	It's a singleton.
//
{
private:
	CPrivilegeEnabler();//ctor
public:
	~CPrivilegeEnabler(){};
	
	static CPrivilegeEnabler & Instance();
	//friend static CPrivilegeEnabler & Instance();
};

CPrivilegeEnabler::CPrivilegeEnabler()
{
	LPCTSTR arPrivelegeNames[]	=	{
										SE_BACKUP_NAME, //	these two are required for the FILE_FLAG_BACKUP_SEMANTICS flag used in the call to 
										SE_RESTORE_NAME,//  CreateFile() to open the directory handle for ReadDirectoryChangesW

										SE_CHANGE_NOTIFY_NAME //just to make sure...it's on by default for all users.
										//<others here as needed>
									};
	for(int i = 0; i < sizeof(arPrivelegeNames) / sizeof(arPrivelegeNames[0]); ++i)
	{
		if( !EnablePrivilege(arPrivelegeNames[i], TRUE) )
		{
			TRACE(_T("Unable to enable privilege: %s	--	GetLastError(): %d\n"), arPrivelegeNames[i], GetLastError());
			TRACE(_T("CDirectoryChangeWatcher notifications may not work as intended due to insufficient access rights/process privileges.\n"));
			TRACE(_T("File: %s Line: %d\n"), _T(__FILE__), __LINE__);
		}
	}
}

CPrivilegeEnabler & CPrivilegeEnabler::Instance()
{
	static CPrivilegeEnabler theInstance;//constructs this first time it's called.
	return theInstance;
}
//
//
//
///////////////////////////////////////////////////////////

	
//
//
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDirectoryChangeHandler::CDirectoryChangeHandler()
: m_nRefCnt( 1 ),
  m_pDirChangeWatcher( NULL ),
  m_nWatcherRefCnt( 0L )
{
}

CDirectoryChangeHandler::~CDirectoryChangeHandler()
{
	UnwatchDirectory();
}

long CDirectoryChangeHandler::AddRef()
{ 
	return InterlockedIncrement(&m_nRefCnt);	
}

long CDirectoryChangeHandler::Release()
{  
	long nRefCnt = -1;
	if( (nRefCnt = InterlockedDecrement(&m_nRefCnt)) == 0 )
		delete this;
	return nRefCnt;
}
long CDirectoryChangeHandler::CurRefCnt()const 
{ 
	return m_nRefCnt;
}

BOOL CDirectoryChangeHandler::UnwatchDirectory()
{
	CSingleLock lock(&m_csWatcher, TRUE);	
	ASSERT( lock.IsLocked() );
	
	if( m_pDirChangeWatcher )
		return m_pDirChangeWatcher->UnwatchDirectory( this );
	return TRUE;
}

long  CDirectoryChangeHandler::ReferencesWatcher(CDirectoryChangeWatcher * pDirChangeWatcher)
{
	ASSERT( pDirChangeWatcher );
	CSingleLock lock(&m_csWatcher, TRUE);
	if( m_pDirChangeWatcher 
	&&  m_pDirChangeWatcher != pDirChangeWatcher )
	{
		TRACE(_T("CDirectoryChangeHandler...is becoming used by a different CDirectoryChangeWatcher!\n"));
		TRACE(_T("Directories being handled by this object will now be unwatched.\nThis object is now being used to ")
			  _T("handle changes to a directory watched by different CDirectoryChangeWatcher object, probably on a different directory"));
		
		if( UnwatchDirectory() )
		{
			m_pDirChangeWatcher = pDirChangeWatcher;
			m_nWatcherRefCnt = 1; //when this reaches 0, set m_pDirChangeWatcher to NULL
			return m_nWatcherRefCnt;
		}
		else
		{
			ASSERT( FALSE );//shouldn't get here!
		}
	}
	else
	{
		ASSERT( !m_pDirChangeWatcher || m_pDirChangeWatcher == pDirChangeWatcher );
		
		m_pDirChangeWatcher = pDirChangeWatcher;	
		
		if( m_pDirChangeWatcher )
			return InterlockedIncrement(&m_nWatcherRefCnt);
		
	}
	return m_nWatcherRefCnt;
}

long CDirectoryChangeHandler::ReleaseReferenceToWatcher(CDirectoryChangeWatcher * pDirChangeWatcher)
{
	ASSERT( m_pDirChangeWatcher == pDirChangeWatcher );
	CSingleLock lock(&m_csWatcher, TRUE);
	long nRef;
	if( (nRef = InterlockedDecrement(&m_nWatcherRefCnt)) <= 0L )
	{
		m_pDirChangeWatcher = NULL; //Setting this to NULL so that this->UnwatchDirectory() which is called in the dtor
									//won't call m_pDirChangeWatcher->UnwatchDirecotry(this).
									//m_pDirChangeWatcher may point to a destructed object depending on how
									//these classes are being used.
		m_nWatcherRefCnt = 0L;
	}
	return nRef;
}

//
//
//	Default implmentations for CDirectoryChangeHandler's virtual functions.
//
//
void CDirectoryChangeHandler::On_FileAdded(const CString & strFileName)
{ 
	TRACE(_T("The following file was added: %s\n"), strFileName);
}

void CDirectoryChangeHandler::On_FileRemoved(const CString & strFileName)
{
	TRACE(_T("The following file was removed: %s\n"), strFileName);
}

void CDirectoryChangeHandler::On_FileModified(const CString & strFileName)
{
	TRACE(_T("The following file was modified: %s\n"), strFileName);
}

void CDirectoryChangeHandler::On_FileNameChanged(const CString & strOldFileName, const CString & strNewFileName)
{
	TRACE(_T("The file %s was RENAMED to %s\n"), strOldFileName, strNewFileName);
}
void CDirectoryChangeHandler::On_ReadDirectoryChangesError(DWORD dwError, const CString & strDirectoryName)
{
	TRACE(_T("WARNING!!!!!\n") );
	TRACE(_T("An error has occurred on a watched directory!\n"));
	TRACE(_T("This directory has become unwatched! -- %s \n"), strDirectoryName);
	TRACE(_T("ReadDirectoryChangesW has failed! %d"), dwError);
	ASSERT( FALSE );//you should override this function no matter what. an error will occur someday.
}

void CDirectoryChangeHandler::On_WatchStarted(DWORD dwError, const CString & strDirectoryName)
{	
	if( dwError == 0 )
		TRACE(_T("A watch has begun on the following directory: %s\n"), strDirectoryName);
	else
		TRACE(_T("A watch failed to start on the following directory: (Error: %d) %s\n"),dwError, strDirectoryName);
}

void CDirectoryChangeHandler::On_WatchStopped(const CString & strDirectoryName)
{
	TRACE(_T("The watch on the following directory has stopped: %s\n"), strDirectoryName);
}

bool CDirectoryChangeHandler::On_FilterNotification(DWORD /*dwNotifyAction*/, LPCTSTR /*szFileName*/, LPCTSTR /*szNewFileName*/)
//
//	bool On_FilterNotification(DWORD dwNotifyAction, LPCTSTR szFileName, LPCTSTR szNewFileName);
//
//	This function gives your class a chance to filter unwanted notifications.
//
//	PARAMETERS: 
//			DWORD	dwNotifyAction	-- specifies the event to filter
//			LPCTSTR szFileName		-- specifies the name of the file for the event.
//			LPCTSTR szNewFileName	-- specifies the new file name of a file that has been renamed.
//
//	RETURN VALUE:
//			return true from this function, and you will receive the notification.
//			return false from this function, and your class will NOT receive the notification.
//
//	Valid values of dwNotifyAction:
//		FILE_ACTION_ADDED			-- On_FileAdded() is about to be called.
//		FILE_ACTION_REMOVED			-- On_FileRemoved() is about to be called.
//		FILE_ACTION_MODIFIED		-- On_FileModified() is about to be called.
//		FILE_ACTION_RENAMED_OLD_NAME-- On_FileNameChanged() is about to be call.
//
//	  
//	NOTE:  When the value of dwNotifyAction is FILE_ACTION_RENAMED_OLD_NAME,
//			szFileName will be the old name of the file, and szNewFileName will
//			be the new name of the renamed file.
//
//  The default implementation always returns true, indicating that all notifications will 
//	be sent.
//	
{
	return true;
}

void CDirectoryChangeHandler::SetChangedDirectoryName(const CString & strChangedDirName)
{
	m_strChangedDirectoryName = strChangedDirName;
}
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////

CDirectoryChangeWatcher::CDirectoryChangeWatcher(bool bAppHasGUI /*= true*/, DWORD dwFilterFlags/*=FILTERS_CHECK_FILE_NAME_ONLY*/)
: m_hCompPort( NULL )
 ,m_hThread( NULL )
 ,m_dwThreadID( 0UL )
 ,m_bAppHasGUI( bAppHasGUI )
 ,m_dwFilterFlags( dwFilterFlags == 0? FILTERS_DEFAULT_BEHAVIOR : dwFilterFlags)
{
	//NOTE:  
	//	The bAppHasGUI variable indicates that you have a message pump associated
	//	with the main thread(or the thread that first calls CDirectoryChangeWatcher::WatchDirectory() ).
	//	Directory change notifications are dispatched to your main thread.
	//	
	//	If your app doesn't have a gui, then pass false.  Doing so causes a worker thread
	//	to be created that implements a message pump where it dispatches/executes the notifications.
	//  It's ok to pass false even if your app does have a GUI.
	//	Passing false is required for Console applications, or applications without a message pump.
	//	Note that notifications are fired in a worker thread.
	//

	//NOTE:
	//
	//
}

CDirectoryChangeWatcher::~CDirectoryChangeWatcher()
{

	UnwatchAllDirectories();

	if( m_hCompPort )
	{
		CloseHandle( m_hCompPort );
		m_hCompPort = NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -