Does a "pure" IDispatch interface require a proxy/stub DLL? - c++

..for an out-of-process-server, or can I call a dispatch interface without registering a proxy/stub?
The interface in question is very high level, so performance is a non-issue, and I could make the whole thing registration-free, which is a big plus

I'm pretty sure you don't need to provide a custom proxy/stub dll if you limit your interface(s) to automation-compatible types. In that case, the system can use the automation marshaler and doesn't need any additional help. I believe the automation-compatible types are the types that can fit into a VARIANT, e.g. simple POD types, BSTRs, and the like.
I found this KB article which has some discussion of the automation marshaler, although it's not specifically targeted at your question. It does list the compatible types, at the very least. It also mentions that you need to specifically identify the automation marshaler in the registration for your component, but in my experience this isn't necessary - your mileage may vary.
Lastly, you may need to implement IProvideClassInfo as well; I usually use the implementation provided by ATL.

You only need a proxy/stub dll if your interface needs to be marshalled. This means if your COM server is in process, and the interface is not passed between apartments, and you aren't going to be calling it from .Net or any other situation that would require it to be marshalled, then you do not need a proxy/stub dll.

Related

What are the files required for a COM client to connect a COM server (out-of-process scenario)?

I would like to understand the purposes of the files mentioned in this article and link the knowledge to my current COM server and COM client scenario, so that I can implement my COM server to use the COM server: this
I am having a COM server which is an exe, or service, that runs in the background. For now, I know there is an exposed interface inherited both from IUnknown and IDispatch. Besides I have the following files generated:
xxx_i.c defines all the CLSIDs and IIDs
xxx_i.h defines all the method the interface supports
xxx_p.c ?
dlldata.c ?
I am now using the automation way, IDispatch -> Invoke(), to access the interface methods. Although this way seems work fine without using any files mentioned above, I still would like to understand the purposes of them while using the normal way, IUnknown -> QueryInterface(), to access the methods.
Since I am new to the COM world, any suggested reading would be appreciated! Thanks!
In its most simple form, COM is only the vtable binary contract plus the mother of all interfaces: IUnknown. COM is a way to reuse code without source, with components, it's some kind of a dynamic casting mechanism. Provided I know the coclasses you support (their CLSID), the interfaces they expose (their IID), and what are these interfaces' methods layout, their parameters, order, type, etc., I can use your COM server.
But to ease "communication" between your COM clients and your COM server, you can/should use some standard mechanisms/documentation and add tooling so plumbing stuff like marshaling (=serialization) will be taken care w/o any effort. This is crucial in the out-of-process case, less important with in-process (I will elude the "apartment" concept here...)
So, lots of things you'll find in COM (like registration, tooling, IDL, typelibs, etc.) are in fact optional, but also very useful (so they kinda become mandatory in the end). The purpose of things like idl (for "interface language definition") is to define and expose to your COM clients what your COM server supports so tooling can generate a lot of code automatically for you and your clients (.c, .h, .tlb). Note that nothing prevents you from implementing interfaces or coclasses without defining them in idl. Nothing obliges you to provide your .idl or your .tlb. In this case, I will only be able to use them if I known their IID, method layout etc.
Then, on top of IUnknown, Microsoft created a universal interface called IDispatch (this is also known as "Automation", or "Late binding" as opposed to "Early binding" for IUnknown), at that time targeting VB/VBA clients (before even VBScript, JScript, and lots of other COM clients, .NET supports IUnknown and IDispatch). IDispatch, if you go that route, could be the last interface you'll ever have to implement, because its semantics allows full discovery and invocation of any method, provided it supports a finite set of defined data types, the "Automation types": BSTR, VARIANT, etc.
So, if you support IDispatch, provide a TLB (typelibs) and restrict all types to Automation types, then you don't need to handle marshaling, you don't need proxies and stubs, you can forget about all this, even in out-of-process scenarios, because Microsoft implements that automatically. Back in the days, we used to call "oleaut32.dll" the "universal marshaler".
Dual interfaces are interfaces that support both IUnknown and derivates and IDispatch at the same time. They mostly exist to support C/C++ clients and Automation clients at the same time. Using Automation (BSTR, VARIANT, etc.) is a bit painful in C/C++ because they were not intended originally to be used by C/C++ clients... Note Microsoft proposes C++ smart wrappers classes: CComBSTR and CComVARIANT with ATL, or _variant_t and _bstr_t with the Windows SDK.
Requests for reading material are out of scope for StackOverflow, but I can't help but to reccomend the seminal work by Don Box: Essential COM which is in print and available as an ebook elsewhere. Here's Don's description of the topic:
Box, Don. Essential COM. Addison-Wesley, 1998, pp. 350:
COM is based on client programs having a priori knowledge of an
interface's definition at development time. This is accomplished
either through C++ header files (for C++ clients) or through type
libraries (for Java and Visual Basic clients). In general, this is not
a problem, as programs written in these languages typically go through
some sort of compilation phase prior to being deployed. Some languages
do not go through such a compilation phase at development time and
instead are deployed in source code form to be interpreted at runtime.
Perhaps the most pervasive of such languages are HTML based scripting
languages (e.g., Visual Basic Script, JavaScript) that execute in the
context of either a Web browser or a Web server. In both of these
cases, script text is stored in its raw form embedded in an HTML file,
and the surrounding runtime executes the script text on the fly as the
HTML is parsed. To provide a rich programming environment, these
environments allow scripts to invoke methods on COM objects that may
be created in the script text itself or perhaps elsewhere in the HTML
stream (e.g., a control that is also part of the Web page). In these
environments, it is currently impossible to use type libraries or
other a priori means to provide the runtime engine with a description
of the interfaces being used. This means that the objects themselves
must assist the interpreter in translating the raw script text into
meaningful method invocations.
To allow objects to be used from
interpretive environments such as Visual Basic Script and JavaScript,
COM defines an interface that expresses the functionality of
interpretation.
Tl;dr: there are two ways to do everything in COM (ignoring IInspectable and dual interfaces):
IUnknownStandard virtual method invocation. Fast, no extra code. Requires compile time interface information (.h or .tlb) on the client calls
IDispatch"Late Binding". Slow, lots of interpreting code. No client compilation or interface spec needed.
Practically speaking, unless you are calling from VBA, VBScript or have some old VB6 clients then you are better off sticking with IUnknown exclusively.

Dynamic calls to WinRT interfaces

I'd like to make dynamic (i.e. reflection-based) calls to WinRT objects, from C or C++. I will assume that I have winmd files available at run-time, so that I can find out what the methods are and what parameters they take.
In OLE Automation, IDispatch was then available to make the actual calls. However, WinRT objects don't support IDispatch. How can I then make calls? Do I need some kind of FFI library that will allow to dynamically pass the parameters, according to the COM calling convention of the processor? Or do I really need "static" class/struct declarations (for C/C++)?
Edit: The target system is a metro-style app. That precludes solutions involving banned APIs.
It is certainly possible to build what you're describing - under the covers that's exactly what the Chakra Javascript engine does with winrt metadata and is similar to what the CLR does. Both of these language projections discover the APIs at runtime and build up the low level assembly to make this happen.
It's a lot of work and isn't particularly pleasant but it's absolutely technically possible. The windows metadata contains all the information needed to create stubs for the APIs and structures.

What is the ($Foo)PS project in my $Foo ATL solution for?

Creating an ATL project in MSVC seems to create not one but two projects; the latter named the same as the former but with PS appended to its name. What is the purpose of this second project and how can I tell whether I need it?
COM supports making interface method calls across two different threads, two different processes or two different machines. This is called marshaling. Two different threads is the most common case, a COM server is often not thread-safe. COM implements thread-safety for such single-threaded coclasses by marshaling the call from the 'wrong' thread to the thread that created the server. Marshaling between processes occurs when you write an out-of-process server. Between different machines across a network is called DCOM.
This is implemented by creating an instance of the interface that looks exactly like the original. But all the methods of the interface are actually substitutes that do the job of the marshaling the call. This is the proxy. On the other end of the wire there's a substitute that looks exactly like the interface but does the opposite job. This is the stub. The proxy and stub work together to create the illusion that you're making a simple method call in your program.
The primary job of the proxy is to serialize the arguments of the method call into a memory buffer or network packet. This can be pretty untrivial, especially when you use pointers to variable-sized structures. COM needs help to get that right and that's the job of your FooPS project. When you run midl.exe on your .idl file, midl auto-generates code from the interface definitions to implement the proxy and the stub. This is quite often good enough but you may need to implement your own if the built-in keywords in IDL are not sufficient to describe your data.
Last but not least, Windows provides a standard marshaller that can marshal simple interfaces. Designed to support the sub-set of COM that's defined by COM Automation. In other words, interfaces that derive from IDispatch and only use Automation compatible types. You only need to get the registry entries right to enable it and don't otherwise need the proxy/stub generated by midl. And of course, if you only make simple in-process calls on one thread then you won't need it either. This is pretty common.
As #ebutusov said, *PS project contains implementations for Proxy and Stub. They are not standard, instead they are generated by MIDL for interfaces exported from your ATL server. These interfaces are declared in the *.IDL file. The ouput of the project is DLL. You may read this article to get more details.
You may remove PS project from the solution in case if you do not define any custom interfaces in you *.IDL file or if you define only interfaces which have dual and oleautomation modifiers. In that case a standard typelib marshaller will be used.
In order to be able to make use of the standard typelib marshaller, one has to register a typelibrary (which is done automatically since you are using ATL)
It's proxy/stub code, which contains non-standard data marshallers needed to transfer data between different apartments (threading related). It's used when application, which calls your COM object, uses different COM threading model. There was an option in ATL/COM wizard to merge this code into main library. In many common scenarios you don't have to worry about it (i.e. when your COM dll runs in the client context), unless you want to write a custom marshaller.

How to find interfaces of an ActiveX control?

Given an instance of an ActiveX control, how do I enumerate it's interfaces? (I'd like to get the names of the interfaces).
Like others have mentioned, the only way is to QueryInterface for all possible interfaces. And this is exactly what the Microsoft tool OleView does for you.
Unfortunately, that's not something COM is designed for. At the basic COM level, you can merely ask an object whether it supports a specific UUID-identified interface, one at a time. Since there are a lot of potential UUID's, getting an exhaustive list that way would take quite a bit of time! While most object implementations would track the list of supported interfaces internally, there is no standard COM way of accessing those lists from the outside. And even if there were, you could only get a programmatic name of the interface by looking their UUID's up in the registry, which isn't always reliable.
ActiveX objects (a tricky term!) tend to support automation through IDispatch. If the objects are well behaved, you will able to get some information on the methods they support through GetTypeInfo(). This won't include the names of the interfaces (if any) the methods belong to.
To summarize, COM is rather poor at object metadata.
No way. The idea behind COM interfaces is that you ask the object - "please give me interface XYZ if you support it) and the object decides how to respond - provide the reference to itself or expose the interface of some internal object etc. So you can't know what interfaces the object "supports" without asking the object as described above. This was the design decision of COM designers.

What's the advantage of using COM over a plain DLL?

Assume that you work only in the C++ world (cross-language interop is not required). What advantages/inconvenients do you see in using COM instead of a plain basic DLL? Do you think using COM is worth the trouble if you are not going to use the interface from different languages?
Everybody is mentioning things that are in COM's plus column. I'll mention a couple of detractions.
When you implement your system using COM, you need to register the COM 'servers' (be they in-proc or out-of-proc) at setup and unregister them at uninstall. This could increase the complexity of your setup system slightly and tends to require a reboot unless the user carefully tears down running processes first.
COM is slow compared to other standard ways of doing the same thing. This comment will probably generate a lot of hate and maybe some downvotes, but the fact of the matter is that at some point you will need to marshall data, and that is expensive.
According to the Rules of COM, once an interface has been published it can never be changed. That in itself is not a negative, and you might even argue that it forces you to do thorough design before shipping the interface. But the truth is there's no such thing as never, and in production code interfaces change. You will undoubtedly need to either add methods or change the signatures of existing methods. In order to accomplish this you have to either break the rules of COM -- which has bad effects -- or follow the rules of COM which are more complicated than just adding a parameter to a function like you would with a astraight DLL.
COM can be useful in plain old C++ for:
Interprocess communication
Plugin architectures
Late binding scenarios
"Much, much, more..." (tm)
That said, if you don't need it, don't use it.
With DLL you can get much closer coupling, while COM limits interactions very precisely. This is the root of both the advantages and the disadvantages!
You get more power and flexibility (e.g. inherit from classes defined in the DLL, not feasible in COM) but the dependency is thereby much stronger (need to rebuild the user for certain changes to the DLL, etc).
Often especially galling is that all DLLs and the EXE must use the same kind of runtime library and options (e.g. all dynamically linked to the non-debug multithreaded version of msvcrt* for example -- can't rebuild just one to use the debug version without incurring very likely errors!).
The looser coupling of COM is therefore often preferable, unless you really need the closer-coupling kinds of interactions in a specific case (e.g., a framework, which definitely requires user-code to inherit from its classes, should be a DLL).
If you can avoid don't use it. In my last project COM brought pretty much limitations into C++ interfaces being used. Just imagine, that you can't simply pass a std::string but have to use an array of characters. In that case you build the string, an then copy it to an array which can be handled by COM.
You also can only use very limited set of fundamental types, have casts and proprietary memory management. You can't use new/delete, but have to use COM own functions.
You also can't simply throw an exception, but have to initialize some COM interface IErrorInfo, which will be rethrown at the other end.
So if you don't need, don't use it. It will definitely screw your design. And if you need it, try to evaluate other interop possibilities: boost::interprocess, zeroc ice...
Regards,
Ovanes
Registration and discovery
Out-of-process
Remote invocation
are the few extra features that you would have got. Even transactional support can flow without the need for COM support these days.
The IUnknown interface is a good base level to support anyway -- gets you a way to add features without breaking old clients (QueryInterface) and pervasive reference counting. You can implement this without buying into everything in COM.
Then, whenever you are adding a feature to a class, if you use the COM interface for it, you at least get an interface that is known -- for example IDispatch if you want reflection features.
Your only delta away from being able to be called by another language would then be the registration and the class factory.
Because interfaces are independent of any particular DLL, at its simplest level, a COM like approach at the very least frees you to change the dll serving an interface under the hood, without having to recompile your app against the new dll name.
Using Full COM with MIDL defined interfaces and proxy stub dlls means that you can use COM to manage thread safety in-process, interprocess comms on the same PC, or even connect to the COM server object on a remote PC.