Я нашел следующее (от интерпретации COM-интерфейсов как чистых структур C + function и хаков Direct X). Работает, но не решает проблему по какой-то причине. Я должен сделать то же самое для рабочих книг, рабочих листов ...
Declare:
typedef HRESULT STDMETHODCALLTYPE QueryInterfacePtr( REFIID, void **);
typedef ULONG STDMETHODCALLTYPE AddRefPtr( );
typedef ULONG STDMETHODCALLTYPE ReleasePtr( );
typedef ULONG STDMETHODCALLTYPE GetTypeInfoCountPtr( UINT *) ;
typedef ULONG STDMETHODCALLTYPE GetTypeInfoPtr ( UINT, LCID, ITypeInfo **) ;
typedef ULONG STDMETHODCALLTYPE GetIDsOfNamesPtr ( REFIID, LPOLESTR *,
UINT, LCID, DISPID *) ;
typedef ULONG STDMETHODCALLTYPE InvokePtr ( DISPID, REFIID,
LCID, WORD, DISPPARAMS *,
VARIANT *, EXCEPINFO *, UINT *) ;
typedef struct {
// IUnknown functions
QueryInterfacePtr * QueryInterface;
AddRefPtr * AddRef;
ReleasePtr * Release;
// IDispatch functions
GetTypeInfoCountPtr* GetTypeInfoCount;
GetTypeInfoPtr* GetTypeInfo;
GetIDsOfNamesPtr* GetIDsOfNames;
InvokePtr* Invoke;
} IDispatchInterceptor;
typedef ULONG __stdcall releasePTR(IDispatch *self);
typedef ULONG __stdcall addrefPTR(IDispatch *self);
Далее я сделал для Excel:
<pre>
static IDispatch * application = NULL;
static releasePTR* realRelease = NULL;
static addrefPTR* realAddRef = NULL;
static ULONG wasAdd = 0;
static ULONG oldCount = 0;</p>
<p>HRESULT STDMETHODCALLTYPE QueryInterfaceNativeOutOfProcSrv(REFIID riid, void **ppv){
return application->QueryInterface(riid,ppv);<br>
}</p>
<p>ULONG STDMETHODCALLTYPE AddRefNativeOutOfProcSrv(){
return application->AddRef();
}</p>
<p>ULONG STDMETHODCALLTYPE ReleaseNativeOutOfProcSrv(){
return application->Release();
}</p>
<p>ULONG STDMETHODCALLTYPE GetTypeInfoCountSrv( UINT * count) {
return application->GetTypeInfoCount(count);
}
ULONG STDMETHODCALLTYPE GetTypeInfoSrv ( UINT n, LCID id, ITypeInfo ** inf) {
return application->GetTypeInfo(n,id,inf);
}
ULONG STDMETHODCALLTYPE GetIDsOfNamesSrv ( REFIID a, LPOLESTR * b, UINT c, LCID d, DISPID * e) {
return application->GetIDsOfNames(a,b,c,d,e);
}
ULONG STDMETHODCALLTYPE InvokeSrv ( DISPID a, REFIID b, LCID c, WORD d, DISPPARAMS * e, VARIANT * i, EXCEPINFO * j, UINT *k) {
return application->Invoke(a,b,c,d,e,i,j,k);
}</p>
<p>static IDispatchInterceptor interceptor =
{QueryInterfaceNativeOutOfProcSrv,AddRefNativeOutOfProcSrv,ReleaseNativeOutOfProcSrv,
GetTypeInfoCountSrv,GetTypeInfoSrv,GetIDsOfNamesSrv,InvokeSrv
};</p>
<p>ULONG __stdcall release(IDispatch *self)
{ </p>
<pre><code>ULONG c = realRelease(self);
Log->logWrite("release %d",c);
if ( c == 1)
{
if (instance != NULL)
{
instance->OnBeginShutdown(NULL);
Log->logWrite("OnBeginShutdown %d",c);
instance->OnEmbeddedDisconnection();
Log->logWrite("OnEmbeddedDisconnection %d",c);
instance = NULL;
}
}
//if (c == 2) {
// c = realRelease(self);
// c = realRelease(self);
//}
return c;
}
ULONG __stdcall addref (IDispatch * self)
{
ULONG c = oldCount;
if (wasAdd == 0)
{
c = realAddRef (self);
oldCount = c;
wasAdd ++;
}
иначе если (wasAdd == 1)
{
Log-> logWrite ("ADDREF FAKE% d", c);
wasAdd ++;
}
иначе если (wasAdd == 2)
{
Log-> logWrite ("ADDREF FAKE% d", c);
wasAdd ++;
}
еще
{
c = realAddRef (self);
}
Log-> logWrite ("ADDREF% d", c);
возврат с;
}
void InterceptRelease (IDispatch obj) {
void iunknown_vtable = (void *) ((unsigned int ) obj);
void * idispatch_vtable = (void *) (((unsigned int) iunknown_vtable) +8);
unsigned int * v1 = (unsigned int *) idispatch_vtable;
realRelease = (releasePTR *) * v1;
DWORD старый;
VirtualProtect (v1,4, PAGE_EXECUTE_READWRITE, и старый);
*v1 = (unsigned int) release;
//while(obj->Release() > 0){};
* *} Тысяча двадцать-один
void InterceptAddRef (IDispatch obj) {
void iunknown_vtable = (void *) ((unsigned int ) obj);
void * idispatch_vtable = (void *) (((unsigned int) iunknown_vtable) +4);
unsigned int * v1 = (unsigned int *) idispatch_vtable;
realAddRef = (addrefPTR *) * v1;
DWORD старый;
VirtualProtect (v1,4, PAGE_EXECUTE_READWRITE, и старые);
* v1 = (без знака int) addref;
}
Применение:
IDispatch * app = Application;
InterceptRelease(app);
InterceptAddRef(app);