What COM support is needed to get my custom DirectShow filter property page to work for a remote filter from the Running Object Table - com

I have some custom DirectShow filters with custom property pages. These work fine when the filter is in the same process as the property page.
However when I use the 'connect to remote graph' feature of Graph Edit the property pages don't work.
When the property page does a QueryInterface for my private COM interface on the remote filter, the QueryInterface fails. Property pages of Microsoft filters (e.g. the EVR video renderer) work fine so it must be possible.
Presumably this is happening because my filter's private interfaces only work 'in process' and I need to add extra COM support so that these interfaces will work with an 'out of process' filter. What do I need to do in COM terms to achieve this?
Do the DirectShow baseclasses support these COM features? Can I reliably detect when the filter is running out of process and refuse to show the property page gracefully?

One option is to build a proxy/stub pair. But another, and way easier, is to make your private interface automation compatible (derive from IDispatch, type constranits apply), and put it into type library, which is to be attached to the DLL, and registered the usual way. Proxy/stub pair will be supplied for such interface automatically without need to bother.
DirectShow base classes do not offer built in support for this. Stock DirectShow filters provided with Windows might be not not be compatible with passing interfaces over process boundaries and my guess would be that it depends on the team in charge for respective development years ago. Video renderers, for instance, have interfaces that you can connect remotely through. Audio renderers, on the contrary, have interfaces without such capability in mind and they just crash one of the processes attempting to makes such connection (client side process, if my memory serves me right).

Related

Registration-free COM and multiple offers of the same interface

We have a suite of components which offer the same set of interfaces.
While investigating the possibility of client code using registration-free COM, we stumbled upon this problem.
One client may use different implementations of the same inteface, depending on configuration provided by the user. Therefore, it must include a dependency for each one of these components.
Each one of these components contains a comInterfaceProxyStub element registering the exported component interface.
That is, we have many components with a comInterfaceProxyStub exporting the same set of interfaces, which they all implement.
It seems this fact causes an error at activation time. ststrace.exe is not clear but it seems it is refusing to "register again".
What are we missing?
Is it supposed to be an error trying to activate a second component with a comInterfaceProxyStub element for an interface already "registered"?

VB connect to COM object

Either I don't understand COM objects, either it's all that confusing.
I frequently 'create' , 'dispatch' COM objects - either in Python, either in VB ( Obj = win32com.client.Dispatch('Visum.Visum') or Obj = CreateObject("Excel.Application") respectively).
That's easy, obvious and everything's fine.
But how can I:
a) connect to COM object which is already running
b) get list of running processes which are COM objects
in VB what is the reference, and additional info on: CreateObject command. In Python it's part of well defined, comprehensive library of win32com whereas in VB it's just single method without reference: http://msdn.microsoft.com/en-us/library/7t9k08y5(v=vs.80).aspx
Highly confusing (COM object,server? connection, dispatching, registering??)
Thanks for claryfying
Rafal
i2
First of all, I would suggest reading a good introduction to COM. Personally, i think that 'Essential COM' by Don Box is the best book about COM. Spending a few hours with it will save you many hours later.
That being said, let's move to your questions.
a) In order to retrieve an existing COM object from VB, you need to call GetObject function. This will only work for COM objects which are registered with Running Object Table. Excel does this, so there shouldn't be any problems with that.
b) as Hans Passant correctly noted, this question doesn't make sense. Processes and COM objects are completely unrelated things, except for the fact that processes host the COM objects. It is similar to asking 'which processes are instances of class X'. However, a process can host a COM object (or many of them). These object can be alive only temporarily, so what would you expect there? Besides, many COM classes are implemented within dlls, but created instances obviously are hosted within a process - so what would you expect there?
COM technology is something I didn't not use for a while, so sorry if some info might be wrong (anyway, I've got my book "Inside COM+ base services" with me!)
Briefly speaking, let's give a simplified definition of a COM object: it nothing else than a standard DLL with classes exposing a standard interface IUnkown with the following methods:
AddRef: to register a client consuming the COM object
Release: to unregister a client (usually unused objects stop running, but other might remain resident)
QueryInterface: to get the address of a function
QueryInterface is used to dynamically retrieve the address of a function (late-binding) which is powerful (you don't have to know the DLL at compile time) but time consuming. On the other hand, you can directly reference the addresses of the functions at compile-time because those DLL are registered in the system (all the informations are stored in the registry)
Creating a new object or getting the address of a running object is done through RPC (remote procedure call) which will load and/or play the role of a proxy
So to create a new instance of a COM object, you will call CreateObject (in VB) (Co)CreateInstance in VC++ (or even c#?), while to get an executing instance, you might want to call GetObject().
Getting the list of COM objects is not that easy (I guess not possible at all) because, as told earlier, a COM object is nothing else but a DLL: this means that the library will mainly load in the address space of each process which access is private. Even for out-process COM objects (opposite to in-process) which are object shared between many processes (i.e.: Excel is an out-of-process COM object: you don't load the DLL in your application's address space), they are loaded by a host (rpc.exe or a proprietary host)
Hope this helps
Serge

Create each COM-instance in it's own exe-container

Is there possible to create a COM-instance in it's own, dedicated, host-process?
I guess some background is needed.
We have an end-user client which has it's central logical components inside an singleton-COM object. (Not propper singleton, but it uses global variables internally, so it would fail.) So that there should be only one instance per exe-file. Convenient while making the client.
However, I should now make a "client-simulator" to test the server-side. I therefore which to make 20 instances of the client-component.
If I could make each instance instanciate in its own exe-host, then the singleton-issue would be handled.
Regards
Leif
I have been struggling with this problem for a few days. I finally found a solution that works. My COM object is written using ATL, so my code snippet will be geared toward that, but the technical solution should be clear. It all hinges on how the class objects are registered. The REGCLS_SINGLEUSE flag is the key. I now have separate processes for each object instance.
In the ATL module, override the RegisterClassObjects() function as follows:
HRESULT RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags) throw()
{
return base::RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_SUSPENDED | REGCLS_SINGLEUSE);
}
From MSDN regarding REGCLS_SINGLEUSE:
REGCLS_SINGLEUSE
After an application is connected to a class object with
CoGetClassObject, the class object is removed from public view so that
no other applications can connect to it. This value is commonly used
for single document interface (SDI) applications. Specifying this
value does not affect the responsibility of the object application to
call CoRevokeClassObject; it must always call CoRevokeClassObject when
it is finished with an object class.
My theory is that because the registration was removed from public view, it causes a new process to be created for the subsequent instantiations.
This other question mentioned a description of how to use DLLHost as a surrogate process:
http://support.microsoft.com/kb/198891
I've never tried this myself, and I don't know off-hand if you can specify flags for the factories (which control if surrogates can be reused for multiple objects), but maybe you can tweak that via DCOMCNFG or OLEVIEW.
My COM days are long gone, but as far as I remember, there's no built-in way to do that.
It might be easier to rewrite your code so it supports multiple instances than to go the one-process-per-instance route with COM, but here's what you could do:
Use thread-local storage for your global variables and write another CoClass, where each instance owns its own thread through which accesses to the class with the global variables are marshaled. This would at least allow you to avoid the performance impact of DCOM.
Write your own out-of-process exe server (similar to windows' DllHost.exe) to host your COM instances. This requires IPC (Inter-Process Communication), so you either have to code something yourself that marshals calls to the external process or use DCOM (presuming your COM object implements IDispatch)

What is COM?

I searched hard, but was unable to grasp the whole idea. Can anyone tell me:
What COM actually is?
How do GUIDs work, and how are they used by COM?
How does COM resolve the issues of different DLL versions.
Or at least, point me to a good article somewhere that explains these concepts?
Thanks!
COM is "Component Object Model". It is one of the first technologies designed to allow "binary reuse" of components... Originally, it was the rewrite of what was, in Microsoft Office circa 1988-1992 time frame, referred to as Dynamic Data Exchange (DDE), a technology designed to allow the various Office applications to talk to one another. The first attempt to rewrite it was called OLE-Automation (Object Linking and Embedding). But when they got done they renamed it to COM.
How it works:
Essentially, before COM, when a client component wanted to use a component (written as a C++ library), it had to be compiled WITH the library, so it could know exactly how many bytes into the compiled binary file to find each method or function call.
With COM, there is a defined mechanism as to how these methods will be structured, and then the compiler produces a separate file (called a type library or an Interface Definition Language (IDL) file, that contains all this function offset data.
Then, as a user of the component, you have to "register" it, which writes all this information (Keyed off of GUIDs) into the OS Registry, where any client app can access it, and by reading the data from the registry, it can know where in the binary file to find each method or class entry point.
Your question is a little large for a full explanation here. A quick high-level introduction to COM can be found in the book Understanding ActiveX and OLE. A more detailed but still introductory introduction is Inside COM. The best book on the subject is Don Box's Essential COM.
A couple of quick answers:
COM is a binary interface standard for objects. It allows various programs to write to interfaces without all having to have been written in the same langauge with the same compiler. There are also related services available.
GUIDs are globally unique numbers that COM uses to identify interfaces.
COM doesn't resolve different DLL version problems. It only allows a single DLL to be registered for each GUID.
COM enables reusable software. Like building blocks, you can create COM objects (or now Assemblies in .NET) to provide functionality to a larger piece of software. I have used COM to provide DB integration for Excel and MS BizTalk. Software like MS BizTalk use COM/Assemblies to extend the processing capabilities of a standard process; you can insert a COM into the message workflow to do more processing than is implemented by Microsoft. COM also allows use of Component Services providing built in object pooling, security, and control interface.
Wikipedia has a good definition of GUID. Note that Microsoft has a formatting that is not necessarly used in the rest of development community.
COM by itself does not resolve DLL version issues. It enables you to extend software incrementally if you use the COM versioning capability. So if you have an application that uses a COM to convert XML to Text (for example) and you want to enhance, you can create a new version (2.0) which you can roll-out slowly as you update the source application to use the new COM. This way you could (if need be) have a switch statement that can still use the old COM if required by system limitations, or use the new one (they would be different DLLs).
COM is a lot of different things. I recommend Don Box's book, Essential COM as a good way to learn.
At a bare minimum, a COM object is an object that exposes a single interface, IUnknown. This interface has 3 methods, AddRef, Release, and QueryInterface. AddRef/Release enables the object to be reference counted, and automatically deleted when the last reference is released. QueryInterface allows you to interrogate the object for other interfaces it supports.
Most COM objects are discoverable. They are registered in the registry under HKEY_CLASSES_ROOT with an identifying GUID, called a CLSID (class ID). This enables you to call CoCreateInstance to create an instance of a registered object if you know a GUID. You can also query the registry via a COM API for the CLSID that backs a ProgId (program id), which is a string that identifies the object.
Many COM objects have typelibs that specify the interfaces and methods the object supports, as well as IDispatch which has a method, Invoke, that allows you to dynamically call methods on the object. This enables the object to be used from scripting languages that don't support strong typing.
Some objects support being run in a different process, on a different thread, or on a different machine. COM supports marshalling for these types of objects. If possible, a standard marshaller can use the object's typelib to marshal calls to the object, but custom marshallers can be provided as well.
And there's a whole lot more to COM objects, I'm barely scratching the surface.
10,000 foot view:
COM is the communication mechanism for software components. Example, you can interact with COM interfaces (COM interop in .NET) to use functionality not exposed through a common interface (.NET assembly).
GUIDs are explained fairly decent on Wikipedia http://en.wikipedia.org/wiki/Globally_Unique_Identifier
I always understood LIB files to be object files for the C++ linker. They contain the code for all objects in a cpp file. The compiler optimizes when it links disregarding portions of the object file that it doesn't need.
Someone please clarify as I am sure I butchered some of this.
COM is Microsoft's Component Object Model, a binary-compatible interface for programs written in various languages to interoperate with each other. It is the "evolutionary step" between the OLE and .NET technologies.
If you want to learn about COM from the C++ perspective, take a look at Don Box's Essential COM, or ATL Internals by Rector and Sells.
The group microsoft.public.vc.atl is probably the best place to ask questions you can't get answers for here. It's primarily an ATL newsgroup, but it seems to be the newsgroup with the most traffic for general COM questions as well. (just be prepared for the usual newsgroup curtness & impatience)
COM is a method to develop software components, small binary exe, that provides services for applications, OS and other components. Developing custom COM comnponent is like developing Object oriented API. GUID is a Global unique ID and used to identify a COM component uniquely.
You can refer a very good book by Dale Rogerson for more details. Inside COM

When To Change a GUID on a Type Library

I know that when you add/change/remove methods in a COM interface you're supposed to change the interface/coclass GUID but what about type libraries. When should you change the type library's GUID? Do you change it if a GUID inside the type library has changed? Or should you only change it when something that doesn't have its own GUID within the type library changes.
The basic principle is that COM interfaces and Type Libraries should be immutable (that is, they shouldn't ever change). If you change one item inside a COM interface, then the new version needs to be a completely separate entity from the previous version. The only way to do this is to change the GUID for every interface in the library and the GUID for the type library itself. It's also a good idea (for your own personal sanity) to change the name of the type library.
Ideally you shouldn't ever change a COM interface. Instead create a new derived COM interface and publish in a new type library.
I've got a similar question.
I had an original control with CLSID_A that implemented interface IID_A in some 1.0 type library with GUID_A
Later on, I decided to add a new interface to the original control. It would then implement both IID_A and IID_B interfaces. I figured that I should probably keep the same CLSID but didn’t knew much what to do with the typelib itself. I was mostly doing VC++ programmatic-by-the-book stuff which involved QueryInterface and didn’t cared much about versioning and typelib. You wanted to create an object with a specific CLSID, you just asked CoCreated instance...and then Queried interface for potential support of the new interface...
Now when I get into fancier environments like LabVIEW or design-time drop-in development environments like Microsoft .NET, MFC stuff that seems to break.
You are mentioning in your answer to change all of the GUID. Is the whole paradigm of adapting an application based on available functionality dead, that a newer application could still use its basic functionality with the older version of a control? Maybe I didn’t catch the later wave that is: No point in adapting an application to run using old control version, it simply requires a specific control version. That would be reason M$ also came out with the ASSEMBLY thing.