接下来我发现了(从将 COM 接口解释为纯 C 结构 + 函数和 Direct X hacks)。工作,但由于某种原因不能解决问题。我应该对工作簿、工作表做同样的事情......
声明:
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 做的:
static IDispatch * application = NULL;
static releasePTR* realRelease = NULL;
static addrefPTR* realAddRef = NULL;
static ULONG wasAdd = 0;
static ULONG oldCount = 0;
HRESULT STDMETHODCALLTYPE QueryInterfaceNativeOutOfProcSrv(REFIID riid, void **ppv){
返回应用程序->QueryInterface(riid,ppv);
}
ULONG STDMETHODCALLTYPE AddRefNativeOutOfProcSrv(){
返回应用程序->AddRef();
}
ULONG STDMETHODCALLTYPE ReleaseNativeOutOfProcSrv(){
返回应用程序->释放();
}
ULONG STDMETHODCALLTYPE GetTypeInfoCountSrv(UINT * count) {
返回应用程序->GetTypeInfoCount(count);
}
ULONG STDMETHODCALLTYPE GetTypeInfoSrv (UINT n, LCID id, ITypeInfo ** inf) {
返回应用程序->GetTypeInfo(n,id,inf);
}
ULONG STDMETHODCALLTYPE GetIDsOfNamesSrv ( REFIID a, LPOLESTR * b, UINT c, LCID d, DISPID * e) {
返回应用程序->GetIDsOfNames(a,b,c,d,e);
}
ULONG STDMETHODCALLTYPE InvokeSrv ( DISPID a, REFIID b, LCID c, WORD d, DISPARAMS * e, VARIANT * i, EXCEPINFO * j, UINT *k) {
返回应用程序->调用(a,b,c,d,e,i,j,k);
}
静态 IDispatchInterceptor 拦截器 =
{QueryInterfaceNativeOutOfProcSrv,AddRefNativeOutOfProcSrv,ReleaseNativeOutOfProcSrv,
GetTypeInfoCountSrv、GetTypeInfoSrv、GetIDsOfNamesSrv、InvokeSrv
};
ULONG __stdcall 释放(IDispatch *self)
{
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);
旧计数 = c;
是加++;
}
否则 if (wasAdd == 1)
{
日志->logWrite("ADDREF FAKE %d",c);
是加++;
}
否则 if (wasAdd == 2)
{
日志->logWrite("ADDREF FAKE %d",c);
是加++;
}
别的
{
c = realAddRef(self);
}
日志->logWrite("ADDREF %d",c);
返回 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,&old);
*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,&old);
*v1 = (unsigned int) addref;
}
申请:
IDispatch * app = Application;
InterceptRelease(app);
InterceptAddRef(app);