7.13.1. Interface Definition Language

The interface definition language of DCOM is called MIDL (Microsoft Interface Definition Language). The language is based on the interface definition language of DCE and syntactically resembles C++ where additional attributes are used to provide the necessary information for generating stubs.

Figure 7.4. MIDL Interface Definition Example

[object, uuid(12345678-9ABC-DEF0-1234-56789ABCDEF0), ]
interface ISomething : IUnknown
{
  typedef unsigned char BUFFER [1234];
  HRESULT MethodOne ([in] short InOne,
                     [out] long *pOutOne,
                     [in, out] BUFFER *pBuffer);
};

7.13.1.1. Interface And Component Attributes

The language defines interfaces as collections of data types and function prototypes. The description of an interface contains attributes that are valid for the entire interface. Some of the attributes are:

  • auto_handle - automatically bind functions that have no explicit binding

  • endpoint - the default protocol and address to be used by the server

  • local - an indication of a local rather than a remote interface

  • object - an indication of a COM rather than an RPC interface

  • uuid - a universally unique identifier used to distinguish the interface

  • version - a major and a minor version number of the interface, only for RPC interfaces

An RPC interface describes an arbitrary interface. A COM interface describes a component interface. Unlike an RPC interface, a COM interface has to inherit, directly or indirectly, from either the IUnknown or the IDispatch interface, and must have the uuid attribute.

The language can define components that group together multiple interfaces. The description of a component contains attributes that are valid for the entire component. Some of the attributes are:

  • aggregatable - indicates that the component supports aggregation

  • appobject - marks the component as a complete application

  • control - marks the component as a user interface component

  • hidden - marks the component as a hidden component

7.13.1.2. Type Attributes

  • allocate - adjusts how memory for a type is allocated and freed

  • context_handle - type contains server side context that is not accessed by client side

  • decode - functions for deserialization are made accessible to the programmer

  • encode - functions for serialization are made accessible to the programmer

  • ignore - ignore the target of the associated pointer when marshalling

  • represent_as - instructs certain wire type to be presented as certain local type, the programmer must supply conversion functions

  • transmit_as - instructs certain local type to be transported as certain wire type, the programmer must supply conversion functions

  • user_marshal - use marshalling functions supplied by the programmer for certain local type

  • wire_marshal - use marshalling functions supplied by the programmer for certain wire type

When the server needs to keep a context between the calls that is not accessed by the client, it can use the context_handle attribute to define a context type. The value of the context type is kept on the server, only a reference to the value is transported over the network to the client.

7.13.1.3. Function Attributes

  • async - generate client stub for asynchronous call with asynchronous call handle as first argument

  • bindable - function is an accessor function for which change notification is provided

  • broadcast - function call should be delivered to all available servers

  • call_as - specifies simplified remote function to be used in place of complex local function

  • callback - function exists on the client and can be called by the server within context of remote call

  • idempotent - function will have the same effect if executed multiple times

  • immediatebind - function is an accessor function for which changes should be made persistent immediately

  • maybe - function does not need to be executed reliably

  • message - call should be delivered as asynchronous message

  • notify - generate server stub that calls notification procedure in case of marshalling failure

  • propget - the function is a getter accessor function for a property

  • propput - the function is a setter accessor function for a property

  • usesgetlasterror - the function signals error code using SetLastError and GetLastError

For a local function with complex arguments, a remote function with simple arguments can be specified using the call_as attribute. The marshalling code is only generated for the simple function, the programmer must provide a pair of helper functions that convert the complex function call to the simple function call on the client side and vice versa on the server side.

7.13.1.4. Argument Attributes

  • in - the argument is passed from client to server

  • out - the argument is passed from server to client

  • optional - the argument is optional

  • readonly - the argument cannot be assigned to

  • partial_ignore - when passing pointer from client to server, only transport information on wheter it is NULL

  • defaultvalue - specifies a default value for an optional argument

  • retval - the argument will hold the return value of the function

  • ptr - the argument is a full pointer, which can be NULL and have aliases

  • ref - the argument is a reference pointer, which cannot be NULL and cannot have aliases

  • unique - the argument is a unique pointer, which can be NULL but cannot have aliases

  • force_allocate - the argument will always be allocated dynamically

  • byte_count - specifies a variable which holds size of referenced data

  • first_is - specifies index of first array item to be transported

  • last_is - specifies index of last array item to be transported

  • length_is - specifies length of array to be transported

  • switch_is - specifies discriminant of a union

  • pipe - the argument represents a stream opened between the client and the server

  • comm_status - the argument will hold failure code on communication error

  • fault_status - the argument will hold failure code on server error

Pointers of three types are distinguished. The ref attribute denotes a pointer that cannot be NULL and cannot be aliased by having another pointer point to the same data. The value of the pointer does not change, only the data the pointer points to can be overwritten. The unique attribute denotes a pointer that can be NULL but cannot be aliased. The value of the pointer can change and the data the pointer points to can be overwritten. The ptr attribute denotes a pointer that can be NULL and can be aliased. The value of the pointer can change and the data the pointer points to can be overwritten.

Pointers annotated with partial_ignore are useful when a function expects a pointer argument that can be either NULL or point to uninitialized memory to be filled with data. When the client supplies a NULL pointer, the server receives a NULL pointer. When the client supplies a pointer to uninitialized memory, the server allocates zero filled memory to be filled with data before invoking the function and returns its content after invoking the function.

Arguments defined as pipe represent a stream opened between the client and the server within the context of the remote call. The client supplies a pull function for an input pipe, a push function for an output pipe, and an allocation function. The server can use the server stub to invoke the supplied functions on the client to pull or push data.