"Pure" dispinterface marshaling - com

Update 2021-04-20: The code presented here is for illustration purposes only. As pointed out by Simon Mourier, for marshaling in-process of such a simple class there is no need for all the TLB shenanigans. In reality, the TLB is provided by a third-party, with the interface in question serving for callbacks.
The object calling the interface resides in another process, however, so I really do have to marshal the interface after implementing it. As demonstrating the whole inter-process flow is tedious, I opted for something simpler - in-process inter-apartment marshaling.
Suppose I have the following type library:
import "oaidl.idl";
import "ocidl.idl";
[
uuid(99CF9EB9-9B6E-4D44-B73C-6BB8FCD45B82),
version(1.0),
]
library IsThisRealMarshal
{
[
uuid(80997EA1-0144-41EC-ABCF-5FAD08D5A498),
nonextensible,
]
dispinterface IMyInterface
{
properties:
methods:
[id(1)]
void Method();
};
};
I would like to marshal IMyInterface to another apartment. Since it's a dispinterface, I would like to use the OLE marshaler for this. And so, I register the type library:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\SOFTWARE\Classes\TypeLib\{99CF9EB9-9B6E-4D44-B73C-6BB8FCD45B82}]
[HKEY_CURRENT_USER\SOFTWARE\Classes\TypeLib\{99CF9EB9-9B6E-4D44-B73C-6BB8FCD45B82}\1.0]
[HKEY_CURRENT_USER\SOFTWARE\Classes\TypeLib\{99CF9EB9-9B6E-4D44-B73C-6BB8FCD45B82}\1.0\0]
[HKEY_CURRENT_USER\SOFTWARE\Classes\TypeLib\{99CF9EB9-9B6E-4D44-B73C-6BB8FCD45B82}\1.0\0\win32]
#="path\\to\\library.tlb"
And the interface (setting the proxy CLSID to that of the OLE marshaler):
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\SOFTWARE\Classes\Interface\{80997EA1-0144-41EC-ABCF-5FAD08D5A498}]
[HKEY_CURRENT_USER\SOFTWARE\Classes\Interface\{80997EA1-0144-41EC-ABCF-5FAD08D5A498}\ProxyStubClsid32]
#="{00020424-0000-0000-C000-000000000046}"
[HKEY_CURRENT_USER\SOFTWARE\Classes\Interface\{80997EA1-0144-41EC-ABCF-5FAD08D5A498}\TypeLib]
#="{99CF9EB9-9B6E-4D44-B73C-6BB8FCD45B82}"
"Version"="1.0"
And I try to marshal (error-checking omitted for brevity):
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
CComPtr<IMyInterface> object {};
object.Attach(new MyObject);
CComPtr<IGlobalInterfaceTable> git {};
git.CoCreateInstance(CLSID_StdGlobalInterfaceTable, nullptr, CLSCTX_INPROC_SERVER);
DWORD cookie = 0;
git->RegisterInterfaceInGlobal(object, __uuidof(IMyInterface), &cookie);
auto thread = std::thread([cookie]
{
CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
CComPtr<IGlobalInterfaceTable> git {};
git.CoCreateInstance(CLSID_StdGlobalInterfaceTable, nullptr, CLSCTX_INPROC_SERVER);
CComPtr<IMyInterface> object {};
git->GetInterfaceFromGlobal(cookie, __uuidof(IMyInterface), (void **)&object);
});
thread.join();
Where the MyObject class implements the bare minimum COM functionality:
class MyObject : public IMyInterface
{
private:
std::atomic<ULONG> _refcount = 1;
public:
MyObject() = default;
MyObject(MyObject const &) = delete;
MyObject & operator=(MyObject const &) = delete;
HRESULT QueryInterface(const IID& riid, void** ppvObject) override
{
if (nullptr == ppvObject)
{
return E_POINTER;
}
if (riid == __uuidof(IUnknown))
{
*ppvObject = static_cast<IUnknown *>(this);
}
else if (riid == __uuidof(IDispatch))
{
*ppvObject = static_cast<IDispatch *>(this);
}
else if (riid == __uuidof(IMyInterface))
{
*ppvObject = static_cast<IMyInterface *>(this);
}
else
{
*ppvObject = nullptr;
return E_NOINTERFACE;
}
static_cast<IUnknown *>(*ppvObject)->AddRef();
return S_OK;
}
ULONG AddRef() override
{
return ++_refcount;
}
ULONG Release() override
{
auto const new_refcount = --_refcount;
if (0 == new_refcount)
{
delete this;
}
return new_refcount;
}
HRESULT GetTypeInfoCount(UINT* pctinfo) override
{
return E_NOTIMPL;
}
HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) override
{
return E_NOTIMPL;
}
HRESULT GetIDsOfNames(const IID& riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) override
{
return E_NOTIMPL;
}
HRESULT Invoke(DISPID dispIdMember, const IID& riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) override
{
return E_NOTIMPL;
}
};
Unfortunately, the call to GetInterfaceFromGlobal fails with E_FAIL.
Debugging reveals that none of the IDispatch methods are called, only the IUnknown ones. Additionally, it appears that the E_FAIL originates from combase!CheckTypeInfo. First, this function uses ITypeInfo::GetTypeAttr to retrieve information about IMyInterface:
It then proceeds to check whether the flags TYPEFLAG_FDUAL (0x40) or TYPEFLAG_FOLEAUTOMATION (0x100) are present in the wTypeFlags field of the TYPEATTR structure:
Since neither of these flags are present (the field has the value 0x1080, and indeed the IDL doesn't mark the interface as either [oleautomation] or [dual]), the function fails with E_FAIL.
What am I doing wrong? And if the OLE marshaler indeed cannot marshal this interface, is there anything I can do apart from implementing IMarshal myself, assuming I cannot modify the IDL?

With the help of Simon Mourier's code, I managed to find the problem. The problem was that I used the PSOAInterface proxy ({00020424-0000-0000-C000-000000000046}). Since IMyInterface is not an OLE Automation interface (i.e. not marked with [oleautomation]), this rightly failed.
The solution is to use the PSDispatch proxy ({00020420-0000-0000-C000-000000000046}), which is capable of marshaling pure IDispatch interfaces.

Related

How to call a native method with a std::vector as argument and retrieve the native object in wrapped class

I have a native C++ method, from external unchangable DLL, that expects a std::vector as a argument with 2 native objects. (for example sake, it's an image library returning width/height of a 2 images)
I would like the native objects in the std::vector to be referenced in my own wrapped MyManagedImageObj.
Somehow the std::vector seems to copy values and has no way to add pointers (correct?); so after calling the NativeMethod; I need to copy the properties (width/height) back again to MyManagedImageObj.
I thought about first declaring the std::vec and getting the pointer of the results and put that in MyManagedImageObj as a pointer. But if I understand it correctly std::vector will clean that native memory up once out of scope. (my c++ experience is 1 week; c# long time)
Is there a better way to do this without reassigning the properties one by one?
Ej
The code looks like this:
//create managed object that wraps also native pointer.
MyManagedImageObj^ obj1 = gcnew MyManagedImageObj();
MyManagedImageObj^ obj2 = gcnew MyManagedImageObj();
//keep list of result
List<MyManagedImageObj^>^ resultList;
resultList->Add(obj1);
resultList->Add(obj2);
//call to native method. Dereference pointers of native wrapped objects... not working?
std::vector<DLLNativeImageObj> nativeImageVec { *obj1->GetInstance(), *obj2->GetInstance() };
bool result = otherNativePtr->NativeMethod(nativeImageVec);
//we still need copy it over results now to 'our' managed objects.
int i = 0;
for (DLLNativeImageObj c : nativeImageVec)
{
resultList[i]->ImageHeight = c.imageHeight;
resultList[i]->ImageWidth = c.imageWidth;
++i;
}
The MyManagedImageObj class looks like this:
//MyManagedImageObj.h
public ref class MyManagedImageObj
{
protected:
DLLNativeImageObj* m_Instance;
public:
MyManagedImageObj(DLLNativeImageObj* instance)
: m_Instance(instance)
{
};
~MyManagedImageObj() //destructor will be called whenever we do 'delete'
{
if (m_Instance != nullptr)
{
delete m_Instance;
}
}
!MyManagedImageObj() //finalizer, called by the garbage collector when it's destroys the wrapper object. So safety check to dispose unmanaged item.
{
if (m_Instance != nullptr)
{
delete m_Instance;
}
}
DLLNativeImageObj* GetInstance() //return the pointer to the unmanaged object
{
return m_Instance;
}
property uint32_t ImageWidth
{
public:
uint32_t get()
{
return m_Instance->imageWidth;
}
public:
void set(uint32_t value)
{
m_Instance->imageWidth = value;
}
}
property uint32_t ImageHeight
{
public:
uint32_t get()
{
return m_Instance->imageHeight;
}
public:
void set(uint32_t value)
{
m_Instance->imageHeight = value;
}
}
};
//MyManagedImageObj.cpp
MyManagedImageObj::MyManagedImageObj(new DLLNativeImageObj())
{
// new keyword important: it returns a pointer to the location and does not get deleted when out of scope. Manual delete is required.
}

IConnectionPoint event in local server COM

I created a local server (EXE) COM project with support for ConnectionPoint events.
idl pseudo:
interface IAtlClass : IDispatch{
[id(1)] HRESULT f1();
};
library ComExeLib
{
dispinterface _IAtlClassEvents
{
methods:
[id(1)] HRESULT f2();
};
[
uuid(...
]
coclass AtlClass
{
[default] interface IAtlClass;
[default, source] dispinterface _IAtlClassEvents;
};
};
Server is built in 32 bit configuration. Client code, built in 64 bit:
HRESULT hr = CoInitialize(NULL);
IAtlClass* atlClass;
hr = CoCreateInstance(CLSID_AtlClass, NULL,
CLSCTX_LOCAL_SERVER,
IID_IAtlClass,
reinterpret_cast<void**>(&atlClass));
hr = atlClass->f1();
IConnectionPointContainer* pICPC = NULL;
hr = atlClass->QueryInterface(IID_IConnectionPointContainer, (VOID **)&pICPC);
IConnectionPoint* pICP = NULL;
hr = pICPC->FindConnectionPoint(DIID__IAtlClassEvents, &pICP);
hr = pICP->Advise((_IAtlClassEvents*)&sink, &cookie);
Sink class:
class Sink : public _IAtlClassEvents
{
public:
HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
{
if ((DIID__IAtlClassEvents == riid))
{
*ppvObject = static_cast<_IAtlClassEvents*>(this);
AddRef();
return(S_OK);
}
*ppvObject = NULL;
return(E_NOINTERFACE);
}
ULONG STDMETHODCALLTYPE AddRef(void)
{
return(InterlockedIncrement(&m_iRef));
}
ULONG STDMETHODCALLTYPE Release(void)
{
if (0 == InterlockedDecrement(&m_iRef))
{
delete this;
return(0);
}
return(m_iRef);
}
HRESULT STDMETHODCALLTYPE GetTypeInfoCount()
HRESULT STDMETHODCALLTYPE GetTypeInfo()
HRESULT STDMETHODCALLTYPE GetIDsOfNames()
HRESULT STDMETHODCALLTYPE Invoke()
};
Registered the server with ComExe.exe /RegServer and the proxy with regsvr32 ComExePS.dll, under folder C:\windows\SysWOW\ and under c:\Windows\System32.
Not sure if necessary but tried to compile the proxy stub under 64 bit as well but it will not build since auto-generated ComExe_p.c contains an #if !defined(AMD64).. so the project can only be built in 32 bit (seems related to this post only I use VS2013).
All client code commands except the last (Advise) succeed (They succeed even without registering the ComExePS.dll) . Advise invokes the sink QueryInterface method (and none but it), five time with following iid's:
{00000003-0000-0000-C000-000000000046}
{ECC8691B-C1DB-4DC0-855E-65F6C551AF49}
{00000003-0000-0000-C000-000000000046}
{0000001B-0000-0000-C000-000000000046}
{IID_IUnknown}
None of which are related to IAtlClass (some standard MS iid's - this guy was getting something similar).
Eventually Advise returns E_UNEXPECTED Catastrophic failure and the question is what am I doing wrong?

Immediate Access Violation when debugging Windows.Devices.Sensors project in Windows 7

I have a large solution with 50+ unmanaged projects in it. I have recently added a project with managed code in it to the solution. The managed code accesses Windows.Devices.Sensors in a .NET dll. This dll is eventually wrapped by unmanaged code and called from another unmanaged project.
My problem is that I get the following access violation before main() even executes.
Unhandled exception at 0x744b8ea0 in myApplication.exe: 0xC0000005: Access violation.
Managed code:
#using <Windows.winmd>
using namespace Windows::Devices::Sensors;
#include <math.h>
namespace TabletSensors
{
namespace NET
{
public ref class DotNetDllClass
{
public:
DotNetDllClass()
{
Initialization();
}
~DotNetDllClass()
{
}
float* GetQuaternion()
{
OrientationSensorReading^ reading = _orientation->GetCurrentReading();
if( reading != nullptr )
{
float* quat = new float[4];
quat[0] = reading->Quaternion->X;
quat[1] = reading->Quaternion->Y;
quat[2] = reading->Quaternion->Z;
quat[3] = reading->Quaternion->W;
return quat;
}
else
{
return NULL;
}
}
private:
void Initialization()
{
_orientation = OrientationSensor::GetDefault();
if( _orientation != nullptr )
{
_orientation->ReportInterval = 16;
}
else
{
// not good ... throw exception or something
}
}
OrientationSensor^ _orientation;
};
}
}
Wrapper header file:
namespace TabletSensors
{
namespace NETWrapper
{
class DLLEXPORT_SENSORS WrapperClass
{
public:
__stdcall WrapperClass();
__stdcall ~WrapperClass();
float* __stdcall GetQuaternion();
};
}
}
Wrapper cpp file:
#define MIXSENSORS_BUILD
#include <gcroot.h>
#include "DotNetWrapper.h"
#include "DotNetDll.h"
using namespace TabletSensors::NETWrapper;
using namespace TabletSensors::NET;
static gcroot<TabletSensors::NET::DotNetDllClass^> Sensors = nullptr;
static System::UInt16 refCount = 0;
#pragma managed
inline TabletSensors::NET::DotNetDllClass^ GetSensors(void)
{
return (TabletSensors::NET::DotNetDllClass^)Sensors;
}
void Init()
{
++refCount;
if(GetSensors() == nullptr)
{
Sensors = gcnew TabletSensors::NET::DotNetDllClass();
}
}
void CleanUp()
{
if( refCount > 0 )
{
--refCount;
}
}
float* GetQuaternion_()
{
return Sensors->GetQuaternion();
}
#pragma unmanaged
TabletSensors::NETWrapper::WrapperClass::WrapperClass()
{
Init();
}
TabletSensors::NETWrapper::WrapperClass::~WrapperClass()
{
CleanUp();
}
float* TabletSensors::NETWrapper::WrapperClass::GetQuaternion()
{
float* x = new float[4];
return GetQuaternion_();
}
#pragma managed
Unmanaged project referencing my wrapper class:
#include "DotNetWrapper.h"
.
.
.
void UnmanagedProject::Update()
{
// if this line is present, I get an access violation without hitting any breakpoints.
TabletSensors::NETWrapper::WrapperClass _tabletSensors;
.
.
.
}
Since the managed code is trying to access Tablet Sensors I understand why it doesn't work on my Windows 7 desktop. What I don't understand it why it won't even allow me to debug my code at all. No breakpoints are hit before the Access Violation occurs.
What I would really like to figure out is how to use exception handling or #ifdefs to keep this crash from happening. But I have had very little luck.
Any ideas?
The fix is to Delay Load the managed DLL. The allows the application to run until that DLL is explicitly called. Thanks to Ben Voight for his answer here: https://stackoverflow.com/a/28467701/1454861

Pass an argument to task in C++/CLI?

I have this code for the C# in Visual Studio 2012.
public Task SwitchLaserAsync(bool on)
{
return Task.Run(new Action(() => SwitchLaser(on)));
}
This will execute SwitchLaser method (public nonstatic member of a class MyClass) as a task with argument bool on.
I would like to do something similar in managed C++/CLI. But I am not able to find out any way how to run a task, which will execute a member method taking one parameter.
Current solution is like this:
Task^ MyClass::SwitchLaserAsync( bool on )
{
laserOn = on; //member bool
return Task::Run(gcnew Action(this, &MyClass::SwitchLaserHelper));
}
Implementation of SwitchLaserHelper function:
void MyClass::SwitchLaserHelper()
{
SwitchLaser(laserOn);
}
There must be some solution like in C# and not to create helper functions and members (this is not threadsafe).
There isn't yet any way to do this.
In C# you have a closure. When your C++/CLI compiler was written, the standardized syntax for closures in C++ was still being discussed. Thankfully, Microsoft chose to wait and use the standard lambda syntax instead of introducing yet another unique syntax. Unfortunately, it means the feature isn't yet available. When it is, it will look something like:
gcnew Action([this, on](){ SwitchLaser(on) });
The current threadsafe solution is to do what the C# compiler does -- put the helper function and data members not into the current class, but into a nested subtype. Of course you'll need to save the this pointer in addition to your local variable.
ref class MyClass::SwitchLaserHelper
{
bool laserOn;
MyClass^ owner;
public:
SwitchLaserHelper(MyClass^ realThis, bool on) : owner(realThis), laserOn(on) {}
void DoIt() { owner->SwitchLaser(laserOn); }
};
Task^ MyClass::SwitchLaserAsync( bool on )
{
return Task::Run(gcnew Action(gcnew SwitchLaserHelper(this, on), &MyClass::SwitchLaserHelper::DoIt));
}
The C++ lamdba syntax will simply create that helper class for you (currently it works for native lambdas, but not yet for managed ones).
Here's generic code I wrote this afternoon which might help (although it's not an exact match for this question). Maybe this will help the next person who stumbles onto this question.
generic<typename T, typename TResult>
ref class Bind1
{
initonly T arg;
Func<T, TResult>^ const f;
TResult _() { return f(arg); }
public:
initonly Func<TResult>^ binder;
Bind1(Func<T, TResult>^ f, T arg) : f(f), arg(arg) {
binder = gcnew Func<TResult>(this, &Bind1::_);
}
};
ref class Binder abstract sealed // static
{
public:
generic<typename T, typename TResult>
static Func<TResult>^ Create(Func<T, TResult>^ f, T arg) {
return (gcnew Bind1<T, TResult>(f, arg))->binder;
}
};
Usage is
const auto f = gcnew Func<T, TResult>(this, &MyClass::MyMethod);
return Task::Run(Binder::Create(f, arg));
Here's the working answer.. Have tested it.. Passing an argument (int) to the action sampleFunction.
#include "stdafx.h"
#include "CLRSamples.h"
using namespace System;
using namespace System::Threading;
using namespace System::Threading::Tasks;
using namespace System::Collections;
using namespace System::Collections::Generic;
void CLRSamples::sampleFunction(Object^ number)
{
Console::WriteLine(number->ToString());
Thread::Sleep((int)number * 100);
}
void CLRSamples::testTasks()
{
List<Task^>^ tasks = gcnew List<Task^>();
for (int i = 0; i < 10; i++)
{
tasks->Add(Task::Factory->StartNew((Action<Object^>^)(gcnew Action<Object^>(this, &CLRSamples::sampleFunction)), i));
}
Task::WaitAll(tasks->ToArray());
Console::WriteLine("Completed...");
}
int main(array<System::String ^> ^args)
{
CLRSamples^ samples = gcnew CLRSamples();
samples->testTasks();
Console::Read();
return 0;
}
I had a similar problem when I wanted to provide a parameter to a task executing a method which does not return a value (retuns void). Because of that Func<T, TResult> was not an option I could use. For more information, please check the page Using void return types with new Func.
So I ended up with a solution where I created a helper class
template <typename T>
ref class ActionArguments
{
public:
ActionArguments(Action<T>^ func, T args) : m_func(func), m_args(args) {};
void operator()() { m_func(m_args); };
private:
Action<T>^ m_func;
T m_args;
};
which is using Action<T> delegate to encapsulate a method that has a single parameter and does not return a value.
I would then use this helper class in a following way
ref class DisplayActivationController
{
public:
DisplayActivationController();
void StatusChanged(EventArgs^ args) { };
}
Action<EventArgs^>^ action =
gcnew Action<EventArgs^>(this, &DisplayActivationController::StatusChanged);
ActionArguments<EventArgs^>^ action_args =
gcnew ActionArguments<EventArgs^>(action, args);
Threading::Tasks::Task::Factory->
StartNew(gcnew Action(action_args, &ActionArguments<EventArgs^>::operator()));
Approach using the helper class is probably not the most elegant solution, but is the best one I could find to be used in C++/CLI which does not support lambda expressions.
If you are using c++/ CLR, then make a C# dll and add reference to it
namespace TaskClrHelper
{
public static class TaskHelper
{
public static Task<TResult> StartNew<T1, TResult>(
Func<T1, TResult> func,
T1 arg)
=> Task.Factory.StartNew(() => func(arg));
public static Task<TResult> StartNew<T1, T2, TResult>(
Func<T1, T2, TResult> func,
T1 arg1, T2 arg2)
=> Task.Factory.StartNew(() => func(arg1, arg2));
}
}
bool Device::Stop(int timeout)
{
_ResetEvent_Running->Set();
return _ResetEvent_Disconnect->WaitOne(timeout);
}
Task<bool>^ Device::StopAsync(int timeout)
{
auto func = gcnew Func<int, bool>(this, &Device::Stop);
return TaskClrHelper::TaskHelper::StartNew<int,bool>(func,timeout);
}

COM - How to get the properties of an interface within the type library the interface is defined

How to get the properties of an interface within the type library the interface is defined, Keeps returning HRESULT but would like it to return the actual value of the property.
EDIT:
IDL:
interface IMyClassInterface : IDispatch
{
[propget, id(1), helpstring("Gets user Type")] HRESULT getUserDefineTypeVal([out,retval] UserDefineEnum *ptrVal);
[propput, id(1), helpstring("Sets user Type ")]HRESULT setUserDefineTypeVal([in] UserDefineEnum newVal);
}
Property in Header File:
STDMETHOD(getUserDefineTypeVal)(UserDefineEnum *ptrVal);
STDMETHOD(setUserDefineTypeVal)(UserDefineEnum newVal);
Property in MYClass.cpp:
STDMETHODIMP CMYClass::getUserDefineTypeVal(UserDefineEnum *ptrVal) {
*ptrVal = UserDefineEnum(private_var_UserDefineTypeVal);
return S_OK;
}
AnotherClass within the Type Library:
IMyClassInterface* private_var_MyClass
STDMETHODIMP CAnotherClass::someMethod(){
UserDefineEnum* p;
if(private_var_MyClass->getUserDefineTypeVal(p)){
//do somestuff
}
}
The problem is the if condition doesn’t return true. However the below partially works.
HRESULT hr = private_var_MyClass->getUserDefineTypeVal(p);
if(hr == S_OK){ do somestuff }
The problem with this is if I attempt a case statement the only value in hr is 0. I need to check the value being set on the clientside.
The value of S_OK is 0, that's why your if() statement doesn't execute. You should use the SUCCEEDED macro:
UserDefinedEnum value;
HRESULT hr = private_var_MyClass->getUserDefineTypeVal(&value);
if (SUCCEEDED(hr)) {
switch (value) {
// etc...
}
}
else {
// do something with the error...
}
COM usually uses out parameters to return values. In C/C++ you have to pass a pointer to a variable which will contain the result upon return.
The HRESULT return parameter is only used to report the success (or failure) of the method call.
EDIT For your code, you need to reserve the memory for the result by the caller:
UserDefineEnum p; // No * here ...
if (private_var_MyClass->getUserDefineTypeValue(&p) == S_OK) { // note '&' operator!
switch (p) {
case ENUM_1: // ...
case ENUM_2:
// ...
}
}