COM Objects in Direct3D - winapi

As mentioned in Microsoft documentation there are two ways to create COM objects:
The module that implements the object might provide a function specifically designed to create instances of that object.
Alternatively, COM provides a generic creation function named CoCreateInstance.
In direct3D you can use first method to create Objects like you use D3D11CreateDevice()
but how you do this by the second method.maybe you need CLSID_D3D11CreateDevice which I didn't find.Is there any library to include or maybe it's impossible to create by the second way.
Also I really like to know if there is a way to see COM objects and what interfaces they implement.

DirectX APIs are not "true COM". These APIs derive from IUnknown for reference counting and polymorphic interfaces for versioning, but they do not follow all the other rules of COM objects. The lifetime rules are also modified for "child" objects, and DirectX APIs only support COINIT_MULTITHREADED.
This is a design pattern known informally as "COM lite" or "nano-COM".
Objects are created with a Win32 "flat" factory function
Objects generally support only IUnknown, the main interface, and derived versions of the main interface
Methods on interfaces can return void or HRESULT
Not all methods need to be thread-safe
They do not support COM aggregation
Interface pointers as parameters do not support client-provided implementations
Direct2D/DirectWrite and Windows Imaging Component (WIC) support CoCreateInstance as did did the original XAudio2 for Windows up to version 2.7 and legacy XACT. Otherwise, "DirectX" components do not support registry-based or manifest-based creation.
This pattern provides a stable "Application Binary Interface (ABI)" and maps well to C++ single-inheritance of pure-virtual classes. It provides an easy way to extend with new versions to add methods, and reference-counting for lifetime management. The resulting APIs are generally compatible with the IID_PPV_ARGS macro as well as COM smart-pointers like Microsoft::WRL::ComPtr, winrt::com_ptr, or the older ATL CComPtr.
See Microsoft Docs: Programming DirectX with COM
More recent versions of DirectX like DirectX 12 have adopted "strongly-typed bitmasks" which were not used in older versions. See this blog post.
While historically the DirectX "COM lite" APIs have provided C support through macros, the most recent guidance is to just support C++ and make use of C++11 features like strongly-typed enumerations (a.k.a. scoped enumerations). You'll see this reflected in the DXCore interfaces.

Related

How can I create a COM object in Rust that inherits from a COM object defined in C++?

I am trying to make a Rust program that emulates a webcam. This question and this answer suggest that the best way to do this is by creating a DirectShow source filter. Based on the PushSource sample in the Windows SDK and some C# implementations on CodeProject, it seems like the canonical way to do this is to extend the DirectShow BaseClasses provided in the Windows SDK. However, this is where my understanding breaks down.
I found the cxx crate and was able to get the classes from BaseClasses into my program, but how do I inherit from them or instantiate them? This crate does not seem to be designed for use with COM, and it is not clear how to call the constructors of classes.
Once I have done that first part, how do I expose my new classes as COM components? I found the com crate, but it seems to expect me to import the base classes using their GUIDs. However, I have no idea how to figure out what their GUIDs might be.

How does COM achieve language interop?

I understand how COM can achieve compiler agnostic C++ code, since it defines an ABI by being careful what features of the C++ language to use. It's just C++ code talking to C++ code in a really clever way. However I still don't understand how it can allow for language interop with C# or Javascript for example.
Where is the boundary? The only explanation I have right now is that the language compiler itself must have special support for COM so that it can generate the proper assembly code to allow for accurate communication between caller/callees.
Since you've tagged your question with WinRT, I assume you're asking specifically about how this is achieved by WinRT language projections. In that case, all languages must have some way to map their natural language constructs to the COM ABI that WinRT defines. That ABI is derived from metadata encoded in the ECMA 335 standard and special rules are applied to transform the abstract metadata into a concrete ABI. There are naturally different ways to achieve this. The CLR itself was updated to support WinRT in C#. The Visual C++ compiler was (sadly) updated with language extensions to support WinRT via C++/CX. The C++/WinRT approach is very different in that it requires only a standard C++ compiler and all of the knowledge about WinRT is delivered via a standard C++ header-only library. Other languages might take different approaches, but at the end of the day they must agree on the way that types expressed in metadata are transformed into objects and virtual function calls on the ABI based on COM.
And while this process is not well documented at the moment, C++/WinRT is one of the only open source language projections and thus acts as a useful reference implementation for those who need to understand how WinRT works under the hood.
https://github.com/microsoft/cppwinrt
The "Type Library" is what enables interop of COM components between different languages.
https://learn.microsoft.com/en-us/windows/desktop/midl/com-dcom-and-type-libraries
A type library (.tlb) is a binary file that stores information about a
COM or DCOM object's properties and methods in a form that is
accessible to other applications at runtime. Using a type library, an
application or browser can determine which interfaces an object
supports, and invoke an object's interface methods. This can occur
even if the object and client applications were written in different
programming languages. The COM/DCOM run-time environment can also use
a type library to provide automatic cross-apartment, cross-process,
and cross-machine marshaling for interfaces described in type
libraries.
The other approach for language interop (e.g. C++ projecting objects to Javascript) is that a COM object can implement IDispatch.
It’s not magic, of course.
COM sets up rules for language interop. It’s just a contract, with some helpful tooling. Each language that wants to support COM has to find a way to abide by the rules on its own. They all have to provide their own compatible mechanism one way or another.
In the case of C++, the rules appear to come for free as you mentioned, but be aware there is one caveat: the language standard does not specify the layout and mechanism of classes and virtual functions. The method mimicked by COM is one extremely common implementation of virtual calling (“the VTable”), and COM follows the exact layout used by the Microsoft compiler. But you can have a perfectly valid C++ compiler where classes with virtual functions would not be compatible with the COM layout. It’s just that nobody does that, at least not in Windows compilers. So even in C++ there is some “meeting in the middle” by the compiler.
In C, you have to do the whole thing by hand. Other languages might allow you to do the same thing (assembler of course).
To help compiled languages exchange information about specific contracts, COM provides Type Libraries and mechanisms to read them. A compiler or language that want to take advantage of them also has to “meet in the middle” and learn how to process them (for example, the Microsoft C++ #import directive; the VB6 Libraries menu).
No every language will support everything you can do in COM, because there is a point (in more obscure features) where the return on investment in implementing support in the language doesn’t pan out. Each language has to pick its own limitations. There is plenty of stuff that you can do in COM (read the IDL specs) that VB6 cannot do.
Because following COM rules in a script-like language is between inpractical and impossible, COM offers a higher-level approach (Automation) that is more amenable to dynamic languages, even if more limited. But a language implementer that wants to provide client support for Automation has to implement an understanding of the IDispatch interface, an activation mechanism, and a translation to its language’s proper facilities. And a scripting language wanting to provide support for creating COM servers has to work even harder to implement a valid COM IDispatch implementation and a standalone host engine on behalf of the user scripts. Even VBScript couldn’t do this at the beginning, until Microsoft added .SCR support with the Windows Scripting Host. “Meeting in the middle” again.
If a language wants to support both pure COM and Automation, they need to work double hard; support for one does not automatically give you support for the other.
For .NET languages like C#, most of the work is done for both native COM and Automation inside of the .NET Runtime, which provides the implementation of the COM Callable Wrappers (CCW) and Runtime Callable Wrappers (RCW) necessary to interact with COM, and handling the conflicts between the Reference Count approach of COM and the GC approach of .NET. Microsoft did all the work in one place so individual .NET language designers didn’t have to.
So, yes, the language implementer has to work extra to give the language special support for COM: following the binary layout rules, implementing a translation layer when needed, and/or possibly providing tooling to read Type Libraries.
Language Interop requires both sides (the caller and the callee) to “meet in the middle” somewhere. COM is just a specification that gives designers that middle ground, “a place where all can meet”.

IFileOpenDialog and IFileSaveDialog from VBA

How do you call IFileOpenDialog and IFileSaveDialog from VBA?
According to Microsoft, applications written for Windows 7 and later should use IFileOpenDialog/IFileSaveDialog API calls instead of GetOpenFileName/GetSaveFileName (see Using the Common File Dialog). This is especially important for full Library support.
Short answer: it's probably not worth the effort.
Longer answer: the CFD interfaces don't extend IDispatch, which makes them impossible to call via late binding from VBA. That doesn't mean they can't be called from VBA, but it means they require a typelib to describe the "shape" of the IUnknown-based CFD interfaces. Unfortunately, Microsoft doesn't provide the CFD interface definitions in a typelib. You can roll your own typelib by reverse-engineering the header files (or try to find the original IDL in the SDK), but you'd then have to register that typelib on every machine you want to use it on (the tools for which are not shipped on the machine, unlike regsvr32 for COM stuff). Assuming you did all that, you could then reference the typelib from VBA, and conditionally call it on Vista or higher OSes. You could also shim through to a small .NET assembly that would create a System.Windows.Forms.FileDialog-derived type and marshal the results back to VBA- that would be much easier, but still more-or-less require that you register the assembly on every machine (or use C++/CLI or other hacks to export a managed DLL function), and it requires you to take a .NET dependency.
They sure didn't make it easy... :) Good luck!

How I can enumerate the COM Object Members like interfaces, properties and methods?

Which WinAPI method or interface I can use to enumerate the interfaces, properties, methods(and parameters) of a COM Object programmatically?
You need to be more specific. There are two ways to interpret your question.
One is that you have a COM component (e.g. some library), and you want to programmatically enumerate interfaces/properties/methods of that. Usually (but not always), COM components come with a type library that contains full metainformation about all this - it's either embedded into the COM .exe or .dll, or is a separate .tlb file. In any case, if the COM component is properly registered in the system (e.g. using regsvr32), then COM provides a standard API to retrieve that type information, centered around ITypeLib and ITypeInfo interfaces.
Another interpretation is that you get a reference to a particular COM object, and you need to enumerate all methods/properties on that and/or invoke them by computed name, like Java or C# reflection, or Delphi RTTI. If so, then it is only possible if the COM object implements IDispatch interface, which allows you to do all of the above.
Well, COM objects are referenced through interfaces, which are opaque abstractions by design. You can't get at the underlying object without some black magic that will only work if you have a really good knowledge of the low-level details of the Delphi object model and the object was actually written in Delphi.
About the best you can do is examine the interface declaration itself, which will give you all the available information in its methods and properties.
I assume you want a list of all interfaces that will successfully QueryInterface. The answer is there's no intrinsic way in COM to do this. Some interfaces themselves provide this functionality like IServiceProvider.
You can get at everything you want from the registry, however this will take some time as the information is not ordered in such a way to give you the information you want without first analyzing most of it. If you download the utility OLEVIEW32 from the Microsoft platform SDK (available on MSDN) you can use it to explore the COM interfaces registered on the machine.
The fundamentals of COM work through the interfaces registered in the registry, under the HKEY CLASSES ROOT\CLSID. When you ask for a specific com object, it resolves to one of these guids, which in turn looks at the InprocServer32 section under this guid to determine what DLL/EXE to load, and what threading model to use. You could use this information to build a map of guids which also resolve to the same DLL (this is to get the classes)
In HKEY CLASSES ROOT\Interface is a link to all of the interfaces registered in the system. Again, its time to play lookup since much of this information is just pointers to another key, or type library. What IS here however and is useful is a list of GUID -> InterfaceName (default property of each guid).
In HKEY CLASSES ROOT\TypeLib is a link to all of the type libraries registered in the system.

What is the closest thing to Windows COM/DCOM in the Linux world?

Anything higher-level, and more comprehensive than pipes/sockets?
For interprocess communication, D-Bus is the standard higher level mechanism. Both GTK and Qt have bindings for D-Bus, most desktop environments (or at least GNOME and KDE) expose various services via D-Bus, and many desktop applications can be controlled via a D-Bus interface. The system bus is also useful for finding out various low level information about the system using standard system services.
KDE4 (built upon Qt4) also includes a technology called KParts, which are often compared to Window's COM.
Yes, there are lots of things, but there isn't one as "Standard" as COM/DCOM. At least, in Windows, COM / DCOM are used by "Windowsish" stuff, and other RPC mechanisms are used by un-"Windowsish" stuff.
Linux doesn't have anything like that, instead things which need higher level RPC protocols typically use whatever their language provides, or a specific library which best suits an app's needs. Examples of that would be RMI in Java, Python's "pyro" module, etc, which will provide (some) functional parity with DCOM.
Corba is a bit heavyweight but some people apparently do use it.
A lot of applications roll their own RPC libraries. Don't do that unless you have to, it's nasty.
D-Bus
D-Bus uses a logical "Bus" over which connected applications may communicate
communication takes place via a simple object model that supports both RPC and publish-subscribe mechanisms
D-Bus includes a standard introspection mechanism for the run-time querying of object interfaces, applications connected to the bus may query for the availability of objects, call remote methods on them, and request notification for the signals they emit
before: GNOME Bonobo, KDE DCOP, CORBA, Sun RPC... nowadays people seem to prefer D-Bus
UNO
interface based component model, as are COM and CORBA
all UNO-interfaces must be derived from a interface that offers acquire, release, and a queryInterface method (comparable to COM)
the lifetime of UNO-objects is controlled by global reference counting.
components communicate only via their interfaces
o each component lives in a Uno Runtime Environment (URE), there is no performance overhead for components, that are instantiated within the same URE, e.g., in C++, a call from component A to B is just a virtual call
UNO-interfaces are specified in IDL
exceptions are used for error handling.
XPCOM
similar to Microsoft COM
Interfaces in XPCOM are defined in a dialect of IDL called XPIDL
disadvantage is that XPCOM adds a lot of code for marshalling objects between different usage contexts, which leads to code bloat in XPCOM based systems
...another alternative to consider might be Java RMI as well
It's also worth to see related questions:
Is there an equivalent to COM on *nix systems ? If not, what was the *nix approach to re-usability?
Analog of COM programming in Linux/UNIX
The Mono project jumps to mind. Mostly because the CLR/.NET is the new COM -- after all, COM was initially sold as language independent, binary compatible objects.
http://mono-project.com/
I guess DCOM (i.e. COM with a longer wire) would be .NET remoting? Or perhaps some web services with object serialization. I believe Mono supports both.
You can check out Corba, it works on Linux and Windows as well.
There is Mozilla's XPCOM technology, Cross Platform Component Object Model. Sort of similar to COM or DCOM conceptually.
Here is a list of the relatively few programs which do make use of the D-bus
DCOM is available on Linux. It isn't "the linux way of doing things", but hey, if you want "like DCOM, but Linux" then just use DCOM on Linux and have done...
https://web.archive.org/web/20071008135843/http://www.softworksltd.com/dcomlinuxfaq.html

Resources