Using OLE Automation Marshaler for 16/16 & 16/32 COM Interface

ID: Q139072

2.0 WINDOWS WINDOWS NT kbinterop kbref

The information in this article applies to:

SUMMARY

Standard marshaling code for custom COM interfaces, generated by using the MIDL compiler or written manually, doesn't support 16-bit to 16-bit or 16-bit to 32-bit interoperability in Windows 95 and in Windows NT version 3.51.

The OLE Automation marshaler, however, does supports 16-bit to 16-bit and 16-bit to 32-bit custom interface interoperability for local servers (.exe servers), so you can use the OLE Automation marshaler if you are interested in 16-bit support. However the types that can be used in interfaces that can be marshaled by the OLE Automation marshaler are restricted to the OLE Automation compatible types

MORE INFORMATION

A COM interface can be marshaled using standard marshaling or custom marshaling. In standard marshaling, proxy and stub code marshals and unmarshals the parameters and return values of an interface method call between processes. In custom marshaling, the object implements IMarshal to marshal the entire object to another process space.

The MIDL compiler can be used to generate proxy and stub code to marshal a COM interface. See the "Designing COM Interfaces" and "CPP to COM" MSDN articles for more information on marshaling interfaces using MIDL. See "The COM Specification" and Chapter 6 of "Inside OLE 2nd Edition" for further information on custom marshaling.

Information about writing 16-bit standard marshaling code for custom interfaces under Windows 95 and Windows NT 3.51 is not available at this time. This prevents the writing or generation of standard marshalling code to support 16-bit to 16-bit local server or 16-bit to 32-bit local server custom interface interoperability on these platforms. See "Interoperability Using Custom Interfaces (either MIDL or Manually Written Marshaling)" in the Win32 SDK online documentation for a description of this limitation.

NOTE: 16-bit to 32-bit in-process server interoperablilty using any COM interface including standard OLE interfaces, is not supported and will not be supported in the future. Information about writing 16-bit standard marshaling code for custom interfaces on Windows 3.x is available; please see the PSSAMP sample and \Docs\Remoting.doc in the 16-bit OLE SDK. Note, however, that this standard marshaling code will not work under Windows 95 or Window NT 3.51.

If you are interested in 16-bit to 16-bit local server or 16-bit to 32-bit local server custom interface interoperability under Windows 95 or Windows NT 3.51, consider using custom marshaling or the standard marshaling implemented by OLE automation's marshaler.

Using Custom Marshaling

You can use custom marshaling to marshal the server object that implements the custom interface. Custom marshaling also requires that the server implement IMarshal. OLE will use IMarshal::MarshalInterface to marshal the custom interface and will use IMarshal::GetUnMarshalClass to obtain the CLSID of the unmarshaller object. The unmarshaller must be registered in the system registry. A 16-bit and a 32-bit implementation of the

unmarshaler object must be provided if you are interested in   16-bit to 32-
bit interoperability. The InprocServer entry under the CLSID of the unmarshaler object in the registry should point to the 16-bit implementation and the InprocServer32 entry should point to the 32-bit implementation. OLE will create an instance of the unmarshaler object in the process space of the client and will use its IMarshal::UnMarshalInterface to unmarshal the entire object in the client's process space. Consequently custom marshaling is appropriate for objects whose state doesn't change or whose state is kept in shared memory. It may not be appropriate for all objects.

Using OLE Automation's Marshaler

You can use standard marshaling as implemented by OLE automation's marshaler. The OLE automation marshaler provides 16-bit and 32-bit standard marshaling code that can run under Windows 95 and Windows NT 3.51. It is generic enough to marshal any custom interface that is described using a type library and that uses a limited set of data types called the OLE Automation compatible types. This will allow 16-bit to 16-bit local server and 16-bit to 32-bit local server interoperability of the custom interface under both Windows 95 and Windows NT 3.51.

This marshaler implements OLE Automation's vtbl-binding. Vtbl-binding is the mechanism used by any COM interface client to bind to the implementation of the COM interface in the server. OLE Automation uses this term to distinguish it from the other binding mechanisms it supports, such as late-binding and id-binding.

The types that can be used in interfaces that can be marshaled by the OLE Automation marshaler are restricted to the OLE Automation compatible types discussed below. In addition, because the OLE Automation marshaler is generic, it is not as efficient as the marshaling code generated by MIDL. Because of these limitations, you should consider this approach only if you are interested in 16-bit to 16-bit or 16-bit to 32-bit interoperabilty. Otherwise, use the MIDL compiler to generate marshaling code.

Important Implementation Details

For documentation and a sample tha shows how to create a custom interface that is marshaled by OLE Automation's marshaler, please see the following article in the Microsoft Knowledge Base:

   ARTICLE-ID: Q139074
   TITLE     : SAMPLE: VTBLBIND: Marshaling Using an OLE Automation
               Marshaler

The server describes the custom interface in the Object Description Language (ODL) in Server.odl. Server.odl is compiled by mktyplib to produce the type library Server.tlb and the interface declaration file IVtblSrv.h.

For example, the IVtblServer custom interface is described as follows:

   [
      uuid(2ED17402-F80F-11ce-8161-00AA0060D733),      // ID_IVtblServer
      oleautomation
    ]
    interface IVtblServer : IUnknown
    {
        HRESULT put_Message([in] BSTR Message);
        HRESULT get_Message([out] BSTR *pMessage);
        HRESULT DisplayMessage([in] SAFEARRAY(unsigned char) Coordinate,
                               [in] short Times);
    }

The IVtblServer custom interface derives from IUnknown and has three methods. The uuid attribute specifies the Interface ID of the interface. The oleautomation attribute specifies that the interface can be marshaled by the marshaler provided by OLE Automation.

The ODL syntax is described in Chapter 7 of OLE Programmer's Reference Volume 2, second edition. Information on how to obtain the second edition of this book can be found in the following article in the Microsoft Knowledge Base:

   ARTICLE-ID: Q124385
   TITLE     : SAMPLE: OLE Automation '94 Documentation and Samples

The types that can be used by the custom interface are restricted to the following OLE Automation compatible types:

   short
   16-bit signed integer.
   
   long
   32-bit signed integer.
   
   float
   32-bit IEEE floating-point number.
   
   double
   64-bit IEEE floating-point number.
   
   CURRENCY
   8-byte fixed-point number.
   
   DATE
   64-bit floating-point fractional number of days since December 30, 1899.
   
   BSTR
   Length-prefixed string. Strings must be passed using this type. BSTRs
   must be created and manipulated using the functions described in OLE
   Programmer's Reference, Vol. 2.
   
   boolean
   Data item that can have the values True or False. The size maps to
   VARIANT_BOOL.
   
   VARIANT
   VARIANT type. This VARIANT can contain any type marked with a [V] in the
   VARENUM enumeration in Oaidl.h. VARIANTs that contain other types cannot
   be marshaled by OLE Automation.
   
   SCODE
   OLE scode.
   
   unsigned char
   Unsigned 8-bit data item. A SAFEARRAY(unsigned char) can be used to pass
   binary data.
   
   IUnknown*
   IUnknown interface pointer. Any OLE interface can be passed using this
   type.
   
   IDispatch*
   IDispatch interface pointer.
   
   SAFEARRAY(type)
   Array of type, which can be any of the previously-listed types but
   cannot be any of the following types. Safearrays must be created and
   manipulated using the Safearray functions described in OLE Programmer's
   Reference, Vol. 2.
   
   short*
   pointer to a short. Can be used to pass a short by reference.
   
   long*
   pointer to a long. Can be used to pass a long by reference.
   
   float*
   pointer to a float. Can be used to pass a float by reference.
   
   double*
   pointer to a double. Can be used to pass a double by reference.
   
   CURRENCY*
   pointer to a CURRENCY. Can be used to pass a CURRENCY by reference.
   
   DATE*
   pointer to a DATE. Can be used to pass a DATE by reference.
   
   BSTR*
   pointer to a BSTR. Can be used to pass a BSTR by reference.
   
   boolean*
   pointer to a boolean. Can be used to pass a boolean by reference.
   
   VARIANT*
   pointer to a VARIANT. Can be used to pass a VARIANT by reference.
   
   SCODE*
   pointer to an scode. Can be used to pass an scode by reference.
   
   unsigned char*
   pointer to an unsigned char. Can be used to pass an unsigned char by
   reference.
   
   IUnknown**
   Pointer to IUnknown*. Can be used to pass an IUnknown interface by
   reference.
   
   IDispatch**
   Pointer to IDispatch*. Can be used to pass an IDispatch interface by
   reference.
   
   SAFEARRAY(type) *
   Pointer to SAFEARRAY. Can be used to pass a SAFEARRAY by reference.
   
   HRESULT
   Return type used for reporting error information in interfaces. Can only
   be used as a return type. Use SCODE for parameter types. SCODE and
   HRESULT are the same in Win32.

The marshaler provided by OLE Automation cannot understand structures. Structures can be passed using a SAFEARRAY(unsigned char). For more information about passing structures, please see the following articles in the Microsoft Knowledge Base:

   ARTICLE-ID: Q122289
   TITLE     : Passing Structures in OLE Automation

   ARTICLE-ID: Q131046
   TITLE     : SAMPLE: BINARY: Transfer Binary Data Using OLE Automation

Custom Interface Implementation

The custom interface is implemented in the server, and the custom interface and type library are registered.

The custom interface, IVtblServer, is registered as follows:

HKEY_CLASSES_ROOT\Interface\{2ED17402-F80F-11ce-8161-00AA0060D733} = IVtblServer HKEY_CLASSES_ROOT\Interface\{2ED17402-F80F-11ce-8161-00AA0060D733} \TypeLib = {2ED17400-F80F-11ce-8161-00AA0060D733} HKEY_CLASSES_ROOT\Interface\{2ED17402-F80F-11ce-8161-00AA0060D733} \ProxyStubClsid = {00020424-0000-0000-C000-000000000046} HKEY_CLASSES_ROOT\Interface\{2ED17402-F80F-11ce-8161-00AA0060D733} \ProxyStubClsid32 = {00020424-0000-0000-C000-000000000046}

{2ED17402-F80F-11ce-8161-00AA0060D733} corresponds to the Interface ID of the custom interface. {00020424-0000-0000-C000-000000000046} is the CLSID of the OLE Automation marshaler that will marshal this custom interface. This is a CLSID that is provided by OLE. The TypeLib key is used to point to the GUID of the type library that describes this custom interface. When the custom interface is marshaled, OLE will look up its interface registration in the system registry using the Interface ID.

The ProxyStubClsid(32) key will point to the object that will marshal the interface. OLE will create this object and ask it to marshal the interface. In this case, OLE will create the OLE Automation marshaler. The OLE Automation marshaler will use the TypeLib key to obtain the type library, which describes the interface and will marshal the interface based on this type information. The CLSID specified by ProxyStubClsid(32) must always be {00020424-0000-0000-C000-000000000046} for an interface that is to be marshaled by the OLE Automation marshaler.

The type library is registered as follows:

HKEY_CLASSES_ROOT\TypeLib\{2ED17400-F80F-11ce-8161-00AA0060D733} HKEY_CLASSES_ROOT\TypeLib\{2ED17400-F80F-11ce-8161-00AA0060D733}\1.0 = VtblServer 1.0 Type Library HKEY_CLASSES_ROOT\TypeLib\{2ED17400-F80F-11ce-8161-00AA0060D733} \1.0\0\win32 = server.tlb

{2ED17400-F80F-11ce-8161-00AA0060D733} is the GUID of the type library. \1.0\0\win32 corresponds to version 1.0 and locale ID 0 (language neutral) of the type library on the win32 platform. The version and locale ID correspond to the version and lcid attributes in Server.odl. The locale ID is important for late-binding in OLE automation and is not important for vtbl-binding. The full path of Server.tlb is registered.

Additional reference words: 4.00 KBCategory: kbinterop kbref KBSubcategory: LeTwoArc

Keywords          : LeTwoArc 
Version           : 2.0
Platform          : NT WINDOWS

Last Reviewed: November 13, 1995