ICopyHook监控文件夹(一)
作者:flyfish 2010-2-2
一 STDMETHODIMP类型的含义
#if defined(_WIN32) || defined(_MPPC_)
// Win32 doesn't support __export
#ifdef _68K_
#define STDMETHODCALLTYPE __cdecl
#else
#define STDMETHODCALLTYPE __stdcall
#endif
#define STDMETHODVCALLTYPE __cdecl
#define STDAPICALLTYPE __stdcall
#define STDAPIVCALLTYPE __cdecl
#else
#define STDMETHODCALLTYPE __export __stdcall
#define STDMETHODVCALLTYPE __export __cdecl
#define STDAPICALLTYPE __export __stdcall
#define STDAPIVCALLTYPE __export __cdecl
#endif
__cdecl
参数传递顺序: 从右向左 最后一个参数先传递,第一个参数最后传递
栈的维护:调用方清空栈
名字修饰约定:在函数名前加上一个下划线
__stdcall
参数传递顺序: 从右向左 最后一个参数先传递,第一个参数最后传递
栈的维护:被调用方清空栈
名字修饰约定:在函数名前面加下划线,后面加“@”符号和参数的字节数
从上面的宏定义可以看出COM接口中的调用方式采用的是__stdcall,也就是由COM来维护栈。
二 那么COM是如何维护栈的呢?
COM规范规定COM接口都必须从IUnknown继承,IUnknown包含三个函数,分别是 QueryInterface、AddRef、
Release。
在IClassFactory中的两个虚函数CreateInstance和LockServer
IClassFactory : public IUnknown
{
public:
virtual /* [local] */ HRESULT STDMETHODCALLTYPE CreateInstance(
/* [unique][in] */ IUnknown *pUnkOuter,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject) = 0;
virtual /* [local] */ HRESULT STDMETHODCALLTYPE LockServer(
/* [in] */ BOOL fLock) = 0;
};
在IUnknown中可以看到三个虚函数QueryInterface,AddRef,Release
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject) = 0;
virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0;
virtual ULONG STDMETHODCALLTYPE Release( void) = 0;
这两段代码在Unknwn.h文件中
COM中对COM对象生存周期的控制使用了“引用计数”技术
每一个COM对象都记录了一个称为“引用计数”的数值,这个在程序中就是
LONG nLocks=0;
nLocks表示为有多少有效指针在引用该COM对象。当得到了一个指向该对象的接口指针时,引用计数值加1,当
用完了该接口指针后,引用计数减1,当引用计数减到0时,COM对象就应该把自己从内存中清除掉,这样也就达
到了维护栈的目的。
在AddRef函数中引用计数值加1,
在Release函数中引用计数减1,如果为0,就清空该COM对象。
三 ICopyHook介绍
ICopyHook是一个用于创建拷贝钩子处理程序COM接口,可以用来监控文件夹的拷贝,移动,重命名和删除。如
果我们执行这些操作,那么Shell会在执行这些操作之前,调用ICopyHook接口的CopyCallback方法对这些操作
进行验证。
CopyCallback
函数原型
UINT CopyCallback( HWND hwnd,
UINT wFunc,
UINT wFlags,
LPCTSTR pszSrcFile,
DWORD dwSrcAttribs,
LPCTSTR pszDestFile,
DWORD dwDestAttribs
);
其中的参数hwnd是一个窗口句柄
参数wFunc指定要被执行的操作,其取值为下表中所列之一:
常量 取值 含义
FO_COPY 复制 由pszSrcFile指定的文件到由pszDestFile指定的位置。
FO_DELETE 删除 由pszSrcFile指定的文件。
FO_MOVE 移动 由pszSrcFile指定的文件到由pszDestFile指定的位置。
FO_RENAME 重命名 由pszSrcFile指定的文件。
参数wFlags指操作的标志;
参数pszSrcFile指源文件夹
参数dwSrcAttribs指源文件夹属性。
参数pszDestFile指目标文件夹
参数dwDesAttribs目标文件夹属性
函数返回值可以为IDYES、IDNO和IDCANCEL。
CopyCallback返回一个UINT值指示Shell是否应该继续执行这个操作。返回值IDYES表示继续,而返回值IDNO和
IDCANCEL则表示终止。
注意:当一个文件夹对象可以安装多个拷贝钩子处理程序时,Shell会依次调用每个处理程序。只有当每个处理
程序都返回IDYES,或者任何一个拷贝钩子返回IDNO或者IDCANCEL,Shell才真正执行用户请求的操作。
拷贝钩子需要在注册表的下面这些地方注册
注册文件夹的地方
HKEY_CLASSES_ROOT
Directory
Shellex
CopyHookHandlers
your_copyhook
(Default) = {copyhook CLSID value}