Previous Table of Contents Next


18.2.10 Interface Mapping


   18.2.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.

   CORBA identifies interfaces using the RepositoryId. The RepositoryId is a unique identifier for, among other things, an interface. 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 CORBA RepositoryId is mapped, bidirectionally, to the COM IID. The algorithm for creating the mapping is detailed in Section 17.5.4, “Mapping Interface Identity,? on page 17-16.

   18.2.10.2 Mapping for exception types

   The CORBA object model uses the concept of exceptions to report error information. Additional, exception-specification information may accompany the exception. The exception-specific information is a specialized form of a record. Because it is defined as a record, the additional information may consist of any of the basic data types or a complex data type constructed from one or more basic data types. Exceptions are classified into two types: System (Standard) Exceptions and User Exceptions.

   COM provides error information to clients only if an operation uses a return result of type HRESULT. A COM HRESULT with a value of zero indicates success. The HRESULT then can be converted into an SCODE (the SCODE is explicitly specified as being the same as the HRESULT on Win32 platforms). 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.

   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 based on the definition of the interface as specified in Microsoft IDL, ODL, or in a type library. Although the set of status 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 the set of valid codes.

   Since the CORBA exception model is significantly richer than the COM exception model, mapping CORBA exceptions to COM requires an additional protocol to be defined for COM. However, this protocol does not violate backwards compatibility, nor does it require any changes to COM. To return the User Exception data to a COM client, an optional parameter is added to the end of a COM operation signature when mapping CORBA operations, which raise User Exceptions. System exception information is returned in a standard OLE Error Object.

   Mapping for System Exceptions

   System exceptions are standard exception types, which are defined by the CORBA specification and are used by the Object Request Broker (ORB) and object adapters (OA). Standard exceptions may be returned as a result of any operation invocation, regardless of the interface on which the requested operation was attempted.

   There are two aspects to the mapping of System Exceptions. One aspect is generating an appropriate HRESULT for the operation to return. The other aspect is conveying System Exception information via a standard OLE Error Object.

   The following table shows the HRESULT, which must be returned by the COM View when a CORBA System Exception is raised. Each of the CORBA System Exceptions is assigned a 16-bit numerical ID starting at 0x200 to be used as the code (lower 16 bits) of the HRESULT. Because these errors are interface-specific, the COM facility code FACILITY_ITF is used as the facility code in the HRESULT.

   Bits 12-13 of the HRESULT contain a bit mask, which indicates the completion status of the CORBA request. The bit value 00 indicates that the operation did not complete, a bit value of 01 indicates that the operation did complete, and a bit value of 02 indicates that the operation may have completed. Table 18-3 lists the HRESULT constants and their values.

   Table 18-3 Standard Exception to SCODE Mapping

HRESULT Constant HRESULT Value
ITF_E_UNKNOWN_NO 0x40200
ITF_E_UNKNOWN_YES 0x41200
ITF_E_UNKNOWN_MAYBE 0x42200
ITF_E_BAD_PARAM_NO 0x40201
ITF_E_BAD_PARAM_YES 0x41201
ITF_E_BAD_PARAM_MAYBE 0x42201
ITF_E_NO_MEMORY_NO 0x40202
ITF_E_NO_MEMORY_YES 0x41202
ITF_E_NO_MEMORY_MAYBE 0x42202
ITF_E_IMP_LIMIT_NO 0x40203

   Table 18-3 Standard Exception to SCODE Mapping (Continued) Table 18-3 Standard Exception to SCODE Mapping (Continued) Table 18-3 Standard Exception to SCODE Mapping (Continued)

ITF_E_IMP_LIMIT_YES 0x41203
ITF_E_IMP_LIMIT_MAYBE 0x42203
ITF_E_COMM_FAILURE_NO 0x40204
ITF_E_COMM_FAILURE_YES 0x41204
ITF_E_COMM_FAILURE_MAYBE 0x42204
ITF_E_INV_OBJREF_NO 0x40205
ITF_E_INV_OBJREF_YES 0x41205
ITF_E_INV_OBJREF_MAYBE 0x42205
ITF_E_NO_PERMISSION_NO 0x40206
ITF_E_NO_PERMISSION_YES 0x41206
ITF_E_NO_PERMISSION_MAYBE 0x42206
ITF_E_INTERNAL_NO 0x40207
ITF_E_INTERNAL_YES 0x41207
ITF_E_INTERNAL_MAYBE 0x42207
ITF_E_MARSHAL_NO 0x40208
ITF_E_MARSHAL_YES 0x41208
ITF_E_MARSHAL_MAYBE 0x42208
ITF_E_INITIALIZE_NO 0x40209
ITF_E_INITIALIZE_YES 0x41209
ITF_E_INITIALIZE_MAYBE 0x42209
ITF_E_NO_IMPLEMENT_NO 0x4020A
ITF_E_NO_IMPLEMENT_YES 0x4120A
ITF_E_NO_IMPLEMENT_MAYBE 0x4220A
ITF_E_BAD_TYPECODE_NO 0x4020B
ITF_E_BAD_TYPECODE_YES 0x4120B
ITF_E_BAD_TYPECODE_MAYBE 0x4220B
ITF_E_BAD_OPERATION_NO 0x4020C
ITF_E_BAD_OPERATION_YES 0x4120C
ITF_E_BAD_OPERATION_MAYBE 0x4220C

ITF_E_NO_RESOURCES_NO 0x4020D
ITF_E_NO_RESOURCES_YES 0x4120D
ITF_E_NO_RESOURCES_MAYBE 0x4220D
ITF_E_NO_RESPONSE_NO 0x4020E
ITF_E_NO_RESPONSE_YES 0x4120E
ITF_E_NO_RESPONSE_MAYBE 0x4220E
ITF_E_PERSIST_STORE_NO 0x4020F
ITF_E_PERSIST_STORE_YES 0x4120F
ITF_E_PERSIST_STORE_MAYBE 0x4220F
ITF_E_BAD_INV_ORDER_NO 0x40210
ITF_E_BAD_INV_ORDER_YES 0x41210
ITF_E_BAD_INV_ORDER_MAYBE 0x42210
ITF_E_TRANSIENT_NO 0x40211
ITF_E_TRANSIENT_YES 0x41211
ITF_E_TRANSIENT_MAYBE 0x42211
ITF_E_FREE_MEM_NO 0x40212
ITF_E_FREE_MEM_YES 0x41212
ITF_E_FREE_MEM_MAYBE 0x42212
ITF_E_INV_IDENT_NO 0x40213
ITF_E_INV_IDENT_YES 0x41213
ITF_E_INV_IDENT_MAYBE 0x42213
ITF_E_INV_FLAG_NO 0x40214
ITF_E_INV_FLAG_YES 0x41214
ITF_E_INV_FLAG_MAYBE 0x42214
ITF_E_INTF_REPOS_NO 0x40215
ITF_E_INTF_REPOS_YES 0x41215
ITF_E_INTF_REPOS_MAYBE 0x42215
ITF_E_BAD_CONTEXT_NO 0x40216
ITF_E_BAD_CONTEXT_YES 0x41216

ITF_E_BAD_CONTEXT_MAYBE 0x42216
ITF_E_OBJ_ADAPTER_NO 0x40217
ITF_E_OBJ_ADAPTER_YES 0x41217
ITF_E_OBJ_ADAPTER_MAYBE 0x42217
ITF_E_DATA_CONVERSION_NO 0x40218
ITF_E_DATA_CONVERSION_YES 0x41218
ITF_E_DATA_CONVERSION_MAYBE 0x42218
ITF_E_OBJ_NOT_EXIST_NO 0X40219
ITF_E_OBJ_NOT_EXIST_MAYBE 0X41219
ITF_E_OBJ_NOT_EXIST_YES 0X42219
ITF_E_TRANSACTION_REQUIRED_NO 0x40220
ITF_E_TRANSACTION_REQUIRED_MAYBE 0x41220
ITF_E_TRANSACTION_REQUIRED_YES 0x42220
ITF_E_TRANSACTION_ROLLEDBACK_NO 0x40221
ITF_E_TRANSACTION_ROLLEDBACK_MAYBE 0x41221
ITF_E_TRANSACTION_ROLLEDBACK_YES 0x42221
ITF_E_INVALID_TRANSACTION_NO 0x40222
ITF_E_INVALID_TRANSACTION_MAYBE 0x41222
ITF_E_INVALID_TRANSACTION_YES 0x42222

   It is not possible to map a System Exception’s minor code and RepositoryId into the HRESULT. Therefore, OLE Error Objects may be used to convey these data. Writing the exception information to an OLE Error Object is optional. However, if the Error Object is used for this purpose, it must be done according to the following specifications.

    The properties of the OLE Error Object must be set according to Table 18-4. Table 18-4 Error Object Usage for CORBA System Exceptions

Property Description
bstrSource <interface name>.<operation name> where the interface and operation names are those of the CORBA interface that this Automation View is representing.
bstrDescription CORBA System Exception: [<exception repository id>] minor code [<minor code>][<completion status>] where the <exception repository id> and <minor code> are those of the CORBA system exception. <completion status> is “YES,? “NO,? or “MAYBE? based upon the value of the system exception’s CORBA completion status. Spaces and square brackets are literals and must be included in the string.
bstrHelpFile Unspecified
dwHelpContext Unspecified
GUID The IID of the COM View Interface

   A COM View supporting error objects would have code, which approximates the following C++ example.

   SetErrorInfo(OL,NULL); // Initialize the thread-local error objecttry {

   // Call the CORBA operation}catch(...) {

   ...

   CreateErrorInfo(&pICreateErrorInfo);pICreateErrorInfo->SetSource(...);pICreateErrorInfo->SetDescription(...); pICreateErrorInfo->SetGUID(...);pICreateErrorInfo ->QueryInterface(IID_IErrorInfo,&pIErrorInfo);pICreateErrorInfo->SetErrorInfo(OL,pIErrorInfo);pIErrorInfo->Release();pICreateErrorInfo->Release();

   ...}

   A client to a COM View would access the OLE Error Object with code approximating the following.

   // After obtaining a pointer to an interface on// the COM View, the // client does the following one time

   pIMyMappedInterface->QueryInterface(IID_ISupportErrorInfo,&pISupportErrorInfo);

   hr = pISupportErrorInfo

   ->InterfaceSupportsError-Info(IID_MyMappedInterface);BOOL bSupportsErrorInfo = (hr == NOERROR ? TRUE : FALSE);...// Call to the COM operation...HRESULT hrOperation = pIMyMappedInterface->...

   if (bSupportsErrorInfo){

   HRESULT hr = GetErrorInfo(O,&pIErrorInfo);

   // S_FALSE means that error data is not available,

   NO_ERROR

   // means it is

   if (hr == NO_ERROR)

   {

   pIErrorInfo->GetSource(...);

   // Has repository id & minor code. hrOperation (above)

   // has the completion status encoded into it.

   pIErrorInfo->GetDescription(...);

   }}

   Mapping for User Exception Types

   User exceptions are defined by users in OMG IDL and used by the methods in an object server to report operation-specific errors. The definition of a User Exception is identified in an OMG IDL file with the keyword exception. The body of a User Exception is described using the syntax for describing a structure in OMG IDL.

   When CORBA User Exceptions are mapped into COM, a structure is used to describe various information about the exception — hereafter called an Exception structure. The structure contains members, which indicate the type of the CORBA exception, the identifier of the exception definition in a CORBA Interface Repository, and interface pointers to User Exceptions. If an interface raises a user exception, a structure is constructed whose name is the interface name [fully scoped] followed by “Exceptions.? For example, if an operation in MyModule::MyInterface raises a user exception, then there will be a structure created named MyModule_MyInterfaceExceptions.

   A template illustrating this naming convention is as follows.

   // Microsoft IDL and ODLtypedef enum { NO_EXCEPTION, USER_EXCEPTION} ExceptionType;

   typedef struct

   {ExceptionType type;LPTSTR repositoryId;I<ModuleName_InterfaceName>UserException

   *....piUserException;

   } <ModuleName_InterfaceName>Exceptions;

   The Exceptions structure is specified as an output parameter, which appears as the last parameter of any operation mapped from OMG IDL to Microsoft IDL, which raises a User Exception. The Exceptions structure is always passed by indirect reference. Because of the memory management rules of COM, passing the Exceptions structure as an output parameter by indirect reference allows the parameter to be treated as optional by the callee1. The following example illustrates this point.

   // Microsoft IDL

interface IBANKAccount

{

HRESULT Withdraw(

};

[in] float fAmount,
[out] float pfNewBalance,
[out] BANk_AccountExceptions
** pException);

   The caller can indicate that no exception information should be returned, if an exception occurs, by specifying NULL as the value for the Exceptions parameter of the operation. If the caller expects to receive exception information, it must pass the address of a pointer to the memory in which the exception information is to be placed. COM’s memory management rules state that it is the responsibility of the caller to release this memory when it is no longer required.

   If the caller provides a non-NULL value for the Exceptions parameter and the callee is to return exception information, the callee is responsible for allocating any memory used to hold the exception information being returned. If no exception is to be returned, the callee need do nothing with the parameter value.

   If a CORBA exception is not raised, then S_OK must be returned as the value of the HRESULT to the callee, indicating the operation succeeded. The value of the HRESULT returned to the callee when a CORBA exception has been raised depends upon the type of exception being raised and whether an Exception structure was specified by the caller.

   1. Vendors that map the MIDL definition directly to C++ should map the exception struct parameter as defaulting to a NULL pointer.

   The following OMG IDL statements show the definition of the format used to represent User Exceptions.

   // OMG IDL

   module BANK { ... exception InsufFunds { float balance }; exception InvalidAmount { float amount }; ... interface Account

   {exception NotAuthorized { };float Deposit( in float Amount )

   raises( InvalidAmount );float Withdraw( in float Amount )raises( InvalidAmount, NotAuthorized );};};

   and map to the following statements in Microsoft IDL and ODL.

   // Microsoft IDL and ODL

   struct Bank_InsufFunds{float balance;};

   struct Bank_InvalidAmount{float amount;};

   struct BANK_Account_NotAuthorized{};

   interface IBANK_AccountUserExceptions : IUnknown{HRESULT _get_InsufFunds( [out] BANK_InsufFunds

   * exceptionBody );HRESULT _get_InvalidAmount( [out] BANK_InvalidAmount* exceptionBody );

   HRESULT _get_NotAuthorized( [out]BANK_Account_NotAuthorized

   * exceptionBody );

   };

   typedef struct{

   ExceptionType type;

   LPTSTR repositoryId;

   IBANK_AccountUserExceptions * piUserException;

   } BANK_AccountExceptions;

   User exceptions are mapped to a COM interface and a structure that describes the body of information to be returned for the User Exception. A COM interface is defined for each CORBA interface containing an operation that raises a User Exception. The name of the interface defined for accessing User Exception information is constructed from the fully scoped name of the CORBA interface on which the exception is raised. A structure is defined for each User Exception, which contains the body of information to be returned as part of that exception. The name of the structure follows the naming conventions used to map CORBA structure definitions.

   Each User Exception that can be raised by an operation defined for a CORBA interface is mapped into an operation on the Exception interface. The name of the operation is constructed by prefixing the name of the exception with the string “_get_?. Each accessor operation defined takes one output parameter in which to return the body of information defined for the User Exception. The data type of the output parameter is a structure that is defined for the exception. The operation is defined to return an HRESULT value.

   If a CORBA User Exception is to be raised, the value of the HRESULT returned to the caller is E_FAIL.

   If the caller specified a non-NULL value for the Exceptions structure parameter, the callee must allocate the memory to hold the exception information and fill in the Exceptions structure as in Table 18-5.

   Table 18-5 User Exceptions Structure

Member

Description

type Indicates the type of CORBA exception that is being raised. Must be USER_EXCEPTION.
repositoryId Indicates the repository identifier for the exception definition.
piUserException Points to an interface with which to obtain information about the User Exception raised.

   When data conversion errors occur while mapping the data types between object models (during a call from a COM client to a CORBA server), an HRESULT with the code E_DATA_CONVERSION and the facility value FACILITY_NULL is returned to the client.

   Mapping User Exceptions: A Special Case

   If a CORBA operation raises only one (COM_ERROR or COM_ERROREX) user exception (defined under Section 18.3.10.2, “Mapping for COM Errors,? on page 18-44), then the mapped COM operation should not have the additional parameter for exceptions. This proviso enables a CORBA implementation of a preexisting COM interface to be mapped back to COM without altering the COM operation’s original signature.

   COM_ERROR (and COM_ERROREX) is defined as part of the CORBA to COM mapping. However, this special rule in effect means that a COM_ERROR raises clause can be added to an operation specifically to indicate that the operation was originally defined as a COM operation.

   18.2.10.3 Mapping for Nested Types

   OMG IDL and Microsoft MIDL/ODL do not agree on the scoping level of types declared within interfaces. Microsoft, for example, considers all types in a MIDL or ODL file to be declared at global scope. OMG IDL considers a type to be scoped within its enclosing module or interface. This means that to prevent accidental name collisions, types declared within OMG IDL modules and OMG IDL interfaces must be fully qualified in Microsoft IDL or ODL.

   The OMG IDL construct:

   Module BANK{

   interface ATM {enum type {CHECKS, CASH};Struct DepositRecord {

   string account;float amount;type kind;

   }; void deposit (in DepositRecord val); };

   Must be mapped in Microsoft MIDL as:

   [uuid(...), object]interface IBANK ATM : IUnknown {

   typedef [v1 enum] enum{BANK ATM CHECKS,BANK ATM CASH} BANK ATM type;

   typedef struct {LPSTR account;BANK ATM type kind;

   } BANK ATM DepositRecord;HRESULT deposit (in BANK ATM DepositRecord *val);};

   and to Microsoft ODL as:

   [uuid(...)]library BANK {...[uuid(...), object]

   interface IBANK ATM : IUnknown {typedef enum { BANK ATM CHECKS, {BANK ATM CASH} BANK ATM type;

   typedef struct {LPSTR struct;float amount;BANK ATM type kind;

   } BANK ATM DepositRecord;HRESULT deposit (in BANK ATM DepositRecord *val);};

   18.2.10.4 Mapping for Operations

   Operations defined for an interface are defined in OMG IDL 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. Optionally, OMG IDL allows the operation definition to indicate exceptions that can be raised, and the context to be passed to the object as implicit arguments, both of which are considered part of the operation.

   OMG IDL parameter directional attributes in, out, inout map directly to Microsoft IDL and ODL parameter direction attributes [in], [out], [in,out]. Operation request parameters are represented as the values of in or inout parameters in OMG 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 OMG IDL, or void if a result is not returned.

   The OMG IDL sample (shown below) illustrates the definition of two operations on the Bank interface. The names of the operations are bolded to make them stand out. Operations can return various types of data as results, including nothing at all. The operation Bank::Transfer is an example of an operation that does not return a value. The operation Bank::Open Account returns an object as a result of the operation.

   // OMG IDL

   #pragma ID::BANK::Bank?IDL:BANK/Bank:1,2? interface Bank { Account OpenAccount( in float StartingBalance,

   in AccountTypes Account(Type);

   void Transfer( in Account Account1, in Account Account2, in float Account) raises(InSufFunds);

   };

   The operations defined in the preceding OMG IDL code are mapped to the following lines of Microsoft IDL code:

   // Microsoft IDL[ object, uuid(682d22fb-78ac-0000-0c03-4d0000000000), pointer_default(unique) ]

   interface IBANK Teller: IUnknown

{

HRESULT

HRESULT

};

OpenAccount(
[in] float StartingBalance,
[in] BANK_AccountTypes AccountType,
[out] IBANK_Account ** ppiNewAccount );
Transfer(
[in] IBANK_Account * Account1,
[in] IBANK_Account * Account2,
[in] float Amount,
[out] BANK_TellerExceptions
** ppException);

   and to the following statements in Microsoft ODL

   // Microsoft ODL[ uuid(682d22fb-78ac-0000-0c03-4d0000000000) odl ]interface IBANK_Teller: IUnknown

    {

    HRESULT OpenAccount(

   [in] float StartingBalance,

   [in] BANK_AccountTypes AccountType,

   [out, retval] IBANK_Account

   ** ppiNewAccount ); HRESULT Transfer( [in] IBANK_Account * Account1,[in] IBANK_Account * Account2,[in] float Amount,[out]BANK_TellerExceptions

   ** ppException); };

   The ordering and names of parameters in the Microsoft IDL and ODL mapping is identical to the order in which parameters are specified in the text of the operation definition in OMG IDL. The COM mapping of all CORBA operations must obey the COM memory ownership and allocation rules specified.

   It is important to note that the signature of the operation as written in OMG IDL is different from the signature of the same operation in Microsoft IDL or ODL. In particular, the result value returned by an operation defined in OMG IDL will be mapped as an output argument at the end of the signature when specified in Microsoft IDL or ODL. This allows the signature of the operation to be natural to the COM developer. When a result value is mapped as an output argument, the result value becomes an HRESULT. Without an HRESULT return value, there would be no way for COM to signal errors to clients when the client and server are not collocated. The value of the HRESULT is determined based on a mapping of the CORBA exception, if any, that was raised.

   It is also important to note that if any user’s exception information is defined for the operation, an additional parameter is added as the last argument of the operation signature. The user exception parameter follows the return value parameter, if both exist. See Section 18.2.10.2, “Mapping for exception types,? on page 18-11 for further details.

   18.2.10.5 Mapping for Oneway Operations

   OMG IDL allows an operation’s definition to indicate the invocation semantics the communication service must provide for an operation. This indication is done through the use of an operation attribute. Currently, the only operation attribute defined by CORBA is the oneway attribute.

   The oneway attribute specifies that the invocation semantics are best-effort, which does not guarantee delivery of the request. Best-effort implies that the operation will be invoked, at most, once. Along with the invocation semantics, the use of the oneway operation attribute restricts an operation from having output parameters, must have no result value returned, and cannot raise any user-defined exceptions.

   It may seem that the Microsoft IDL maybe operation attribute provides a closer match since the caller of an operation does not expect any response. However, Microsoft RPC maybe does not guarantee at most once semantics, and therefore is not sufficient. Because of this, the mapping of an operation defined in OMG IDL with the oneway operation attribute maps the same as an operation that has no output arguments.

   18.2.10.6 Mapping for Attributes

   OMG IDL allows the definition of attributes for an interface. Attributes are essentially a short-hand for a pair of accessor functions to an object’s data; one to retrieve the value and possibly one to set the value of the attribute. The definition of an attribute must be contained within an interface definition and can indicate whether the value of the attribute can be modified or just read. In the example OMG IDL next, the attribute Profile is defined for the Customer interface and the read-only attribute is Balance-defined for the Account interface. The keyword attribute is used by OMG IDL to indicate that the statement is defining an attribute of an interface.

   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 only raising system exceptions. The value of the HRESULT is determined based on a mapping of the CORBA exception, if any, that was raised.

   // OMG IDL

   struct CustomerData{CustomerId Id;string Name;string SurName;};

   #pragma ID::BANK::Account "IDL:BANK/Account:3.1"

   interface Account

   {

   readonly attribute float Balance;

   float Deposit(in float amount) raises(InvalidAmount);

   float Withdrawal(in float amount) raises(InsufFunds, InvalidAmount);

   float Close( );

   };

   #pragma ID::BANK::Customer "IDL:BANK/Customer:1.2"

   interface Customer

    {

    attribute CustomerData Profile;

    };

   When mapping attribute statements in OMG IDL to Microsoft IDL or ODL, the name of the get accessor is the same as the name of the attribute prefixed with _get_ in Microsoft IDL and contains the operation attribute [propget] in Microsoft ODL. The name of the put accessor is the same as the name of the attribute prefixed with _put_ in Microsoft IDL and contains the operation attribute [propput] in Microsoft ODL.

   Mapping for Read-Write Attributes

   In OMG IDL, attributes are defined as supporting a pair of accessor functions: one to retrieve the value and one to set the value of the attribute, unless the keyword readonly precedes the attribute keyword. In the preceding example, the attribute Profile is mapped to the following statements in Microsoft IDL.

   // Microsoft IDL[ object, uuid(682d22fb-78ac-0000-0c03-4d0000000000), pointer_default(unique) ]interface ICustomer : IUnknown

{

HRESULT

HRESULT

};

_get_Profile( [out] CustomerData * Profile );
_put_Profile( [in] CustomerData * Profile );

   Profile is mapped to these statements in Microsoft ODL.

   // Microsoft ODL[ uuid(682d22fb-78ac-0000-0c03-4d0000000000) ]interface IBANK_Customer : IUnknown

    { [propget] HRESULT Profile( [out] BANK_CustomerData * val); [propput] HRESULT Profile( [in] BANK_CustomerData * val); };

   Note – The attribute is actually mapped as two different operations in both Microsoft IDL and ODL. The IBANK_Customer::get_profile operation (in Microsoft IDL) and the [propget] Profile operation ( in Microsoft ODL) are used to retrieve the value of the attribute. The IBANK_Customer::put_profile operation is used to set the value of the attribute.

   Mapping for Read-Only Attributes

   In OMG IDL, an attribute preceded by the keyword readonly is interpreted as only supporting a single accessor function used to retrieve the value of the attribute. In the previous example, the mapping of the attribute Balance is mapped to the following statements in Microsoft IDL.

   // Microsoft IDL[ object, uuid(682d22fb-78ac-0000-0c03-4d0000000000) ]interface IAccount: IUnknown

    { HRESULT _get_Balance([out] float Balance); };

   and the following statements in Microsoft ODL.

   // Microsoft ODL[ uuid(682d22fb-78ac-0000-0c03-4d0000000000) ]interface IAccount: IUnknown

    { [propget] HRESULT Balance([out] float *val); };

   Note that only a single operation was defined since the attribute was defined to be read-only.

   18.2.10.7 Indirection Levels for Operation Parameters

   • optional parameters are passed using double indirection (e.g., IntfException ** val).