Previous | Table of Contents | Next |
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.