Why do CoMarshalInterface and CoUnmarshalInterface need REFIID? - c++

I am a noob regarding COM. In the project that I am currently working we use CoMarshalInterface and CoUnmarshalInterface with REFIID of IDispatch for all the COM object/proxy instances because they are all derived from it.
I wanted to template the code and use it with the most derived COM interfaces and that sparked a discussion in the team as it might introduce unintended/unforeseen changes. From testing, I did not see any differences, but it's still a bit curious that these functions need a REFIID parameter.
So my questions are as follows:
Why do CoMarshalInterface and CoUnmarshalInterface need the REFIID parameter? In the docs [1] MS says they query the object for IMarshal and if not found they fallback to the default COM implementation
Is there any difference between calling these functions with IDispatch vs most derived interfaces (which we know are derived from IDispatch)? The scenario put forward was maybe some interfaces do implement IMarshal, but the implementations might have problems. In that case, wouldn't the object reply to the QueryInterface with IMarshal regardless of the functions being called with IDispatch or most derived?
[1] https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-comarshalinterface#remarks

Related

Removing smart pointers [duplicate]

This question already has an answer here:
What does ComPtr.As() do?
(1 answer)
Closed 2 years ago.
I'm testing some code examples for a CLR project. What would be this code equivalent without using smart pointers?
Microsoft::WRL::ComPtr<ID3D11Device1> m_d3dDevice;
Microsoft::WRL::ComPtr<IDXGIDevice1> dxgiDevice;
...
m_d3dDevice.As(&dxgiDevice);
I tried something like this, but I'm not sure if it's ok.
ID3D11Device1* m_d3dDevice;
IDXGIDevice1* dxgiDevice;
...
dxgiDevice = reinterpret_cast<IDXGIDevice1*>(m_d3dDevice);
These are COM object pointers.
I am not sure why you would not want to use a COM smart pointer template class. They eliminate most reference counting issues that can drive you crazy. And they have almost zero overhead.
As such, you can use the ComPtr class or the legacy CComPtr from ATL as your smart ptr template type to automatically handle Addref, Release, and QueryInterface calls for yourself. You can also roll your own smart pointer classes, but ComPtr/CComPtr are very efficiently written.
The rules of COM basically often break when you try to cast between interfaces without using QueryInterface. The actual concrete implementation is probably a C++ class with multiple inheritance from many interfaces. As such, casting between interfaces is probably a shift in the pointer value. But the compiler can't infer that from base class interfaces only. Also, many COM classes cheat this by having QueryInterface return an entirely different object.
So, instead of this:
dxgiDevice = reinterpret_cast<IDXGIDevice1*>(m_d3dDevice);
This is probably all you need:
HRESULT hr = m_d3dDevice->QueryInterface(&dxgiDevice);
Some legacy SDKs don't have the template overload for IUnknown::QueryInterface that eliminates the need to deal with IID guids. So the full expanded function is really this:
HRESULT hr = m_d3dDevice->QueryInterface(__uuidof(IDXGIDevice1), (void**)&dxgiDevice);
Or the most "old school" way (assuming you know how to link in the definition for the IID variable). dxguids.lib might still be a thing, otherwise, the header file hacks for DEFINE_GUID.
HRESULT hr = m_d3dDevice->QueryInterface(IID_IDXGIDevice1, (void**)&dxgiDevice);

How to send list through COM

Can I send a list of objects through COM?
I have my class and there is also a list of this class. And I need to send this through a COM function. Can I do that? If yes, then how? Do I need serialization marshaling?
COM does not pin down any particular collection type, it certainly doesn't have anything standard that models a list. By convention, you can model any collection with an interface. So say you have a collection of Foo objects that each implement IFoo. Then declare an IEnumFoo interface similar to:
interface IEnumFoo : IUnknown
{
HRESULT Next( [in] ULONG celt,
[out, size_is(celt), length_is(*pceltFetched)] IFoo **rgelt,
[in,out,unique] ULONG *pceltFetched );
HRESULT Skip( [in] ULONG celt);
HRESULT Reset();
HRESULT Clone( [out] IEnumFoo **ppenum );
}
And then simply return an interface pointer to an implementation of this interface to allow the client code to enumerate the list. Check the MSDN docs for IEnumVARIANT, a very common enumeration interface type for variants. Which also explains what the methods do.
If one side of the interface will be written in a language with a "simpler" type system, such as VB6 or script, then the SAFEARRAY is the way to go. COM's universal marshaller can take care of it.
If you have C++ on both sides of the interface, and you're happy to define the interface in IDL, and generate custom marshalling code, then IDL includes a "size_is" attribute that can be used. See here for details.
To any reasonable degree, there's no way to do so with std::list. I'm sure there is some maniac who could manage it but from my experience, it's not worth it. If doesn't have to be an std::list and just some linked list, then you'll have to either define a new COM interface and provide it's implementation (which can just be a wrapper around std::list) or find some thirdparty resource that has an adequate implementation for your purposes. If you don't have much experience with implementing COM interfaces, then you'll need to do some good amount of reading.
If it can be an array, then you can make your life a lot simpler by using a SAFEARRAY. And SAFEARRAYs can be easier to use with ATL's CComSafeArray, which is pretty much a wrapper. It tries to help/save you from issues, such as reference counting, when dealing with COM objects. You can then just pass the array between your COM objects. Just going to remind you that you still need to pay attention to who is responsible for de-allocating the memory.

Using IUnknown derived C++ COM object in VB6

I have developed a C++ DLL-based COM object that implements some IUnknown derived interface. How can I use it in VB6? Does VB6 support IUnknown based interfaces, or I need to derive from IDispatch?
UPDATE
I have not used ATL. The implementation is based on A very simple COM server without ATL or MFC article. Seems like I need to generate a .tlb file for my object?!
You do not need to use IDispatch; that's only required for late binding.
To use your object you must add a reference to the object's type library to your VB6 project.
If the interface is only derived from IUnknown and not IDispatch , you can use early binding in VB6.

How does implementing multiple COM interfaces work in C++?

I am trying to understand this example code regarding Browser Helper Objects.
Inside, the author implements a single class which exposes multiple interfaces (IObjectWithSite, IDispatch).
His QueryInterface function performs the following:
if(riid == IID_IUnknown) *ppv = static_cast<BHO*>(this);
else if(riid == IID_IObjectWithSite) *ppv = static_cast<IObjectWithSite*>(this);
else if (riid == IID_IDispatch) *ppv = static_cast<IDispatch*>(this);
I have learned that from a C perspective, interface pointers are just pointers to VTables. So I take it to mean that C++ is capable of returning the VTable of any implemented interface using static_cast.
Does this mean that a class constructed in this way has a bunch of VTables in memory (IObjectWithSite, IDispatch, etc)? What does C++ do with the name collisions on the different interfaces (they each have a QueryInterface, AddRef and Release function), can I implement different methods for each of these?
Yes, there are multiple v-tables, one for each inherited interface. The static_cast<> returns it. The compiler makes sure that common methods in the inherited interfaces are shared, it fills each v-table slot with the a pointer to the same function. So you only need one implementation of AddRef, Release, QueryInterface. Just what you want. None of this is an accident.
This is only ever a problem when a coclass implements multiple interfaces with the same method that you don't want to give the same implementation. The IConnectionPoint::Advise() method is a notorious example. Or was it DAdvise()? Unfortunately, I don't remember what it clashed with and how it was solved, it was covered by ATL Internals. Very good book btw.
In multiple inheritance, multiple VTables are arranged in sequence like following format if given this pointer (which point to first byte, 01)
[01][02][03][04] [05][06][07][08] [09][10][11][12]
[Ptr of VTableA][Ptr of VTableB][Ptr of VTableC]
In C++, only 1 implementation will be generated per function prototype in multiple interface scenario.
However for normal inheritance scenario, superclass might have pre-defined implementation and children who overrides the function will have their VTables pointing to different content than the parent.

Custom COM Implementation?

I'm looking to implement a custom implementation of COM in C++ on a UNIX type platform to allow me to dynamically load and link object oriented code. I'm thinking this would be based on a similar set of functionality that POSIX provides to load and call dll's ie dlopen, dlsym and dlclose.
I understand that the general idea of COM is that you link to a few functions ie QueryInterface, AddRef and Release in a common dll (Kernel32.dll) which then allows you to access interfaces which are just a table of function pointers encapsulated with a pointer to the object for which the function pointers should be called with. These functions are exposed through IUnknown which you must inherit off of.
So how does this all work? Is there a better way to dynamically link and load to object oriented code? How does inheritance from a dll work - does every call to the base class have to be to an exposed member function i.e private/protected/public is simply ignored?
I'm quite well versed in C++ and template meta-programming and already have a fully reflective C++ system i.e member properties, member functions and global/static functions that uses boost.
A couple of things to keep in mind:
The power of COM comes largely from the IDL and the midl compiler. It allows a verry succint definition of the objects and interfaces with all the C/C++ boilerplate generated for you.
COM registration. On Windows the class IDs (CLSID) are recorded in the registry where they are associated with the executable. You must provide similar functionality in the UNIX environment.
The whole IUnknown implementation is fairly trivial, except for QueryInterface which works when implemented in C (i.e. no RTTI).
A whole another aspect of COM is IDispatch - i.e. late bound method invocation and discovery (read only reflection).
Have a look at XPCOM as it is a multi-platform COM like environment. This is really one of those things you are better off leveraging other technologies. It can suck up a lot of the time better spent elsewhere.
I'm looking to implement a custom implementation of COM in C++ on a UNIX type platform to allow me to dynamically load and link object oriented code. I'm thinking this would be based on a similar set of functionality that POSIX provides to load and call dll's ie dlopen, dlsym and dlclose.
At its simplest level, COM is implemented with interfaces. In c++, if you are comfortable with the idea of pure virtual, or abstract base classes, then you already know how to define an interface in c++
struct IMyInterface {
void Method1() =0;
void Method2() =0;
};
The COM runtime provides a lot of extra services that apply to the windows environment but arn't really needed when implementing "mini" COM in a single application as a means to dynamically link to a more OO interface than traditionally allowed by dlopen, dlsym, etc.
COM objects are implemented in .dll, .so or .dylib files depending on your platform. These files need to export at least one function that is standardized: DllGetClassObject
In your own environment you can prototype it however you want but to interop with the COM runtime on windows obviously the name and parameters need to conform to the com standard.
The basic idea is, this is passed a pointer to a GUID - 16 bytes that uniquely are assigned to a particular object, and it creates (based on the GUID) and returns the IClassFactory* of a factory object.
The factory object is then used, by the COM runtime, to create instances of the object when the IClassFactory::CreateInstance method is called.
So, so far you have
a dynamic library exporting at least one symbol, named "DllGetClassObject" (or some variant thereof)
A DllGetClassObject method that checks the passed in GUID to see if and which object is being requested, and then performs a "new CSomeObjectClassFactory"
A CSomeObjectClassFactory implementation that implements (derives from) IClassFactory, and implements the CreateInstance method to "new" instances of CSupportedObject.
CSomeSupportedObject that implements a custom, or COM defined interface that derives from IUnknown. This is important because IClassFactory::CreateInstance is passed an IID (again, a 16byte unique id defining an interface this time) that it will need to QueryInterface on the object for.
I understand that the general idea of COM is that you link to a few functions ie QueryInterface, AddRef and Release in a common dll (Kernel32.dll) which then allows you to access interfaces which are just a table of function pointers encapsulated with a pointer to the object for which the function pointers should be called with. These functions are exposed through IUnknown which you must inherit off of.
Actually, COM is implemented by OLE32.dll which exposes a "c" api called CoCreateInstance. The app passed CoCreateInstance a GUID, which it looks up in the windows registry - which has a DB of GUID -> "path to dll" mappings. OLE/COM then loads (dlopen) the dll, calls its DllGetClassObject (dlsym) method, passing in the GUID again, presuming that succeeds, OLE/COM then calls the CreateInstance and returns the resulting interface to app.
So how does this all work? Is there a better way to dynamically link and load to object oriented code? How does inheritance from a dll work - does every call to the base class have to be to an exposed member function i.e private/protected/public is simply ignored?
implicit inheritance of c++ code from a dll/so/dylib works by exporting every method in the class as a "decorated" symbol. The method name is decorated with the class, and type of every parameter. This is the same way the symbols are exported from static libraries (.a or .lib files iirc). Static or dynamic libraries, "private, protected etc." are always enforced by the compiler, parsing the header files, never the linker.
I'm quite well versed in C++ and template meta-programming and already have a fully reflective C++ system i.e member properties, member functions and global/static functions that uses boost.
c++ classes can typically only be exported from dlls with static linkage - dlls that are loaded at load, not via dlopen at runtime. COM allows c++ interfaces to be dynamically loaded by ensuring that all datatypes used in COM are either pod types, or are pure virtual interfaces. If you break this rule, by defining an interface that tries to pass a boost or any other type of object you will quickly get into a situation where the compiler/linker will need more than just the header file to figure out whats going on and your carefully prepared "com" dll will have to be statically or implicitly linked in order to function.
The other rule of COM is, never pass ownership of an object accross a dynamic library boundary. i.e. never return an interface or data from a dll, and require the app to delete it. Interfaces all need to implement IUnknown, or at least a Release() method, that allows the object to perform a delete this. Any returned data types likewise must have a well known de-allocator - if you have an interface with a method called "CreateBlob", there should probably be a buddy method called "DeleteBlob".
To really understand how COM works, I suggest reading "Essential COM" by Don Box.
Look at the CORBA documentation, at System.ComponentModel in the sscli, the XPCOM parts of the Mozilla codebase. Miguel de Icaza implemented something like OLE in GNOME called Bonobo which might be useful as well.
Depending on what you're doing with C++ though, you might want to look at plugin frameworks for C++ like Yehia. I believe Boost also has something similar.
Edit: pugg seems better maintained than Yehia at the moment. I have not tried it though.
The basic design of COM is pretty simple.
All COM objects expose their functionality through one or more interfaces
All interfaces are derived from the IUnknown interface, thus all interfaces have
QueryInterface, AddRef & Release methods as the first 3 methods of their virtual
function table in a known order
All objects implement IUnknown
Any interface that an object supports can be queried from any other interface.
Interfaces are identified by Globally Unique Identifiers, these are IIDs GUIDs or CLSIDs, but they are all really the same thing. http://en.wikipedia.org/wiki/Globally_Unique_Identifier
Where COM gets complex is in how it deals with allowing interfaces to be called from outside the process where the object resides. COM marshalling is a nasty, hairy, beast. Made even more so by the fact that COM supports both single threaded and multi-threaded programming models.
The Windows implementaion of COM allows objects to be registered (the original use of the Windows registry was for COM). At a minimum the COM registry contains the mapping between the unique GUID for a COM object, and the library (dll) that contains it's code.
For this to work. DLLs that implement COM objects must have a ClassFactory - an entry point in the DLL with a standard name that can be called to create one of the COM objects the DLL implements. (In practice, Windows COM gets an IClassFactory object from this entry point, and uses that to create other COM objects).
so that's the 10 cent tour, but to really understand this, you need to read Essential COM by Don Box.
You may be interested in the (not-yet)Boost.Extension library.