Hello and good day to you.
Situation:
For some reason, from time to time I run into situation when I need to override one or two methods of a COM interface (that is being used for some older application without source code), which is normally Direct3D/DirectInput related (i.e. it is created by calling a DLL method, not by CoCreateInstance). Normally I deal with situation by writing a proxy DLL that overrides a method that creates interface I need to “modify”, and replace original interface with my own. Normally this is required to make some older application work properly without crashing/artifacts.
Compiler:
I use Visual Studio express 2008 on windows machine, so there are no C++0x features. The system has msysgit, msys, python, perl, gnu utilities (awk/sed/wc/bash/etc), gnu make and qmake (Qt-4.7.1) installed (and available within PATH).
Problem:
Overriding one method of a COM interface is a pain (especially if original interface has a hundred of methods or so), because I need to forward many calls to original interface, and currently I see no way to simplify or automate the process. For example, override of IDirect3D9 looks like this:
class MyD3D9: public IDirect3D9{
protected:
volatile LONG refCount;
IDirect3D9 *orig;
public:
STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj){
if (!ppvObj)
return E_INVALIDARG;
*ppvObj = NULL;
if (riid == IID_IUnknown || riid == IID_IDirect3D9){
*ppvObj = (LPVOID)this;
AddRef();
return NOERROR;
}
return E_NOINTERFACE;
}
STDMETHOD_(ULONG,AddRef)(THIS){
InterlockedIncrement(&refCount);
return refCount;
}
STDMETHOD_(ULONG,Release)(THIS){
ULONG ref = InterlockedDecrement(&refCount);
if (refCount == 0)
delete this;
return ref;
}
/*** IDirect3D9 methods ***/
STDMETHOD(RegisterSoftwareDevice)(THIS_ void* pInitializeFunction){
if (!orig)
return E_FAIL;
return orig->RegisterSoftwareDevice(pInitializeFunction);
}
STDMETHOD_(UINT, GetAdapterCount)(THIS){
if (!orig)
return 0;
return orig->GetAdapterCount();
}
STDMETHOD(GetAdapterIdentifier)(THIS_ UINT Adapter,DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier){
if (!orig)
return E_FAIL;
return orig->GetAdapterIdentifier(Adapter, Flags, pIdentifier);
}
STDMETHOD_(UINT, GetAdapterModeCount)(THIS_ UINT Adapter,D3DFORMAT Format){
if (!orig)
return 0;
return orig->GetAdapterModeCount(Adapter, Format);
}
/* some code skipped*/
MyD3D9(IDirect3D9* origD3D9)
:refCount(1), orig(origD3D9){
}
~MyD3D9(){
if (orig){
orig->Release();
orig = 0;
}
}
};
As you can see, this is very inefficient, error-prone and requires a lot of copy-pasting.
Question:
How can I simplify overriding of a single method of a COM interface in this situation? I would like to specify only method I change, but I currently see no way to do so. I also don’t see a way to elegantly shorten “forwarded” methods with macros or templates or macros, because they have variable number of arguments. Another approach I saw is to use directly patch method table returned by another method (modify access right using VirtualProtect, then write into method table), which I don’t exactly like.
Limitations:
I would prefer to solve in C++ source code (macros/templates) and without code generators (unless code generator usage is extremely simple/elegant – i.e. writing code generator is not ok, using already available code generator I can set up in minutes and solve the whole thing in one line of code is ok). Boost is okay only if it doesn’t add extra DLL dependency. MS-specific compiler directives and language extensions are also ok.
Ideas? Thanks in advance.
Okay, since I don’t like unanswered questions…
To implement “COM implementation inheritance” there’s currently no sane and compact solution written in pure C++. This is mostly because in C++ it is forbidden to create an instance of abstract class or manipulate virtual method table directly. As a result, there are 2 commonly used solutions:
Advantage of #1 is that this approach is safe and you can store additional data within custom class.
Disadvantage of #1 is that writing a wrapper for every single method is extremely tedious procedure.
Advantage of #2 is that this approach is compact. You replace single method.
Disadvantage of #2 is that dispatch table might be located in write-protected space (most likely it wouldn’t happen, but it could happen in theory) and you can’t store custom data in hacked interface. As a result, although it is simple/short, it is quite limiting.
And there’s a 3rd approach. (which nobody has suggested for some reason)
Short description: instead of using virtual method table provided by C++, write non-virtual class that will emulate virtual method table.
Example:
To swap it with real interface, you’ll have to use
reinterpret_cast.As you can see this method requires assembly, macros, templates combined together with casting class method pointer to void*. Also it is compiler-dependent(msvc, although you should be able to do same trick with g++) and architecture-dependent (32/64-bit). Plus it is unsafe (as with dispatch table hacking).
The advantage compared to dispatch tables you can use custom class and store additional data within interface. However: