Ticket #82 (closed defect: fixed)

Opened 3 years ago

Last modified 3 years ago

IUnknown is not unique

Reported by: jasper Owned by: jasper
Priority: major Milestone: Maintenance of Phase II
Component: COMBIA Version: 1.2.0.8
Keywords: Cc:

Description

In a scenario where a COBIA object is exposed to COM via COBIA, a wrapper is placed around the object.

If a COBIA object is passed as an argument to COM, through a COMBIA call, this object is also wrapped by a COM object.

If the object that is passed as an argument was already wrapped, this leads to a second COM wrapper being created in case the object is passed as argument as well. This happens for example in ICapeFlowsheetMonitoring::RegisterForEvents?. In this situation, there are two COM objects created for the same COBIA object, and they are therefore observed from the COM side as two different objects. The first argument to RegisterForEvents? of course is means exactly to identify the object (which can be done by QI for IUnknown, as COM rules stipulate that QI for IUnknown on the same object must always return the same pointer).

Change History

comment:1 Changed 3 years ago by jasper

  • Status changed from new to closed
  • Resolution set to fixed

Also in the custom data interface specification, the data source is passed as argument, and similar scenarios occur.

It is assumed that if you QI for ICapeInterface on a COBIA object, the interface that is returned is unique, just as in COM. All current COBIA object implementations that are based of CapeOpenObject? fulfill this.

An operator== is added to CapeInterface? to check equality against another CapeInterface? or ICapeInterface, as assigning objects to CapeInterface? does not actually do a QI - it does a cast (all CAPE-OPEN interfaces can be cast to ICapeInterface). The operator== does a QI for ICapeInterface on both objects and compares the resulting pointers.

The solution to the multiple COM wrapper creation is to keep a table of COM wrappers that are currently alive, index by unique ICapeInterface pointer. Any COM wrapper created is added to the table, any COM object deleted is removed from the table. If a COM pointer is requested, the table is checked. All of this is shielded by a mutex specific to this table.

A similar construct is created for the opposite direction - wrapped COM objects now return the same wrapper object to COBIA even if passed by argument, and therefore result a unique mapping to ICapeInterface*.

comment:2 Changed 3 years ago by jasper

One of the fixed caused a crash - a new operator== on CapeInterface? failed to check for a null pointer. Fixed in revision 228

comment:3 Changed 3 years ago by jasper

Another bug is caused by an invalid reference count on passing a COM object twice to COBIA, and one that is caused by creating a duplicate object for a parameter spec due to difference in arrangements of parameters on COM and COBIA. Fixed in revision 229.

Note: See TracTickets for help on using tickets.