Solved

redirecting function to another version of dll

Posted on 2009-04-09
2
780 Views
Last Modified: 2013-12-14
Hi,

I would like to redirect a COM interface method into another version of same dll. I use Detours 2.1 Express to hook the function. in the snippet you can see a sample of hooking the IWebBrowser2::Navigate2 method. it works as expected but not as needed :) what I need is to call the Navigate2 method from custom dll (redirect it).

This is not a problem when it's an ordinary function like i.e. Sleep from kernel32.dll (I can use LoadLibrary, GetProcAddress or DetourFindFunction which in fact tries to use LoadLibrary...). Problem is how to call a COM interface method from custom dll. Any suggestions? Will appreciate any help. Thank you in advance.
#define CINTERFACE
 
#include <windows.h>
#include "detours.h"
#include <stdlib.h>
#include <iostream>
#include <string.h>
 
#include <ObjBase.h>
#include <ExDisp.h>
 
using namespace std;
 
//function prototype
HRESULT (__stdcall *RealNavigate2)(IWebBrowser2 *This,
								VARIANT *URL,
								VARIANT *flags,
								VARIANT *TargetFrameName,
								VARIANT *PostData,
								VARIANT *Headers) = NULL;
 
//detour function
HRESULT __stdcall NewNavigate2(IWebBrowser2 *This,
							VARIANT *URL,
							VARIANT *flags,
							VARIANT *TargetFrameName,
							VARIANT *PostData,
							VARIANT *Headers)
{
	//HERE IT CALLS THE ORIGINAL IWebBrowser2::Navigate2
	//I NEED TO REDIRECT IT TO OTHER VERSION OF SAME DLL
	cout << "hooked Navigate2 :)" << endl;
	HRESULT hr = RealNavigate2(This, URL, flags, TargetFrameName, PostData, Headers);
	return hr;
}
 
 
int main(int argc, char **argv){
	
	if(SUCCEEDED(OleInitialize(NULL))){
		
		IWebBrowser2 *pBr;
		CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, (void**)&pBr);
		
		//assigning the target function for detouring
		RealNavigate2 = pBr->lpVtbl->Navigate2;
		
		//this part is not important, only some string processing
		string url = "http://www.google.com";
		VARIANT myURL;
		VariantInit(&myURL);
		myURL.vt = VT_BSTR;
 
		#ifndef UNICODE
		{
			wchar_t		*buffer;
			DWORD		size;
 
			size = MultiByteToWideChar(CP_ACP, 0, url.c_str(), -1, 0, 0);
			if (!(buffer = (wchar_t *)GlobalAlloc(GMEM_FIXED, sizeof(wchar_t) * size))){
				cout << "badalloc" << endl;
				getchar();
				return 0;
			}
			MultiByteToWideChar(CP_ACP, 0, url.c_str(), -1, buffer, size);
			myURL.bstrVal = SysAllocString(buffer);
			GlobalFree(buffer);
		}
		#else
		myURL.bstrVal = SysAllocString(url);
		#endif		
		
		//attaching target and detour function
		DetourTransactionBegin();
		DetourUpdateThread(GetCurrentThread());
		DetourAttach(&(PVOID&)RealNavigate2, NewNavigate2);
		DetourTransactionCommit();
 
		VARIANT vFlags;
		V_VT(&vFlags) = VT_I4;
		V_I4(&vFlags) = navOpenInNewWindow;
		
		VARIANT vEmpty;
		VariantInit(&vEmpty);
 
		//calling the target function, which gets hooked and it will jump to execution of NewNavigate2 detour function
		HRESULT hr = pBr->lpVtbl->Navigate2(pBr, &myURL, &vEmpty, &vEmpty, &vEmpty, &vEmpty);
		if (SUCCEEDED(hr))
		{
			pBr->lpVtbl->put_Visible(pBr, VARIANT_TRUE);
		}
		else
		{
			pBr->lpVtbl->Quit(pBr);
		}
 
		pBr->lpVtbl->Release(pBr);
 
		OleUninitialize();
 
		
	}
	
	return 0;
}

Open in new window

0
Comment
Question by:StraySod
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
2 Comments
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 500 total points
ID: 24105537
A COM Dll is registered in registry what means that only one (probably the youngest) version is currently active.

The only way I know to call a dll of different version (beside of explicitly loading from file) is to register it in the .manifest file of your application. AFAIK that could be done with MSI but I never did it myself. And I don't know either whether it works for COM as well (but there is a good chance cause the .manifest simply overrules normal registry entries).

Note, for using .manifest files you need XP or Vista.
0
 
LVL 7

Author Closing Comment

by:StraySod
ID: 31568438
Ok, thank you for your reply :) will try it
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Ownerdraw of the grid button.  A singleton class implentation and usage. Continuing from the fifth article about sudoku.   Open the project in visual studio. Go to the class view – CGridButton should be visible as a class.  R…
Introduction: Dialogs (2) modeless dialog and a worker thread.  Handling data shared between threads.  Recursive functions. Continuing from the tenth article about sudoku.   Last article we worked with a modal dialog to help maintain informat…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
THe viewer will learn how to use NetBeans IDE 8.0 for Windows to perform CRUD operations on a MySql database.

726 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question