I have been trying to do a basic ActiveX component marshalling for across thread access. I do it through a Global Interface Table (GIT) . I have a simple MFC dialog to which I add an arbitrary AciveX control such as IDC_PDF. Inserting activeX control to MFC dialog in C++
After that I add the variable representing this control to the code. This effectively adds a pdf1.h and pdf1.cpp to the project. At initialization of the dialog inside OnInitDialog() I try to marshal the interface to this ActiveX component so that it could be used from another thread without STA apartment violation.
bool CLMC_mfcDlg::CreateMarshalledController()
{
::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
CComPtr<IGlobalInterfaceTable> pGIT;
// get pointer to GIT
CoCreateInstance(CLSID_StdGlobalInterfaceTable,
NULL,
CLSCTX_INPROC_SERVER,
IID_IGlobalInterfaceTable,
(void **)&pGIT);
// get IID and IUnknown interface pointer
REFIID iid = Pd_OCX_fControl.GetClsid();
IUnknown* active_x_pointer = Pd_OCX_fControl.GetControlUnknown();
// register interface inside the GIT
if (active_x_pointer != NULL) {
HRESULT hr = pGIT->RegisterInterfaceInGlobal(active_x_pointer, iid, &dwCookie);
if (SUCCEEDED(hr))
{
// OK, wir haben das interface im GIT registriert
assert(dwCookie != 0);
}
else
dwCookie = 0;
//pGIT->Release();
}
else
dwCookie = 0;
active_x_pointer->Release();
return dwCookie!=0;
}
As a result the value of the dwCookie is set to 256, which though not 0, still feels like an error value. When I try to get the marshalled interface from another thread. The marshalled interface received is 0x0000.
bool CLMC_mfcDlg::FetchMarshalledController()
{
HRESULT res = ::OleInitialize(NULL);
switch (res)
{
case S_OK:
break;
case OLE_E_WRONGCOMPOBJ:
case RPC_E_CHANGED_MODE:
return false;
}
CComPtr<IGlobalInterfaceTable> pThreadGIT;
CoCreateInstance(CLSID_StdGlobalInterfaceTable,
NULL,
CLSCTX_INPROC_SERVER,
IID_IGlobalInterfaceTable,
(void **)&pThreadGIT);
REFIID iid = Pd_OCX_fControl.GetClsid();
pThreadGIT->GetInterfaceFromGlobal(
dwCookie, iid, (void**)&pMarshalledOCX);
pThreadGIT->RevokeInterfaceFromGlobal(dwCookie);
return pMarshalledOCX != nullptr;
}
What am I doing wrong? I am working with a standard ActiveX, using standard marshalling patern. Anybody got this to work?
Aurora was correct. To get a proper IID you need to find the interface in registry using oleview.exe:
you use the finding to define interface IID in your code:
static REFIID const intf_id
= { 0x5CD5C9C3, 0x0CD7, 0x453A,{ 0x8D, 0x27, 0xE3, 0xBB, 0x32, 0xB7, 0xEA, 0xFC } };
you get the interface pointer for it like this:
IUnknown * pUnknown = CBaldorOCXCard.GetControlUnknown();
// get _DMintControllerCtrl interface pointer
void* IMint = NULL;
pUnknown->QueryInterface(intf_id, (void **)&IMint);
The interface pointer and IID can now be used in marshaling.
(The problem how you work with this interface pointer without a wrapper class:) Still looking for answer)