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:
139074 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:
124385 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:
122289 Passing Structures in OLE Automation
131046 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.