描述:
HOOK OF COM (1)
很少看见这样的话题,前不久在www.codeguru.com 看到了这篇文章,觉得不错,
最近写COM程序,看到这个,翻译了以下,有错在所难免,欢迎指教
、、、、、、、、、、、
我还将翻译作者的其他2篇文章 HOOK OF COM (2) 过些日 翻译 完毕
、、、、、、、、、、、
/*
翻译文档来自www.codeguru.com
原作者: Chunhua Liu(好像是在美国工作的中国人,程序写的不错)
程序修改
,翻译: 赵宗宝
本人邮箱:An_Eagle@163.com
时间:2005-12-10 19:30
备注: 我一直希望HOOK OF COM 这样的文档有中文文档(参考的资料实在太少了)
第一次翻译难免有错误的地方,请您发E_Mail我一定及时改正
提供源代码,以及编译过的文件,只要我有时间我就恢复你
声明: 版权归原作者所有.
测试环境:WindowsXP-SP2(English), Visual C++ 6.0(Englsh), MSDN 2003 FEB(CHINA)
还有一个BUG: 有时HOOK会有问题
*/
自2001.Oct后, 我们在vc6里就不能按F1键使用最新的MSDN.微软已经改变了从CHM到
文挡浏览器的格式。
在vc6里可以使用最新的MSDN吗?
问题的答案当然是“YES”!
详述:
首先,我们必须知道在vc6中按下F1是如何引发帮助的。如果你有像Soft-ICE这样的调试器
这一起显的很简单。
如果你没有安装MSDN.当你按下F1后,vc6将弹出一个消息对话框内容是你没有安装MSDN.
在MessageBox设置断点。按F1并且调试对话框。看看栈。我们将看到这个函数引发自
"C:\Program Files\Common Files\Microsoft Shared\VS98\vshelp.dll"
Then we use Dependency Walker ("depends" in Visual Studio Tools) to see
what functions are exported. We will see DllRegisterServer
and DllUnregisterServer. It's obviously a COM.
用vc6创建一个a simple console project. 增加下面这行语句在.CPP文件中
#import "c:\Program Files\Common Files\Microsoft Shared\VS98\vshelp.dll"
编译工程。在Debug目录里,你会发现"vshelp.tlh"和"vshelp.thi".打开"vshelp.tlh",我们看见
struct __declspec(uuid("854d7ac0-bc3d-11d0-b421-00a0c90f9dc4"))
IVsHelpSystem : IUnknown
{
//
// Wrapper methods for error-handling
//
HRESULT KeywordSearch ( // 这里这里
LPWSTR pszKeyword,
long dwFlags,
long dwReserved );
HRESULT ALinkSearch (
LPWSTR pszALink,
long dwFlags,
long dwReserved );
......
}
当我们按F1后KeywordSearch函数被调用.因此我们替换这个函数并把她调用最新的MSDN帮助函数,那么帮助将会
起作用.
怎么去实施呢?因为是一个COM 接口,因此很容易Hook It
基础的COM接口就是一个C++的虚函数表。她有一个指向所有虚函数表地址的头指针.并且这个表共享了所有的实例
所以我们仅仅需要改变虚函数在表里的地址。这个接口看起来是这样。
struct _IVsHelpSystemVtbl
{
HRESULT (STDMETHODCALLTYPE *QueryInterface)(IUnknown *This, REFIID riid, void **ppvObject);
ULONG (STDMETHODCALLTYPE *AddRef)(IUnknown *This);
ULONG (STDMETHODCALLTYPE *Release)(IUnknown *This);
HRESULT (STDMETHODCALLTYPE *KeywordSearch)(IUnknown *This,LPWSTR pszKeyword,long dwFlag, long dwReserved);
};
struct _IVsHelpSystem
{
struct _IVsHelpSystemVtb1 *lpVtbl;
};
我们需要的是仅仅创建这个COM实例.并且我们将得到这个表的地址。
现在我们需要知道最新的MSDN是如何引发的.It seems it's not documented. It's also a COM
在CPP文件中加入下面的这句.你将得到COM的声明
#import "C:\Program Files\Common Files\Microsoft Shared\MSEnv\vshelp.tlb"
在"vshelp.tlh"中,你将发现这样的函数:
HRESULT DisplayTopicFromF1Keyword( _bstr_t pszKeyword );
很明显,这是我们需要的。所以我们在KeywordSearch函数里,调用DisplayTopicFromF1Keyword就会
引用最新的MSDN。