龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > C/C++开发 >

用拷贝钩子实现对文件夹的监控

时间:2009-12-22 15:42来源:未知 作者:admin 点击:
分享到:
本文原出处已不知。原作:webber84, 经ccrun(老妖)修改并在BCB在调试通过。 ICopyHook是一个用于创建拷贝钩子处理程序COM接口,它决定一个文件夹或者打印机对象是否可以被移动,拷贝,

  本文原出处已不知。原作:webber84, 经ccrun(老妖)修改并在BCB在调试通过。

  

ICopyHook是一个用于创建拷贝钩子处理程序COM接口,它决定一个文件夹或者打印机对象是否可以被移动,拷贝,重命名或删除。Shell在执行这些操作之前,会调用ICopyHook接口的CopyCallback方法对它们进行验证。CopyCallback返回一个int值指示Shell是否应该继续执行这个操作。返回值IDYES表示继续,而返回值IDNO和IDCANCEL则表示终止。

  

  

一个文件夹对象可以安装多个拷贝钩子处理程序。假如出现这种情况,Shell会依次调用每个处理程序。只有当每个处理程序都返回IDYES时,Shell才真正执行用户请求的操作。

  

  

拷贝钩子处理程序的作用是在上述四种操作执行前对它们进行验证,但是Shell并不会把操作的结果通知给拷贝钩子处理程序。而windows提供的API函数FindFirstChangeNotification和FindNextChangeNotification却可以实现这个功能。因此,只有把这种两种方法结合起来,才能对一个文件夹的状态进行完全的监控。

  

  

拷贝钩子处理程序实现并不困难,首先创建一个作为进程内组件的COM对象,它只需要暴露一个ICopyHook接口(当然还有IUnknown)。然后用regsrv32.exe注册这个COM组件。最后一步是向Shell注册你的这个拷贝钩子处理程序,方法是在注册表HKEY_CLASSES_ROOTDirectoryShellexCopyHookHandlers下创建一个名称任意的sub key,在此sub key中创建一个类型为REG_SZ的项并将你的COM对象的CLSID作为它的默认值就可以了。

  

  

下面就是一个拷贝钩子的实现程序(注:以下代码经老妖改动并添加了具体操作过程,在BCB6中成功编译并通过测试)

  

  

1. 从ICopyHook接口创建TCopyHook,从IClassFactory接口创建TClassFactory:

  

  

// TCopyHook.h

  

// TCopyHook类实现了ICopyHook接口,TClassFactory实现了IClassFactory接口

  

//---------------------------------------------------------------------------

  

#define NO_WIN32_LEAN_AND_MEAN

  

#include

  

//---------------------------------------------------------------------------

  

class TCopyHook: public ICopyHook

  

{

  

public:

  

TCopyHook():m_refcnt(0) {}

  

STDMETHODIMP QueryInterface(REFIID iid,void **ppvObject);

  

STDMETHODIMP_(ULONG) AddRef();

  

STDMETHODIMP_(ULONG) Release();

  

STDMETHODIMP_(UINT) CopyCallback(HWND hwnd, UINT wFunc, UINT wFlags,

  

LPCTSTR pszSrcFile, DWord dwSrcAttribs,

  

LPCTSTR pszDestFile, DWORD dwDestAttribs);

  

private:

  

int m_refcnt;

  

};

  

//---------------------------------------------------------------------------

  

class TClassFactory : public IClassFactory

  

{

  

public:

  

TClassFactory():m_refcnt(0) {}

  

STDMETHODIMP QueryInterface(REFIID iid, void **ppvObject);

  

STDMETHODIMP_(ULONG) AddRef();

  

STDMETHODIMP_(ULONG) Release();

  

STDMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject);

  

  

STDMETHODIMP LockServer(BOOL fLock);

  

private:

  

int m_refcnt;

  

};

  

  

  

// TCopyHook.cpp

  

// TCopyHook对象和TClassFactory对象的实现文件

  

#include

  

#include "TCopyHook.h"

  

//---------------------------------------------------------------------------

  

extern LONG nLocks; // 对象计数,用于DllCanUnloadNow

  

ULONG __stdcall TCopyHook::AddRef()

  

{

  

if(m_refcnt == 0)

  

nLocks++;

  

m_refcnt++;

  

return m_refcnt;

  

}

  

//---------------------------------------------------------------------------

  

ULONG __stdcall TCopyHook::Release()

  

{

  

int nNewCnt = --m_refcnt;

  

if(nNewCnt <= 0)

  

{

  

nLocks--;

  

delete this;

  

}

  

return nNewCnt;

  

}

  

//---------------------------------------------------------------------------

  

HRESULT __stdcall TCopyHook::QueryInterface(REFIID dwIID, void **ppvObject)

  

{

  

if(dwIID == IID_IUnknown)

  

*ppvObject = static_cast(this);

  

else

  

if(dwIID == IID_IShellCopyHook)

  

*ppvObject = static_cast(this);

  

else

  

return E_NOINTERFACE;

  

reinterpret_cast(*ppvObject)->AddRef();

  

return S_OK;

  

}

  

//---------------------------------------------------------------------------

  

// 这就是CopyCallback方法,拷贝钩子的所有功能由它实现。参数的具体值参看MSDN

  

UINT __stdcall TCopyHook::CopyCallback(HWND hwnd, UINT wFunc, UINT wFlags,

  

LPCTSTR pszSrcFile, DWORD dwSrcAttribs,

  

LPCTSTR pszDestFile, DWORD dwDestAttribs)

  

{

  

char szMessage[MAX_PATH+14];

  

sprintf(szMessage, "对%s进行的操作,是否继续?", pszSrcFile);

  

return MessageBox(NULL, szMessage, "确认", MB_YESNO MB_ICONEXCLAMATION);

  

}

  

//---------------------------------------------------------------------------

  

  

ULONG __stdcall TClassFactory::AddRef()

  

{

  

if(m_refcnt==0)

  

nLocks++;

  

m_refcnt++;

  

return m_refcnt;

  

}

  

//---------------------------------------------------------------------------

  

ULONG __stdcall TClassFactory::Release()

  

{

  

  

int nNewCnt = --m_refcnt;

  

  

if(nNewCnt <= 0)

  

{

  

nLocks--;

  

delete this;

  

}

  

return nNewCnt;

  

}

  

//---------------------------------------------------------------------------

  

HRESULT __stdcall TClassFactory::QueryInterface(REFIID dwIID, void **ppvObject)

  

{

  

if(dwIID == IID_IUnknown)

  

*ppvObject = static_cast(this);

  

else

  

if(dwIID == IID_IClassFactory)

  

*ppvObject = static_cast(this);

  

else

  

return E_NOINTERFACE;

  

reinterpret_cast(*ppvObject)->AddRef();

  

return S_OK;

  

}

  

//---------------------------------------------------------------------------

  

HRESULT __stdcall TClassFactory::CreateInstance(IUnknown* pUnkownOuter,

  

&

  

精彩图集

赞助商链接