#include "XCDotNet.h" /*#include "mscorlib.h"*/ #include const IID IID__Object = {0x65074F7F,0x63C0,0x304E,{0xAF,0x0A,0xD5,0x17,0x41,0xCB,0x4A,0x8D}}; enum BindingsFlags { InvokeMethod = 256, CreateInstance = 512, GetField = 1024, SetField = 2048, GetProperty = 4096, SetProperty = 8192, }; void __declspec(dllexport) xcdotnet_fire_event(IDispatch *sender, IDispatch *target, IDispatch *event_args) { HRESULT hres; DISPPARAMS dispParams = { NULL, NULL, 0, 0 }; VARIANT retval, args[2]; XCDotNet *dotnet_sender = NULL, *dotnet_args = NULL; args[1].vt = VT_DISPATCH; dotnet_sender = make_XCDotNet(sender); IDispatch_QueryInterface(&dotnet_sender->iface, &IID_IDispatch, (void**)&args[1].pdispVal); args[0].vt = VT_DISPATCH; dotnet_args = make_XCDotNet(event_args); IDispatch_QueryInterface(&dotnet_args->iface, &IID_IDispatch, (void**)&args[0].pdispVal); dispParams.rgvarg = args; dispParams.cArgs = 2; hres = IDispatch_Invoke(target, 0, &IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispParams, &retval, NULL, NULL); IDispatch_Release(&dotnet_sender->iface); IDispatch_Release(&dotnet_args->iface); printf("Event result=%p\n", hres); } STDMETHODIMP xcdotnet_queryinterface(IDispatch *This, REFIID iid, void **ppvObject) { if (InlineIsEqualGUID(iid, &IID_IUnknown) || InlineIsEqualGUID(iid, &IID_IDispatch) || InlineIsEqualGUID(iid, &IID_IDispatchEx)) *ppvObject = This; else return E_NOINTERFACE; IDispatch_AddRef(This); return S_OK; } STDMETHODIMP_(ULONG) xcdotnet_addref(IDispatch *This) { ((XCDotNet*)This)->m_refCount++; return S_OK; } STDMETHODIMP_(ULONG) xcdotnet_release(IDispatch *This) { XCDotNet *dotnet = (XCDotNet*)This; if (--(dotnet->m_refCount) == 0) { if (dotnet->m_objectproxy) IDispatch_Release(dotnet->m_objectproxy); LocalFree(This); } return S_OK; } STDMETHODIMP xcdotnet_gettypeinfocount(IDispatch *This, UINT *pctinfo) { return E_NOTIMPL; } STDMETHODIMP xcdotnet_gettypeinfo(IDispatch *This, UINT itinfo, LCID lcid, ITypeInfo **pptinfo) { return DISP_E_BADINDEX; } STDMETHODIMP xcdotnet_getidsofnames(IDispatch *This, REFIID iid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) { if (cNames != 1) return DISP_E_UNKNOWNNAME; else { XCDotNet *dotnet = (XCDotNet*)This; HRESULT hres; LPOLESTR memberName = L"GetMemberID"; DISPPARAMS dispParams = { NULL, NULL, 0, 0 }; VARIANT retval, arg; BSTR argName = SysAllocString(rgszNames[0]); DISPID dispID; hres = IDispatch_GetIDsOfNames(dotnet->m_objectproxy, &IID_NULL, &memberName, 1, lcid, &dispID); arg.vt = VT_BSTR; arg.bstrVal = argName; dispParams.rgvarg = &arg; dispParams.cArgs = 1; hres = IDispatch_Invoke(dotnet->m_objectproxy, dispID, &IID_NULL, lcid, DISPATCH_METHOD, &dispParams, &retval, NULL, NULL); if (retval.vt == VT_I4 && retval.lVal >= 0) { *rgDispId = retval.lVal; return S_OK; } else return DISP_E_UNKNOWNNAME; } } STDMETHODIMP xcdotnet_invoke(IDispatch *This, DISPID dispIdMember, REFIID iid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { HRESULT hres; DISPID dispID; DISPPARAMS dispParams = { NULL, NULL, 0, 0 }; LPOLESTR memberName = L"InvokeProxy"; VARIANT args[3]; XCDotNet *dotnet = (XCDotNet*)This; SAFEARRAY *argArray; unsigned int i; hres = IDispatch_GetIDsOfNames(dotnet->m_objectproxy, &IID_NULL, &memberName, 1, lcid, &dispID); args[2].vt = VT_I4; args[2].lVal = dispIdMember; args[1].vt = VT_I4; args[1].lVal = 0; if (wFlags & DISPATCH_METHOD) args[1].lVal |= InvokeMethod; if (wFlags & DISPATCH_PROPERTYGET) args[1].lVal |= (GetProperty | GetField); if (wFlags & (DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF)) args[1].lVal |= (SetProperty | SetField); if (wFlags & DISPATCH_CONSTRUCT) args[1].lVal |= CreateInstance; args[0].vt = VT_ARRAY; argArray = SafeArrayCreateVector(VT_VARIANT, 0, pDispParams->cArgs); for (i=0; icArgs; i++) { if (pDispParams->rgvarg[i].vt == VT_DISPATCH && pDispParams->rgvarg[i].pdispVal->lpVtbl->Invoke == xcdotnet_invoke) { pDispParams->rgvarg[i].pdispVal = ((XCDotNet*)pDispParams->rgvarg[i].pdispVal)->m_objectproxy; } SafeArrayPutElement(argArray, &i, &pDispParams->rgvarg[i]); } args[0].parray = argArray; dispParams.rgvarg = args; dispParams.cArgs = 3; hres = IDispatch_Invoke(dotnet->m_objectproxy, dispID, &IID_NULL, lcid, DISPATCH_METHOD, &dispParams, pVarResult, pExcepInfo, NULL); if (pVarResult && (pVarResult->vt == VT_UNKNOWN || pVarResult->vt == VT_DISPATCH)) { IDispatch *disp = NULL; XCDotNet *dotnet; if (pVarResult->vt == VT_UNKNOWN) { IUnknown_QueryInterface(pVarResult->punkVal, &IID__Object, &disp); IUnknown_Release(pVarResult->punkVal); } else disp = pVarResult->pdispVal; dotnet = make_XCDotNet(disp); pVarResult->vt = VT_DISPATCH; IDispatch_QueryInterface(&dotnet->iface, &IID_IDispatch, (void**)&pVarResult->pdispVal); } return hres; } STDMETHODIMP xcdotnet_getdispid(IDispatchEx *This, BSTR name, DWORD flags, DISPID *dispID) { return IDispatchEx_GetIDsOfNames(This, &IID_NULL, &name, 1, LOCALE_USER_DEFAULT, dispID); } STDMETHODIMP xcdotnet_invokeex(IDispatchEx *This, DISPID id, LCID lcid, WORD flags, DISPPARAMS *dispParams, VARIANT *retval, EXCEPINFO *einfo, IServiceProvider *spCaller) { printf("InvokeEx: %p\n", id); return IDispatchEx_Invoke(This, id, &IID_NULL, lcid, flags, dispParams, retval, einfo, NULL); } STDMETHODIMP xcdotnet_deletememberbyname(IDispatchEx *This, BSTR name, DWORD flags) { return E_NOTIMPL; } STDMETHODIMP xcdotnet_deletememberbydispid(IDispatchEx *This, DISPID id) { return E_NOTIMPL; } STDMETHODIMP xcdotnet_getmemberproperties(IDispatchEx *This, DISPID id, DWORD flags, DWORD *pFlags) { return E_NOTIMPL; } STDMETHODIMP xcdotnet_getmembername(IDispatchEx *This, DISPID id, BSTR *pName) { return E_NOTIMPL; } STDMETHODIMP xcdotnet_getnextdispid(IDispatchEx *This, DWORD flags, DISPID id, DISPID *pid) { return E_NOTIMPL; } STDMETHODIMP xcdotnet_getnamespaceparent(IDispatchEx *This, IUnknown **punk) { return E_NOTIMPL; } static IDispatchExVtbl vtbl = { xcdotnet_queryinterface, xcdotnet_addref, xcdotnet_release, xcdotnet_gettypeinfocount, xcdotnet_gettypeinfo, xcdotnet_getidsofnames, xcdotnet_invoke, xcdotnet_getdispid, xcdotnet_invokeex, xcdotnet_deletememberbyname, xcdotnet_deletememberbydispid, xcdotnet_getmemberproperties, xcdotnet_getmembername, xcdotnet_getnextdispid, xcdotnet_getnamespaceparent }; XCDotNet* make_XCDotNet(IDispatch *punk) { XCDotNet *dotnet = (XCDotNet*)LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, sizeof(XCDotNet)); dotnet->iface.lpVtbl = (IDispatchVtbl*)&vtbl; dotnet->m_objectproxy = punk; return dotnet; }