saludos StackOverflowians,Gancho API en una función de objeto COM?
Como descubrió here, Windows 7 ofrece un fallo en el que el evento DISPID_BEFORENAVIGATE2 no se dispara para las instancias de Windows Explorer. Este evento permite que se notifiquen las extensiones de shell cuando está a punto de realizarse una navegación, y (lo que es más importante para mí) tenemos la oportunidad de cancelar la navegación. He estado buscando una solución por bastante tiempo, y creo que encontré una. Pero me gustaría obtener algunas opiniones sobre cuán seguro es.
He estado jugando con API enganchándose mucho últimamente, y ya lo estoy usando para conectar algunas funciones para mi extensión. Me di cuenta de que hay un function in IShellBrowser que controla la navegación. Al principio pensé que no podías enganchar algo así, pero al leer sobre el layout of a COM object me di cuenta que debería ser posible simplemente tomando el puntero de la función derecha del vtable de cualquier instancia activa. Efectivamente, funciona como un sueño. Después de establecer el enganche, todas las navegaciones en todas las ventanas del Explorador se ejecutan directamente a través de mi función de desvío, y puedo decidir si las rechazaré en función de su pidl de destino.
Entonces mi pregunta es, ¿hay alguna razón por la que NO deba hacer esto? Nunca escuché sobre el enganche API utilizado para enganchar funciones de objetos COM. ¿Hay circunstancias en las que no funcionaría? ¿Es peligroso? (Más que el enganche API regular, al menos)
El código relevante a continuación. Estoy usando MinHook, una biblioteca de enlaces minimalista que usa el método comprobado de funciones de trampolín.
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;
}
}
Gracias por la tranquilidad. =) –
Esta respuesta es incorrecta. ¡El enganche COM es muy especial, especialmente en Internet Explorer y no tiene nada en común con el enganche de API común! Un objeto COM puede ser envuelto en un objeto contenedor y finalmente solo engancha el contenedor. Lee los enlaces en este artículo: http://stackoverflow.com/questions/1505196/spying-on-com-objects – Elmue