Previous Table of Contents Next


18.3.10 Interface Mapping


   COM is a binary standard based upon standard machine calling conventions. Although interfaces can be expressed in Microsoft IDL, Microsoft ODL, or C++, the following interface mappings between COM and CORBA will use Microsoft ODL as the language of expression for COM constructs.

   COM interface pointers bidirectionally map to CORBA Object references with the appropriate mapping of Microsoft IDL and ODL interfaces to OMG IDL interfaces.

   18.3.10.1 Mapping for Interface Identifiers

   Interface identifiers are used in both CORBA and COM to uniquely identify interfaces. These allow the client code to retrieve information about, or to inquire about other interfaces of an object.

   COM identifies interfaces using a structure similar to the DCE UUID (in fact, identical to a DCE UUID on Win32) known as an IID. As with CORBA, COM specifies that the textual names of interfaces are only for convenience and need not be globally unique.

   The COM interface identifier (IID and CLSID) are bidirectionally mapped to the CORBA RepositoryId.

   18.3.10.2 Mapping for COM Errors

   COM will provide error information to clients only if an operation uses a return result of type HRESULT. The COM HRESULT, if zero, indicates success. The HRESULT, if nonzero, can be converted into an SCODE (the SCODE is explicitly specified as being the same as the HRESULT on Win32). The SCODE can then be examined to determine whether the call succeeded or failed. The error or success code, also contained within the SCODE, is composed of a “facility? major code (13 bits on Win32 and 4 bits on Win16) and a 16-bit minor code.

   COM object developers are expected to use one of the predefined SCODE values, or use the facility FACILITY_ITF and an interface-specific minor code. SCODE values can indicate either success codes or error codes. A typical use is to overload the SCODE with a boolean value, using S_OK and S_FALSE success codes to indicate a true or false return. If the COM server returns S_OK or S_FALSE, a CORBA exception will not be raised and the value of the SCODE will be mapped as the return value. This is because COM operations, which are defined to return an HRESULT, are mapped to CORBA as returning an HRESULT.

   Unlike CORBA, COM provides no standard way to return user-defined exception data to the client. Also, there is no standard mechanism in COM to specify the completion status of an invocation. In addition, it is not possible to predetermine what set of errors a COM interface might return. Although the set of success codes that can be returned from a COM operation must be fixed when the operation is defined, there is currently no machine-readable way to discover what the set of valid success codes are.

   COM exceptions have a straightforward mapping into CORBA. COM system error codes are mapped to the CORBA standard exceptions. COM user-defined error codes are mapped to CORBA user exceptions.

   COM system error codes are defined with the FACILITY_NULL and FACILITY_RPC facility codes. All FACILITY_NULL and FACILITY_RPC COM errors are mapped to CORBA standard exceptions. Table 18-10 lists the mapping from COM FACILITY_NULL exceptions to CORBA standard exceptions.

   Table 18-10Mapping from COM FACILITY_NULL Error Codes to CORBA Standard (System) Exceptions

COM CORBA
E_OUTOFMEMORY NO_MEMORY
E_INVALIDARG BAD_PARAM
E_NOTIMPL NO_IMPLEMENT
E_FAIL UNKNOWN
E_ACCESSDENIED NO_PERMISSION
E_UNEXPECTED UNKNOWN
E_ABORT UNKNOWN
E_POINTER BAD_PARAM
E_HANDLE BAD_PARAM

    Table 18-11 lists the mapping from COM FACILITY_RPC exceptions to CORBA standard exceptions. All FACILITY_RPC exceptions not listed in this table are mapped to the new CORBA standard exception COM.

   Table 18-11 Mapping from COM FACILITY_RPC Error Codes to CORBA Standard (System) Exceptions Table 18-11 Mapping from COM FACILITY_RPC Error Codes to CORBA Standard (System) Exceptions (Continued)

COM CORBA
RPC_E_CALL_CANCELED TRANSIENT
RPC_E_CANTPOST_INSENDCALL COMM_FAILURE
RPC_E_CANTCALLOUT_INEXTERNALCALL COMM_FAILURE
RPC_E_CONNECTION_TERMINATED NV_OBJREF

RPC_E_SERVER_DIED INV_OBJREF
RPC_E_SERVER_DIED_DNE INV_OBJREF
RPC_E_INVALID_DATAPACKET COMM_FAILURE
RPC_E_CANTTRANSMIT_CALL TRANSIENT
RPC_E_CLIENT_CANTMARSHAL_DATA MARSHAL
RPC_E_CLIENT_CANTUNMARSHAL_DATA MARSHAL
RPC_E_SERVER_CANTMARSHAL_DATA MARSHAL
RPC_E_SERVER_CANTUNMARSHAL_DATA MARSHAL
RPC_E_INVALID_DATA COMM_FAILURE
RPC_E_INVALID_PARAMETER BAD_PARAM
RPC_E_CANTCALLOUT_AGAIN COMM_FAILURE
RPC_E_SYS_CALL_FAILED NO_RESOURCES
RPC_E_OUT_OF_RESOURCES NO_RESOURCES
RPC_E_NOT_REGISTERED NO_IMPLEMENT
RPC_E_DISCONNECTED INV_OBJREF
RPC_E_RETRY TRANSIENT
RPC_E_SERVERCALL_REJECTED TRANSIENT
RPC_E_NOT_REGISTERED NO_IMPLEMENT

   COM SCODEs, other than those previously listed, are mapped into CORBA user exceptions and will require the use of the raises clause in OMG IDL. Since the OMG IDL mapping from the Microsoft IDL and ODL is likely to be generated, this is not a burden to the average programmer. The following OMG IDL illustrates such a user exception.

   // OMG IDL exception COM_ERROREX {

   long hresult;

   Any info; };

   The COM_ERROREX extension is designed to allow exposure of exceptions passed using the per-thread ErrorObject. The Any contained in the COM_ERROREX is defined to hold a CORBA object reference that supports the OMG IDL mapping for the IErrorInfo interface.

   18.3.10.3 Mapping of Nested Data Types

   Microsoft MIDL (and ODL) consider all definitions to be at global (or library) scope regardless of position in the file. This can lead to name collisions in datatypes across interfaces. Operations or types later in the file can refer to a datatype without fully qualifying the name even if the type is nested within another interface.

   For purposes of mapping MIDL/ODL to OMG IDL, we treat nested datatypes as if they had been prepended with the name of the scoping level. Thus:

   interface IA : IUnknown

   {typedef enum {ONE, TWO, THREE} Count;HRESULT f([in] Count val);

   }

   is mapped as if it were defined as:

   typedef enum {A_ONE, A_TWO, A_THREE} A_Count;interface IA : IUnknown{

   HRESULT f([in] A_Count val);}

   18.3.10.4 Mapping of Names

   Microsoft MIDL and ODL support prefixing types/names with leading underscores. When mapping from Microsoft MIDL or ODL to OMG IDL, the leading underscores are removed.

   Note – This simple rule is not sufficient to avoid all name collisions (such as MIDL types that clash with OMG IDL reserved names or situations where two operation names differ only in the leading underscore). However, this rule will cover many common cases and leads to a more natural mapping than prepending a character before the underscore.

   18.3.10.5 Mapping for Operations

   Operations defined for an interface are defined in Microsoft IDL and ODL within interface definitions. The definition of an operation constitutes the operations signature. An operation signature consists of the operation’s name, parameters (if any), and return value. Unlike OMG IDL, Microsoft IDL and ODL does not allow the operation definition to indicate the error information that can be returned.

   Microsoft IDL and ODL parameter directional attributes ([in], [out], [in, out]) map directly to OMG IDL (in, out, inout). Operation request parameters are represented as the values of [in] or [inout] parameters in Microsoft IDL, and operation response parameters are represented as the values of [inout] or [out] parameters. An operation return result can be any type that can be defined in Microsoft IDL/ODL, or void if a result is not returned. By convention, most operations are defined to return an HRESULT. This provides a consistent way to return operation status information.

   When Microsoft ODL methods are mapped to OMG IDL, they undergo the following transformations. First, if the last parameter is tagged with the Microsoft ODL keyword retval, that argument will be used as the return type of the operation. If the last parameter is not tagged with retval, then the signature is mapped directly to OMG IDL following the mapping rules for the data types of the arguments. Some example mappings from COM methods to OMG IDL operations are shown in the following code.

   // Microsoft ODL

   interface IFoo: IUnknown{HRESULT stringify( [in] VARIANT value,

   [out, retval] LPSTR * pszValue);

   HRESULT permute( [inout] short * value);

   HRESULT tryPermute([inout] short * value, [out] long newValue);

   };

   In OMG IDL this becomes:

   typedef long HRESULT;

   interface IFoo: CORBA::Composite, CosLifeCycle::LifeCycleObject { string stringify(in any value) raises (COM_ERROR),

   COM_ERROREX);HRESULT permute(inout short value);

   HRESULT tryPermute(inout short value, out long newValue) };

   18.3.10.6 Mapping for Properties

   In COM, only Microsoft ODL and OLE Type Libraries provide support for describing properties. Microsoft IDL does not support this capability. Any operations that can be determined to be either a put/set or get accessor are mapped to an attribute in OMG IDL. Because Microsoft IDL does not provide a means to indicate that something is a property, a mapping from Microsoft IDL to OMG IDL will not contain mappings to the attribute statement in OMG IDL.

   When mapping between Microsoft ODL or OLE Type Libraries, properties in COM are mapped in a similar fashion to that used to map attributes in OMG IDL to COM. For example, the following Microsoft ODL statements define the attribute Profile for the ICustomer interface and the read-only attribute Balance for the IAccount interface. The keywords [propput] and [propget] are used by Microsoft ODL to indicate that the statement is defining a property of an interface.

   // Microsoft ODL

   interface IAccount { [propget] HRESULT Balance([out, retval] float

   * pfBalance ); ... };

   interface ICustomer {

    [propget] HRESULT Profile([out] CustomerData * Profile); [propput] HRESULT Profile([in] CustomerData * Profile); };

   The definition of attributes in OMG IDL are restricted from raising any user-defined exceptions. Because of this, the implementation of an attribute’s accessor function is limited to raising system exceptions. The value of the HRESULT is determined by a mapping of the CORBA exception, if any, that was raised.