问题描述
问候StackOverflowians,
Greetings StackOverflowians,
如发现,Windows 7的功能对于Windows资源管理器实例,不会触发DISPID_BEFORENAVIGATE2事件的错误。此事件允许在即将发生导航时通知shell扩展,并且(最重要的是对我来说)有机会取消导航。我一直在寻找一个解决方法相当一段时间,我想我发现了一个。
As discovered here, Windows 7 features a bug in which the DISPID_BEFORENAVIGATE2 event does not fire for Windows Explorer instances. This event allows shell extensions to be notified when a navigation is about to take place, and (most importantly for me) have the opportunity to cancel the navigation. I've been looking for a workaround for quite some time, and I think I found one. But, I'd like to get some opinions on how safe it is.
我最近一直在玩API,我已经在使用它了。挂钩我的扩展的几个功能。我注意到在IShellBrowser中有我意识到,应该可以通过抓取正确的函数指针从任何活动实例的vtable。果然,它的工作原理就像一个梦想。设置挂钩后,所有资源管理器窗口中的所有导航都会通过我的绕行函数运行,我可以根据目标pidl来决定是否拒绝它们。
I've been playing with API hooking a lot lately, and I'm already using it to hook a few functions for my extension. I noticed that there is a function in IShellBrowser that controls navigation. At first I thought you couldn't hook something like that, but upon reading about the layout of a COM object I realized it should be possible by just grabbing the right function pointer out of the vtable of any active instance. Sure enough, it works like a dream. After the hook is set, all navigations in all Explorer windows run right through my detour function, and I can decide whether to reject them based on their target pidl.
问题是,有什么原因我不应该这样做吗?我从来没有听说过API钩子用来挂钩COM对象函数。有没有情况下它不会工作?危险吗? (至少比常规API挂钩多了)
So my question is, is there any reason I should NOT do this? I've never heard of API hooking used to hook COM object functions. Are there circumstances it which it wouldn't work? Is it dangerous? (Any more than regular API hooking, at least)
相关代码如下。我正在使用,一个简约的挂钩库,它使用已尝试和trampoline函数的真实方法。
The relevant code follows. I'm using MinHook, a minimalistic hooking library that uses the tried-and-true method of trampoline functions.
typedef HRESULT (WINAPI *BROWSEOBJECT)(IShellBrowser*, PCUIDLIST_RELATIVE, UINT);
HRESULT WINAPI DetourBrowseObject(IShellBrowser* _this, PCUIDLIST_RELATIVE pidl, UINT wFlags);
BROWSEOBJECT fpBrowseObject = NULL;
BROWSEOBJECT ShellBrowser_BrowseObject = NULL;
bool Initialize() {
if(MH_Initialize() != MH_OK) {
return false;
}
// Get a reference to an existing IShellBrowser. Any instance will do.
// ShellBrowser enum code taken from The Old New Thing
IShellWindows *psw;
BOOL fFound = FALSE;
if (SUCCEEDED(CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_ALL, IID_IShellWindows, (void**)&psw))) {
VARIANT v;
V_VT(&v) = VT_I4;
IDispatch *pdisp;
for (V_I4(&v) = 0; !fFound && psw->Item(v, &pdisp) == S_OK; V_I4(&v)++) {
IWebBrowserApp *pwba;
if (SUCCEEDED(pdisp->QueryInterface(IID_IWebBrowserApp, (void**)&pwba))) {
IServiceProvider *psp;
if (SUCCEEDED(pwba->QueryInterface(IID_IServiceProvider, (void**)&psp))) {
IShellBrowser *psb;
if (SUCCEEDED(psp->QueryService(SID_STopLevelBrowser,IID_IShellBrowser, (void**)&psb))) {
fFound = true;
// Grab the 11th entry in the VTable, which is BrowseObject
void** vtable = (*(void***)(psb));
ShellBrowser_BrowseObject = (BROWSEOBJECT)(vtable[11]);
psb->Release();
}
psp->Release();
}
pwba->Release();
}
pdisp->Release();
}
psw->Release();
}
if(fFound) {
if(MH_CreateHook(ShellBrowser_BrowseObject, &DetourBrowseObject, reinterpret_cast<void**>(&fpBrowseObject)) != MH_OK) {
return false;
}
if(MH_EnableHook(ShellBrowser_BrowseObject) != MH_OK) {
return false;
}
}
return true;
}
HRESULT WINAPI DetourBrowseObject(IShellBrowser* _this, PCUIDLIST_RELATIVE pidl, UINT wFlags) {
if(NavigateIsOkay(pidl, wFlags)) {
return fpBrowseObject(_this, pidl, wFlags);
}
else {
return S_FALSE;
}
}
推荐答案
的COM对象不是真的那么不同,实际上可以钩住只是罚款,如果你坚持通常的钩子的准则。几年前,我不得不挂钩一个专有的CRM解决方案的COM组件来连接到一个数据库服务器。该应用程序工作正常,并已运行相当稳定几年。
Member functions of COM Objects are not really that different and can actually be hooked just fine if you stick to the usual guidelines for hooking. A few years ago, I had to hook COM components of a proprietary CRM solution to connect it to a database server. The application worked fine and has been running quite stable for several years.
这篇关于API Hook上一个COM对象函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!