问候StackOverflowians,
发现here时,Windows 7会出现一个错误,其中不会触发Windows资源管理器实例的DISPID_BEFORENAVIGATE2事件。此事件允许在即将进行导航时通知shell扩展,并且(对我来说最重要的)有机会取消导航。我已经找了很长时间的解决方法,我想我找到了一个。但是,我想对它的安全性有一些看法。
我最近一直在玩API挂钩,而且我已经用它为我的扩展程序挂了几个函数。我注意到有function in IShellBrowser控制导航。起初我以为你不能挂钩那样的东西,但是在阅读layout of a COM object之后,我意识到应该可以通过从任何活动实例的vtable中抓取正确的函数指针来实现它。果然,它像梦一样。设置挂钩后,所有资源管理器窗口中的所有导航都会在我的绕行功能中运行,我可以根据目标pidl决定是否拒绝它们。
所以我的问题是,我有什么理由不这样做吗?我从来没有听说过用于挂钩COM对象函数的API钩子。是否存在不起作用的情况?危险吗? (至少比常规API挂钩更多)
相关代码如下。我正在使用MinHook,这是一个简单的挂钩库,它使用了经过验证的蹦床函数方法。
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;
}
}
答案 0 :(得分:2)
我从来没有听说过使用的API挂钩 挂钩COM对象函数。
COM对象的成员函数实际上并没有那么不同,如果你坚持通常的挂钩指南,实际上可以很好地挂钩。几年前,我不得不挂钩专有CRM解决方案的COM组件,将其连接到数据库服务器。该应用程序运行良好,并已运行相当稳定了好几年。