Com PDF
Com PDF
Purpose
COM is a platform-independent, distributed, object-oriented system for creating binary software components that
can interact. COM is the foundation technology for Microsoft's OLE (compound documents) and ActiveX
(Internet-enabled components) technologies.
Where applicable
COM objects can be created with a variety of programming languages. Object-oriented languages, such as C++,
provide programming mechanisms that simplify the implementation of COM objects. These objects can be within
a single process, in other processes, even on remote computers.
Run-time requirements
For information on which operating systems are required to use a particular interface or function, see the
Requirements section of the documentation for the interface or function.
In this section
TOPIC DESCRIPTION
OLE and Data Transfer Describes compound documents and data transfer.
Controls and Property Pages Describes ActiveX controls and property pages.
Related documentation
TOPIC DESCRIPTION
OLE and Data Transfer Describes compound documents and data transfer.
Controls and Property Pages Describes ActiveX controls and property pages.
Microsoft Interface Definition Language (MIDL) The Microsoft Interface Definition Language (MIDL) defines
interfaces between client and server programs. Microsoft
includes the MIDL compiler with the Platform Software
Development Kit (SDK) to enable developers to create the
interface definition language (IDL) files and application
configuration files (ACF) required for remote procedure call
(RPC) interfaces and COM/DCOM interfaces. MIDL also
supports the generation of type libraries for OLE Automation.
Structured Storage Structured Storage provides file and data persistence in COM
by handling a single file as a structured collection of objects
known as storages and streams.
Related topics
C
o
m
p
o
n
e
n
t
O
b
j
e
c
t
M
o
d
e
l
(
C
O
M
)
C
o
n
t
r
o
l
s
a
n
d
P
r
o
p
e
r
t
y
P
a
g
e
s
O
L
E
a
n
d
D
a
t
a
T
r
a
n
s
f
e
r
Guide
1/7/2020 • 2 minutes to read • Edit Online
Related topics
R
e
f
e
r
e
n
c
e
What's New in COM
1/7/2020 • 2 minutes to read • Edit Online
Related topics
C
h
a
n
g
e
s
t
o
C
O
M
i
n
W
i
n
d
o
w
s
V
i
s
t
a
Changes to COM in Windows Vista
1/7/2020 • 2 minutes to read • Edit Online
Related topics
C
h
a
n
g
e
s
t
o
C
O
M
i
n
W
i
n
d
o
w
s
7
The Component Object Model
1/7/2020 • 2 minutes to read • Edit Online
The Microsoft Component Object Model (COM ) is a platform-independent, distributed, object-oriented system
for creating binary software components that can interact. COM is the foundation technology for Microsoft's OLE
(compound documents), ActiveX (Internet-enabled components), as well as others.
To understand COM (and therefore all COM -based technologies), it is crucial to understand that it is not an
object-oriented language but a standard. Nor does COM specify how an application should be structured;
language, structure, and implementation details are left to the application developer. Rather, COM specifies an
object model and programming requirements that enable COM objects (also called COM components, or
sometimes simply objects) to interact with other objects. These objects can be within a single process, in other
processes, and can even be on remote computers. They can be written in different languages, and they may be
structurally quite dissimilar, which is why COM is referred to as a binary standard; a standard that applies after a
program has been translated to binary machine code.
The only language requirement for COM is that code is generated in a language that can create structures of
pointers and, either explicitly or implicitly, call functions through pointers. Object-oriented languages such as C++
and Smalltalk provide programming mechanisms that simplify the implementation of COM objects, but
languages such as C, Java, and VBScript can be used to create and use COM objects.
COM defines the essential nature of a COM object. In general, a software object is made up of a set of data and
the functions that manipulate the data. A COM object is one in which access to an object's data is achieved
exclusively through one or more sets of related functions. These function sets are called interfaces, and the
functions of an interface are called methods. Further, COM requires that the only way to gain access to the
methods of an interface is through a pointer to the interface.
Besides specifying the basic binary object standard, COM defines certain basic interfaces that provide functions
common to all COM -based technologies, and it provides a small number of functions that all components require.
COM also defines how objects work together over a distributed environment and has added security features to
help provide system and component integrity.
The following topics in this section describe basic COM issues related to designing COM objects:
COM Objects and Interfaces
Using and Implementing IUnknown
Reusing Objects
The COM Library
Managing Memory Allocation
COM Technical Overview
1/29/2020 • 21 minutes to read • Edit Online
This topic provides an overview of the Microsoft Component Object Model (COM ):
Introduction to COM
Objects and Interfaces
Interface implementation
The IUnknown Interface
The Client/Server Model
Service Control Manager
Reusability
Storage and Stream Objects
Data Transfer
Remoting
Security
Related topics
Introduction to COM
The Microsoft Component Object Model (COM ) defines a binary interoperability standard for creating reusable
software libraries that interact at run time. You can use COM libraries without the requirement of compiling them
into your application. COM is the foundation for a number of Microsoft products and technologies, such as
Windows Media Player and Windows Server.
COM defines a binary standard that applies to many operating systems and hardware platforms. For network
computing, COM defines a standard wire format and protocol for interaction among objects that run on different
hardware platforms. COM is independent of implementation language, which means that you can create COM
libraries by using different programming languages, such as C++ and those in the .NET Framework.
The COM specification provides all of the fundamental concepts that enable cross-platform software reuse:
A binary standard for function calls between components.
A provision for strongly-typed groupings of functions into interfaces.
A base interface that provides polymorphism, feature discovery, and object lifetime tracking.
A mechanism that uniquely identifies components and their interfaces.
A component loader that creates component instances from a deployment.
COM has a number of parts that work together to enable the creation of applications that are built from reusable
components:
A host system that provides a run-time environment that conforms to the COM specification.
Interfaces that define feature contracts, and components that implement interfaces.
Servers that provide components to the system, and clients that use the features provided by components.
A registry that tracks where components are deployed on local and remote hosts.
A Service Control Manager that locates components on local and remote hosts and connects servers to clients.
A structured storage protocol that defines how to navigate the contents of files on the host's file system.
Enabling code re-use across hosts and platforms is central to COM. A reusable interface implementation is named
a component, a component object, or a COM object. A component implements one or more COM interfaces.
You define a custom COM library by designing the interfaces that your library implements. Consumers of your
library can discover and use its features without any knowledge of your library's deployment and implementation
details.
Interface implementation
You cannot create an instance of a COM interface by itself. Instead, you create an instance of a class that
implements the interface. In C++, a COM interface is modeled as an abstract base class, which means that the
interface is a C++ class that contains only pure virtual member functions. A C++ library implements COM objects
by inheriting the member function signatures from one or more interfaces, overriding each member function, and
providing an implementation for each function.
You can use any programming language that supports the concept of function pointers to implement a COM
interface. For example, in C, an interface is a structure containing a pointer to a table of function pointers, one for
each method in the interface.
When you implement an interface, your class must provide an implementation for every function in the interface. If
the class has no work to do in an interface function, the implementation may be a single return statement.
A COM class is identified by using a unique 128-bit Class ID (CLSID ) that associates a class with a particular
deployment in the file system, which for Windows is a DLL or EXE. A CLSID is a GUID, which means that no other
class has the same CLSID. The use of unique class identifiers prevents name collisions among classes. For example,
two different vendors can write a class named CStack, but both classes have a unique CLSID, so any possibility of a
collision is avoided.
You obtain a new CLSID by using the CoCreateGuid function or by using a COM authoring tool, such as Visual
Studio, that calls this function internally.
NOTE
A COM server is not the same as the COM object that it provides to the system.
To enable creating a COM object, a COM server must provide an implementation of the IClassFactory interface.
Clients can call the CreateInstance method to request a new instance of a COM object, but usually such requests
are encapsulated in the CoCreateInstance function.
You can deploy a COM server either as a shared library that is loaded into the client's process at run time (DLL on
Windows platforms) or as an executable module (EXE on Windows platforms). For more information, see
Registering COM Applications.
Reusability
COM supports black-box reusability, which means that the implementation details of a reusable component are
not exposed to clients. To achieve black-box reusability, COM supports two mechanisms through which one object
may reuse another. The two forms of reuse are named containment and aggregation. By convention, the object
being reused is named the inner object, and the object that is making use of the inner object is named the outer
object.
In containment, the outer object behaves as a client of the inner object. The outer object is a logical container for
the inner object, and when the outer object uses the services of the inner object, the outer object delegates
implementation to the inner object's interfaces. This means that the outer object is implemented in terms of the
inner object's services. The outer object may not support the same interfaces as the inner object, and the outer
object may use an inner object's interface to help with implementing parts of a different interface on the outer
object.
In aggregation, the outer object exposes interfaces from the inner object as if they were implemented on the outer
object. This is useful when the outer object would always delegate every call on one of its interfaces to the same
interface of the inner object. Aggregation is a convenience that enables the outer object to avoid extra
implementation overhead.
For more information, see Reusing Objects.
Data Transfer
Structured storage provides the basis for data exchange between COM objects and processes, which is named
uniform data transfer. Before COM was implemented in OLE 2, data transfer on Windows was specified by
transfer protocols, such as the clipboard and drag-drop protocols. Each transfer protocol had its own set of
functions that bound the protocol to the query, and specific code was required to handle each different protocol
and exchange procedure. Uniform data transfer represents all data transfers by using the IDataObject interface,
which separates common data exchange operations from the transfer protocol.
The IDataObject interface encapsulates the standard get and set operations on data, queries and enumerations,
and notifications that detect when data changes in an object. Uniform data transfer enables rich descriptions of
data formats, as well as the use of different storage media for the data transfer.
During uniform data transfer, all protocols exchange a pointer to an IDataObject interface. The server is the
source of the data and implements one data object, which is usable in any data exchange protocol. The client
consumes the data and requests data from a data object when it receives an IDataObject pointer from any
protocol. After the pointer exchange has occurred, both sides handle data exchange in a uniform fashion, through
the IDataObject interface.
COM defines two data structures that enable uniform data transfer. The FORMATETC structure represents a
generalized clipboard format, and the STGMEDIUM structure represents the transfer medium as a memory
handle.
The client creates a FORMATETC structure to indicate the type of data that it requests from a data source, and it is
used by the data source to describe what formats it provides. The client queries a data source for its available
formats by requesting its IEnumFORMATETC interface. For more information, see The FORMATETC Structure.
The client creates a STGMEDIUM structure and passes it to the GetData method, and the data object returns the
data in the provided STGMEDIUM structure.
The STGMEDIUM structure enables both clients and data sources to choose the most efficient exchange medium.
For example, if the data to be exchanged is very large, the data source can indicate a disk-based medium as its
preferred format, instead of main memory. This flexibility enables efficient data exchanges that can be as fast as
passing a pointer to an IStorage or an IStream. For more information, see The STGMEDIUM Structure.
A client of a data source may require notification when the data changes. COM handles data-change notifications
by using an advise sink object, which implements the IAdviseSink interface. The advise sink object and the
IAdviseSink interface are implemented by the client, which passes an IAdviseSink pointer to the data source.
When the data source detects a change in the underlying data, it calls an IAdviseSink method to notify the client.
For more information, see Data Notification.
Remoting
COM enables remote and distributed computation. Interface remoting enables a member function to return an
interface pointer to a COM object that is in a different process or on a different host computer. The infrastructure
that performs the interface remoting is transparent to both the client and the object server. Neither the client nor
the server need one another's deployment details to communicate through a remoted interface. A client calls
member functions on the same interface to communicate with a COM object that is in-process, out-of-process on
the local host, or on a remote computer. Local and remote calls on the same interface are indistinguishable to the
client.
To communicate with a COM object, a client always calls an in-process implementation. If the COM object is in-
process, the call is direct. If the COM object is out-of-process or remote, COM provides a proxy implementation
that forwards the call to the object by using the Remote Procedure Call (RPC ) protocol.
A COM object always receives calls from a client through an in-process implementation. If the caller is in-process,
the call is direct. If the caller is out-of-process or remote, COM provides a stub implementation that receives the
remote procedure call from the proxy in the client process.
Marshaling is the procedure for packaging the call stack for transmission from proxy to stub. Unmarshaling is the
unpackaging that occurs at the receiving end. Return values are marshaled and unmarshaled from the stub to the
proxy. This kind of communication is also referred to as sending a call over the wire.
Each different data type has rules for marshaling. Interface pointers also have a marshaling protocol, which is
encapsulated in the CoMarshalInterface function. In most cases, standard interface marshaling, which is
provided by the system, is sufficient, but a COM object optionally may implement custom interface marshaling to
control the creation of remote object proxies to itself. For more information, see Inter-Object Communication.
Security
COM provides two forms of application security. One is activation security, which specifies how new objects are
created, how clients connect to new and existing objects, and how certain public services, such as the Class Table
and the Running Object Table are secured. The other is call security, which specifies how security operates in an
established connection between a client to a COM object.
Activation security is applied automatically by the Service Control Manager (SCM ). When the SCM receives a
request to retrieve a COM object, it checks the request against security information that is stored in the registry.
SCM implementations usually offer registry-driven configuration for administering deployed classes and for
specific user accounts on the host. For more information, see Activation Security.
Call security is applied automatically or is enforced by the application. If the application provides setup information,
COM performs the necessary checks to secure the application.
The automatic mechanism checks security for the process, but not for individual objects or methods. If an
application requires more fine-grained security, COM provides functions that applications may use do their own
security checking.
The automatic and custom mechanisms can be used together, so an application may ask COM to perform
automatic security checking and then perform its own.
COM call security services are divided into the following categories:
General functions that are called by both clients and servers, which enable the automatic security mechanism to
be initialized and automatic authentication services to be registered. The general call security APIs are the
CoInitializeSecurity and CoQueryAuthenticationServices functions.
Interfaces on client proxies, which enable the client to control the security on calls to individual interfaces. The
IClientSecurity interface and the CoQueryProxyBlanket, CoSetProxyBlanket, and CoCopyProxy
functions provide call security on a remote object.
Server-side functions and call-context interfaces, which enable the server to retrieve security information about
a call and to impersonate the caller. The IServerSecurity interface and the CoGetCallContext,
CoImpersonateClient, and CoRevertToSelf functions provide server-side call security.
Often, the client queries the COM object for the IClientSecurity interface, which is implemented locally by the
remoting layer. The client uses this interface to control the security of individual interface proxies on the COM
object before making a call on one of the interfaces.
When a call arrives at the server, the server may call the CoGetCallContext function to retrieve an
IServerSecurity interface, which allows the server to check the client's authentication and to impersonate the
client, if necessary. The IServerSecurity object is valid for the duration of the call.
Call the CoInitializeSecurity function to initialize the security layer and set the specified values as the security
default. If a process does not call CoInitializeSecurity, COM calls it automatically the first time an interface is
marshaled or unmarshaled, registering the system default security. The CoInitializeSecurity function allows the
client to establish default call security for the process, which avoids the use of IClientSecurity on individual
proxies. The CoInitializeSecurity function enables a server to register automatic authentication services for the
process. For more information, see Setting Process-Wide Security with CoInitializeSecurity.
Related topics
C
O
M
C
l
i
e
n
t
s
a
n
d
S
e
r
v
e
r
s
D
e
f
i
n
i
n
g
C
O
M
I
n
t
e
r
f
a
c
e
s
R
e
g
i
s
t
e
r
i
n
g
C
O
M
A
p
p
l
i
c
a
t
i
o
n
s
S
e
c
u
r
i
t
y
i
n
C
O
M
P
r
o
c
e
s
s
e
s
,
T
h
r
e
a
d
s
,
a
n
d
A
p
a
r
t
m
e
n
t
s
COM Objects and Interfaces
1/7/2020 • 2 minutes to read • Edit Online
COM is a technology that allows objects to interact across process and computer boundaries as easily as within a
single process. COM enables this by specifying that the only way to manipulate the data associated with an object
is through an interface on the object. When this term is used in this documentation, it refers to an implementation
in code of a COM binary-compliant interface that is associated with an object.
COM uses the word interface in a sense different from that typically used in Visual C++ programming. A C++
interface refers to all of the functions that a class supports and that clients of an object can call to interact with it. A
COM interface refers to a predefined group of related functions that a COM class implements, but a specific
interface does not necessarily represent all the functions that the class supports.
Referring to an object implementing an interface means that the object uses code that implements each method of
the interface and provides COM binary-compliant pointers to those functions to the COM library. COM then
makes those functions available to any client who asks for a pointer to the interface, whether the client is inside or
outside of the process that implements those functions.
For more information, see the following topics:
Interfaces and Interface Implementations
Interface Pointers and Interfaces
IUnknown and Interface Inheritance
Related topics
I
n
t
e
r
f
a
c
e
s
Interfaces and Interface Implementations
1/7/2020 • 2 minutes to read • Edit Online
COM makes a fundamental distinction between interface definitions and their implementations.
An interface is actually a contract that consists of a group of related function prototypes whose usage is defined
but whose implementation is not. These function prototypes are equivalent to pure virtual base classes in C++
programming. An interface definition specifies the interface's member functions, called methods, their return types,
the number and types of their parameters, and what they must do. There is no implementation associated with an
interface.
An interface implementation is the code a programmer supplies to carry out the actions specified in an interface
definition. Implementations of many of the interfaces a programmer can use in an object-based application are
included in the COM libraries. However, programmers are free to ignore these implementations and write their
own. An interface implementation is to be associated with an object when an instance of that object is created, and
the implementation provides the services that the object offers.
For example, a hypothetical interface named IStack might define two methods, named Push and Pop, specifying
that successive calls to the Pop method return, in reverse order, values previously passed to the Push method. This
interface definition would not specify how the functions are to be implemented in code. In implementing the
interface, one programmer might implement the stack as an array and implement the Push and Pop methods in
such a way as to access that array, while another programmer might use a linked list and would implement the
methods accordingly. Regardless of a particular implementation of the Push and Pop methods, the in-memory
representation of a pointer to an IStack interface, and therefore its use by a client, is completely determined by the
interface definition.
Simple objects support only a single interface. More complicated objects, such as embeddable objects, typically
support several interfaces. Clients have access to a COM object only through a pointer to one of its interfaces,
which, in turn, allows the client to call any of the methods that make up that interface. These methods determine
how a client can use the object's data.
Interfaces define a contract between an object and its clients. The contract specifies the methods that must be
associated with each interface and what the behavior of each of the methods must be in terms of input and output.
The contract generally does not define how to implement the methods in an interface. Another important aspect of
the contract is that if an object supports an interface, it must support all of that interface's methods in some way.
Not all of the methods in an implementation need to do something—if an object does not support the function
implied by a method, its implementation may be a simple return or perhaps the return of a meaningful error
message—but the methods must exist.
Related topics
C
O
M
O
b
j
e
c
t
s
a
n
d
I
n
t
e
r
f
a
c
e
s
Interface Pointers and Interfaces
1/7/2020 • 2 minutes to read • Edit Online
An instance of an interface implementation is actually a pointer to an array of pointers to methods - that is, a
function table that refers to an implementation of all of the methods specified in the interface. Objects with
multiple interfaces can provide pointers to more than one function table. Any code that has a pointer through
which it can access the array can call the methods in that interface.
Speaking precisely about this multiple indirection is inconvenient, so instead, the pointer to the interface function
table that another object must have to call its methods is called simply an interface pointer. You can manually
create function tables in a C application or almost automatically by using Visual C++ (or other object-oriented
languages that support COM ).
With appropriate compiler support (which is inherent in C and C++), a client can call an interface method through
its name, not its position in the array. Because an interface is a type, the compiler, given the names of methods, can
check the types of parameters and return values of each interface method call. In contrast, if a client uses a
position-based calling scheme, such type-checking is not available, even in C or C++.
Each interface is an immutable contract of a functional group of methods. You reference an interface at run time
with a globally unique interface identifier (IID ). This IID, which is a specific instance of a globally unique identifier
(GUID ) supported by COM, allows a client to ask an object precisely whether it supports the semantics of the
interface, without unnecessary overhead and without the confusion that could arise in a system from having
multiple versions of the same interface with the same name.
To summarize, it is important to understand what a COM interface is, and is not:
A COM interface is not the same as a C++ class. The pure virtual definition carries no implementation. If you
are a C++ programmer, you can define your implementation of an interface as a class, but this falls under the
heading of implementation details, which COM does not specify. An instance of an object that implements an
interface must be created for the interface actually to exist. Furthermore, different object classes may implement
an interface differently yet be used interchangeably in binary form, as long as the behavior conforms to the
interface definition.
A COM interface is not an object. It is simply a related group of functions and is the binary standard through
which clients and objects communicate. As long as it can provide pointers to interface methods, the object can
be implemented in any language with any internal state representation.
COM interfaces are strongly typed. Every interface has its own interface identifier (a GUID ), which eliminates
the possibility of duplication that could occur with any other naming scheme.
COM interfaces are immutable. You cannot define a new version of an old interface and give it the same
identifier. Adding or removing methods of an interface or changing semantics creates a new interface, not a new
version of an old interface. Therefore, a new interface cannot conflict with an old interface. However, objects can
support multiple interfaces simultaneously and can expose interfaces that are successive revisions of an
interface, with different identifiers. Thus, each interface is a separate contract, and systemwide objects need not
be concerned about whether the version of the interface they are calling is the one they expect. The interface ID
(IID ) defines the interface contract explicitly and uniquely.
Related topics
C
O
M
O
b
j
e
c
t
s
a
n
d
I
n
t
e
r
f
a
c
e
s
IUnknown and Interface Inheritance
1/29/2020 • 2 minutes to read • Edit Online
Inheritance in COM does not mean code reuse. Because no implementations are associated with interfaces,
interface inheritance does not mean code inheritance. It means only that the contract associated with an interface is
inherited in a C++ pure-virtual base-class fashion and modified — either by adding new methods or by further
qualifying the allowed usage of methods. There is no selective inheritance in COM. If one interface inherits from
another, it includes all the methods that the other interface defines.
Inheritance is used sparingly in the predefined COM interfaces. All predefined interfaces (and any custom
interfaces you define) inherit their definitions from the important interface IUnknown, which contains three vital
methods: QueryInterface, AddRef, and Release. All COM objects must implement the IUnknown interface
because it provides the means, using QueryInterface, to move freely between the different interfaces that an
object supports as well as the means to manage its lifetime by using AddRef and Release.
In creating an object that supports aggregation, you would need to implement one set of IUnknown functions for
all interfaces as well as a stand-alone IUnknown interface. In any case, any object implementor will implement
IUnknown methods. See the section Using and Implementing IUnknown for more information.
While there are a few interfaces that inherit their definitions from a second interface in addition to IUnknown, the
majority simply inherit the IUnknown interface methods. This makes most interfaces relatively compact and easy
to encapsulate.
Related topics
C
O
M
O
b
j
e
c
t
s
a
n
d
I
n
t
e
r
f
a
c
e
s
Using and Implementing IUnknown
1/7/2020 • 2 minutes to read • Edit Online
COM provides a rich set of standards for implementing and using objects and for inter-object communication. The
topics in this section describe basic information relating to implementing objects. For information about how
clients and servers interact, see COM Clients and Servers. For more information about threading models and their
implementation and use, see Processes, Threads, and Apartments.
For details on using and implementing IUnknown, see the following topics:
QueryInterface: Navigating in an Object
Rules for Implementing QueryInterface
Managing Object Lifetimes Through Reference Counting
QueryInterface: Navigating in an Object
1/29/2020 • 3 minutes to read • Edit Online
After you have an initial pointer to an interface on an object, COM has a very simple mechanism to find out
whether the object supports another specific interface and, if so, to get a pointer to it. (For information about
getting an initial pointer to an interface on an object, see Getting a Pointer to an Object.) This mechanism is the
QueryInterface method of the IUnknown interface. If the object supports the requested interface, the method
must return a pointer to that interface. This permits an object to navigate freely through the interfaces that an
object supports. QueryInterface separates the request "Do you support a given contract?" from the high-
performance use of that contract once negotiations have been successful.
When a client initially gains access to an object, that client will receive, at a minimum, an IUnknown interface
pointer (the most fundamental interface) through which it can control the lifetime of the object—by telling the
object when it is done using the object—and invoke QueryInterface. The client is programmed to ask each object
it manages to perform some operations, but the IUnknown interface has no functions for those operations.
Instead, those operations are expressed through other interfaces. The client is thus programmed to negotiate with
objects for those interfaces. Specifically, the client will call QueryInterface to ask an object for an interface
through which the client may invoke the desired operations.
Because the object implements QueryInterface, it has the ability to accept or reject the request. If the object
accepts the client's request, QueryInterface returns a new pointer to the requested interface to the client. Through
that interface pointer, the client has access to the methods of that interface. If, on the other hand, the object rejects
the client's request, QueryInterface returns a null pointer—an error—and the client has no pointer through which
to call the desired functions. In this case, the client must deal gracefully with that possibility. For example, suppose
a client has a pointer to interface A on an object and asks for interfaces B and C. Suppose also that the object
supports interface B but does not support interface C. The result is that the object returns a pointer to B and
reports that C is not supported.
A key point is that when an object rejects a call to QueryInterface, it is impossible for the client to ask the object
to perform the operations expressed through the requested interface. A client must have an interface pointer to
invoke methods in that interface. If the object refuses to provide the requested pointer, the client must be prepared
to do without, either by not doing whatever it had intended to do with that object or by attempting to fall back on
another, perhaps less powerful, interface. This feature of COM functionality works well in comparison with other
object-oriented systems in which you cannot know whether a function will work until you call that function, and
even then, handling failure is uncertain. QueryInterface provides a reliable and consistent way to know whether
an object supports an interface before attempting to call its methods.
The QueryInterface method also provides a robust and reliable way for an object to indicate that it does not
support a given contract. That is, if in a call to QueryInterface one asks an "old" object whether it supports a
"new" interface (one, for example, that was invented after the old object had been shipped), the old object will
reliably, without causing a crash, answer "no." The technology that supports this is the algorithm by which IIDs are
allocated. While this may seem like a small point, it is extremely important to the overall architecture of the system,
and the ability to inquire of legacy elements about new functionality is, surprisingly, a feature not present in most
other object architectures.
Related topics
U
s
i
n
g
a
n
d
I
m
p
l
e
m
e
n
t
i
n
g
I
U
n
k
n
o
w
n
Rules for Implementing QueryInterface
1/29/2020 • 2 minutes to read • Edit Online
There are three main rules that govern implementing the IUnknown::QueryInterface method on a COM object:
Objects must have identity.
The set of interfaces on an object instance must be static.
It must be possible to query successfully for any interface on an object from any other interface.
pA->QueryInterface(IID_IA, ...)
If a call to QueryInterface for a second interface pointer succeeds, a call to QueryInterface from that
pointer for the first interface must also succeed. If pB was successfully obtained, the following must also
succeed:
pB->QueryInterface(IID_IA, ...)
Any interface must be able to query for any other interface on an object. If pB was successfully obtained and
you successfully query for a third interface (IC ) using that pointer, you must also be able to query
successfully for IC using the first pointer, pA. In this case, the following sequence must succeed:
IC * pC = NULL;
hr = pB->QueryInterface(IID_IC, &pC);
pA->QueryInterface(IID_IC, ...)
Interface implementations must maintain a counter of outstanding pointer references to all the interfaces on a
given object. You should use an unsigned integer for the counter.
If a client needs to know that resources have been freed, it must use a method in some interface on the object with
higher-level semantics before calling IUnknown::Release.
Related topics
U
s
i
n
g
a
n
d
I
m
p
l
e
m
e
n
t
i
n
g
I
U
n
k
n
o
w
n
Managing Object Lifetimes Through Reference
Counting
1/7/2020 • 3 minutes to read • Edit Online
In traditional object systems, the life cycle of objects—that is, the issues surrounding the creation and deletion of
objects—is handled implicitly by the language (or the language run time) or explicitly by application programmers.
In an evolving, decentrally constructed system made up of reused components, it is no longer true that any client,
or even any programmer, always "knows" how to deal with a component's lifetime. For a client with the right
security privileges, it is still relatively easy to create objects through a simple request, but object deletion is another
matter entirely. It is not necessarily clear when an object is no longer needed and should be deleted. (Readers
familiar with garbage-collected programming environments, such as Java, may disagree; however, Java objects do
not span machine or even process boundaries, and therefore the garbage collection is restricted to objects living
within a single-process space. In addition, Java forces the use of a single programming language.) Even when the
original client is done with the object, it cannot simply shut the object down, because some other client or clients
might still have a reference to it.
One way to ensure that an object is no longer needed is to depend entirely on an underlying communication
channel to inform the system when all connections to a cross-process or cross-channel object have disappeared.
However, schemes that use this method are unacceptable for several reasons. One problem is that it could require
a major difference between the cross-process/cross-network programming model and the single-process
programming model. In the cross-process/cross-network programming model, the communication system would
provide the hooks necessary for object lifetime management, while in the single-process programming model,
objects are directly connected without any intervening communications channel. Another problem is that this
scheme could also result in a layer of system-provided software that would interfere with component performance
in the in-process case. Furthermore, a mechanism based on explicit monitoring would not tend to scale toward
many thousands or millions of objects.
COM offers a scalable and distributed approach to this set of problems. Clients tell an object when they are using
it and when they are done, and objects delete themselves when they are no longer needed. This approach
mandates that all objects count references to themselves. Programming languages such as Java, which inherently
have their own lifetime management schemes, such as garbage collection, can use COM's reference counting to
implement and use COM objects internally, allowing the programmer to avoid dealing with it.
Just as an application must free memory it has allocated once that memory is no longer in use, a client of an object
is responsible for freeing its references to the object when that object is no longer needed. In an object-oriented
system, the client can do this only by giving the object an instruction to free itself.
It is important that an object be deallocated when it is no longer being used. The difficulty lies in determining
when it is appropriate to deallocate an object. This is easy with automatic variables (those allocated on the stack)—
they cannot be used outside the block in which they're declared, so the compiler deallocates them when the end of
the block is reached. For COM objects, which are dynamically allocated, it is up to the clients of an object to decide
when they no longer need to use the object—especially local or remote objects that might be in use by multiple
clients at the same time. The object must wait until all clients are finished with it before freeing itself. Because COM
objects are manipulated through interface pointers and can be used by objects in different processes or on other
machines, the system cannot keep track of an object's clients.
COM's method of determining when it is appropriate to deallocate an object is manual reference counting. Each
object maintains a reference count that tracks how many clients are connected to it—that is, how many pointers
exist to any of its interfaces in any client.
For more information, see the following topics:
Implementing Reference Counting
Rules for Managing Reference Counts
Related topics
U
s
i
n
g
a
n
d
I
m
p
l
e
m
e
n
t
i
n
g
I
U
n
k
n
o
w
n
Implementing Reference Counting
1/29/2020 • 2 minutes to read • Edit Online
Reference counting requires work on the part of both the implementor of a class and the clients who use objects of
that class. When you implement a class, you must implement the AddRef and Release methods as part of the
IUnknown interface. These two methods have the following simple implementations:
AddRef increments the object's internal reference count.
Release first decrements the object's internal reference count, and then it checks whether the reference count
has fallen to zero. If it has, that means no one is using the object any longer, so the Release function deallocates
the object.
A common implementation approach for most objects is to have only one implementation of these methods (along
with QueryInterface), which is shared between all interfaces, and therefore a reference count that applies to the
entire object. However, from a client's perspective, reference counting is strictly and clearly a per-interface-pointer
notion, and therefore objects that take advantage of this capability by dynamically constructing, destroying, loading,
or unloading portions of their functionality based on the currently extant interface pointers may be implemented.
These are colloquially called tear-off interfaces.
Whenever a client calls a method (or API function), such as QueryInterface, that returns a new interface pointer,
the method being called is responsible for incrementing the reference count through the returned pointer. For
example, when a client first creates an object, it receives an interface pointer to an object that, from the client's point
of view, has a reference count of one. If the client then calls AddRef on the interface pointer, the reference count
becomes two. The client must call Release twice on the interface pointer to drop all of its references to the object.
An example of how reference counts are strictly per-interface-pointer occurs when a client calls QueryInterface
on the first pointer for either a new interface or the same interface. In either of these cases, the client is required to
call Release once for each pointer. COM does not require that an object return the same pointer when asked for
the same interface multiple times. (The only exception to this is a query to IUnknown, which identifies an object to
COM.) This allows the object implementation to manage resources efficiently.
Thread-safety is also an important issue in implementing AddRef and Release. For more information, see
Processes, Threads, and Apartments.
Related topics
M
a
n
a
g
i
n
g
O
b
j
e
c
t
L
i
f
e
t
i
m
e
s
T
h
r
o
u
g
h
R
e
f
e
r
e
n
c
e
C
o
u
n
t
i
n
g
Rules for Managing Reference Counts
1/29/2020 • 4 minutes to read • Edit Online
Using a reference count to manage an object's lifetime allows multiple clients to obtain and release access to a
single object without having to coordinate with one another in managing the object's lifetime. As long as the client
object conforms to certain rules of use, the object, in effect, provides this management. These rules specify how to
manage references between objects. (COM does not specify internal implementations of objects, although these
rules are a reasonable starting point for a policy within an object.)
Conceptually, interface pointers can be thought of as residing within pointer variables that include all the internal
computation state that holds an interface pointer. This would include variables in memory locations, in internal
processor registers, and both programmer-generated and compiler-generated variables. Assignment to or
initialization of a pointer variable involves creating a new copy of an already existing pointer. Where there was one
copy of the pointer in some variable (the value used in the assignment/initialization), there are now two. An
assignment to a pointer variable destroys the pointer copy presently in the variable, as does the destruction of the
variable itself. (That is, the scope in which the variable is found, such as the stack frame, is destroyed.)
From a COM client's perspective, reference counting is always done for each interface. Clients should never
assume that an object uses the same counter for all interfaces.
The default case is that AddRef must be called for every new copy of an interface pointer and Release must be
called for every destruction of an interface pointer, except where the following rules permit otherwise:
In-out parameters to functions. The caller must call AddRef on the parameter because it will be released
(with a call to Release) in the implementing code when the out value is stored on top of it.
Fetching a global variable. When creating a local copy of an interface pointer from an existing copy of the
pointer in a global variable, you must call AddRef on the local copy because another function might destroy the
copy in the global variable while the local copy is still valid.
New pointers synthesized out of "thin air." A function that synthesizes an interface pointer using special
internal knowledge rather than obtaining it from some other source must call AddRef initially on the newly
synthesized pointer. Important examples of such routines include instance creation routines, implementations of
QueryInterface, and so on.
Retrieving a copy of an internally stored pointer. When a function retrieves a copy of a pointer that is
stored internally by the object called, that object's code must call AddRef on the pointer before the function
returns. Once the pointer has been retrieved, the originating object has no other way of determining how its
lifetime relates to that of the internally stored copy of the pointer.
The only exceptions to the default case require that the managing code know the relationships of the lifetimes of
two or more copies of a pointer to the same interface on an object and simply ensure that the object is not
destroyed by allowing its reference count to go to zero. There are generally two cases, as follows:
When one copy of a pointer already exists and a second is created subsequently and then is destroyed while the
first copy still exists, calls to AddRef and Releasefor the second copy can be omitted.
When one copy of a pointer exists and a second is created and then the first is destroyed before the second, the
calls to AddReffor the second copy and to Release for the first copy can be omitted.
The following are specific examples of these situations, the first two being especially common:
In parameters to functions. The lifetime of the copy of an interface pointer passed as a parameter to a
function is nested in that of the pointer used to initialize the value, so there is no need for a separate reference
count on the parameter.
Out parameters from functions, including return values. To set the out parameter, the function must have
a stable copy of the interface pointer. On return, the caller is responsible for releasing the pointer. Therefore, the
out parameter does not need a separate reference count.
Local variables. A method implementation has control of the lifetimes of each of the pointer variables
allocated on the stack frame and can use this to determine how to omit redundant AddRef/Release pairs.
Backpointers. Some data structures contain two objects, each with a pointer to the other. If the lifetime of the
first object is known to contain the lifetime of the second, it is not necessary to have a reference count on the
second object's pointer to the first object. Often, avoiding this cycle is important in maintaining the appropriate
deallocation behavior. However, uncounted pointers should be used with extreme caution because the portion
of the operating system that handles remote processing has no way of knowing about this relationship.
Therefore, in almost all cases, having the backpointer see a second, "friend" object of the first pointer (thus
avoiding the circularity) is the preferred solution. COM's connectable objects architecture, for example, uses this
approach.
When implementing or using reference-counted objects, it may be useful to apply artificial reference counts, which
guarantee object stability during processing of a function. In implementing a method of an interface, you might call
functions that have a chance of decrementing your reference count to an object, causing a premature release of the
object and failure of the implementation. A robust way to avoid this is to insert a call to AddRef at the beginning
of the method implementation and pair it with a call to Release just before the method returns.
In some situations, the return values of AddRef and Release may be unstable and should not be relied upon; they
should be used only for debugging or diagnostic purposes.
Related topics
M
a
n
a
g
i
n
g
O
b
j
e
c
t
L
i
f
e
t
i
m
e
s
T
h
r
o
u
g
h
R
e
f
e
r
e
n
c
e
C
o
u
n
t
i
n
g
Reusing Objects
1/7/2020 • 2 minutes to read • Edit Online
An important goal of any object model is to enable object authors to reuse and extend objects provided by others
as pieces of their own implementations. One way to do this in Microsoft Visual C++ and other languages is by
using implementation inheritance, which allows an object to inherit ("subclass") some of its functions from another
object while overriding other functions.
The problem for systemwide object interaction using traditional implementation inheritance is that the contract
(the interface) between objects in an implementation hierarchy is not clearly defined. In fact, it is implicit and
ambiguous. When the parent or child object changes its implementation, the behavior of related components
might become undefined or unstably implemented. In any single application, where the implementation can be
managed by a single engineering team that updates all of the components at the same time, this is not always a
major concern. In an environment where the components of one team are built through black-box reuse of other
components built by other teams, this type of instability jeopardizes reuse. Additionally, implementation
inheritance usually works only within process boundaries. This makes traditional implementation inheritance
impractical for large, evolving systems composed of software components built by many engineering teams.
The key to building reusable components is to be able to treat the object as a black box. This means that the piece
of code attempting to reuse another object knows nothing, and needs to know nothing, about the internal
structure or implementation of the component being used. In other words, the code attempting to reuse a
component depends on the behavior of the object and not its exact implementation.
To achieve black-box reusability, COM adopts other established reusability mechanisms such as
containment/delegation and aggregation.
NOTE
For convenience, the object being reused is called the inner object and the object making use of that inner object is the outer
object.
It is important to remember in both these mechanisms how the outer object appears to its clients. As far as the
clients are concerned, both objects implement any interfaces to which the client can get a pointer. The client treats
the outer object as a black box and therefore does not care, nor does it need to care, about the internal structure of
the outer object—the client cares only about behavior.
For more information, see the following topics:
Containment/Delegation
Aggregation
Containment/Delegation
1/7/2020 • 2 minutes to read • Edit Online
The most common mechanism for object reuse in COM is containment/delegation. This type of reuse is a familiar
concept found in most object-oriented languages and systems. The outer object, which needs to make use of the
inner object, acts as an object client to the inner object. The outer object "contains" the inner object, and when the
outer object requires the services of the inner object, the outer object explicitly delegates implementation to the
inner object's methods. That is, the outer object uses the inner object's services to implement itself.
It is not necessary for the outer and inner objects to support the same interfaces, although it certainly is
reasonable to contain an object that implements an interface that the outer object does not and implement the
methods of the outer object simply as calls to the corresponding methods in the inner object. When the complexity
of the outer and inner objects differs greatly, however, the outer object may implement some of the methods of its
interfaces by delegating calls to interface methods implemented in the inner object.
It is simple to implement containment for an outer object. The outer object creates the inner objects it needs to use
as any other client would. This is nothing new —the process is like a C++ object that itself contains a C++ string
object that it uses to perform certain string functions, even if the outer object is not considered a string object in its
own right. Then, using its pointer to the inner object, a call to a method in the outer object generates a call to an
inner object method.
Related topics
A
g
g
r
e
g
a
t
i
o
n
Aggregation
1/29/2020 • 4 minutes to read • Edit Online
Aggregation is the object reuse mechanism in which the outer object exposes interfaces from the inner object as if
they were implemented on the outer object itself. This is useful when the outer object delegates every call to one
of its interfaces to the same interface in the inner object. Aggregation is available as a convenience to avoid extra
implementation overhead in the outer object in this case. Aggregation is actually a specialized case of
containment/delegation.
Aggregation is almost as simple to implement as containment is, except for the three IUnknown functions:
QueryInterface, AddRef, and Release. The catch is that from the client's perspective, any IUnknown function
on the outer object must affect the outer object. That is, AddRef and Release affect the outer object and
QueryInterface exposes all the interfaces available on the outer object. However, if the outer object simply
exposes an inner object's interface as its own, that inner object's IUnknown members called through that
interface will behave differently than those IUnknown members on the outer object's interfaces, an absolute
violation of the rules and properties governing IUnknown.
The solution is that aggregation requires an explicit implementation of IUnknown on the inner object and
delegation of the IUnknown methods of any other interface to the outer object's IUnknown methods.
STDMETHODIMP_(DWORD) AddRef(void)
{ return m_pUnkOuter->AddRef(); };
STDMETHODIMP_(DWORD) Release(void)
{ return m_pUnkOuter->Release(); };
// ISomeInterface members
STDMETHODIMP SomeMethod(void)
{ return S_OK; };
} ;
CImpSomeInterface m_ImpSomeInterface ;
public:
CSomeObject(IUnknown * pUnkOuter)
{
m_cRef=0;
// No AddRef necessary if non-NULL as we're aggregated.
m_pUnkOuter=pUnkOuter;
m_ImpSomeInterface.m_pUnkOuter=pUnkOuter;
} ;
~CSomeObject(void) {} ;
Aggregating Objects
When developing an aggregable object, the following rules apply:
When creating the inner object, the outer object must explicitly ask for its IUnknown.
The outer object must protect its implementation of Release from reentrancy with an artificial reference
count around its destruction code.
The outer object must call its controlling IUnknown Release method if it queries for a pointer to any of
the inner object's interfaces. To free this pointer, the outer object calls its controlling IUnknown AddRef
method, followed by Release on the inner object's pointer.
The outer object must not blindly delegate a query for any unrecognized interface to the inner object,
unless that behavior is specifically the intention of the outer object.
Related topics
C
o
n
t
a
i
n
m
e
n
t
/
D
e
l
e
g
a
t
i
o
n
The COM Library
1/7/2020 • 2 minutes to read • Edit Online
Any process that uses COM must both initialize and uninitialize the COM library. In addition to being a
specification, COM also implements some important services in this library. Provided as a set of DLLs and EXEs
(primarily Ole32.dll and Rpcss.exe) in Microsoft Windows, the COM library includes the following:
A small number of fundamental functions that facilitate the creation of COM applications, both client and
server. For clients, COM supplies basic functions for creating objects. For servers, COM supplies the means
of exposing their objects.
Implementation-locator services through which COM determines, from a unique class identifier (CLSID ),
which server implements that class and where that server is located. This service includes support for a
level of indirection, usually a system registry, between the identity of an object class and the packaging of
the implementation so that clients are independent of the packaging, which can change in the future.
Transparent remote procedure calls when an object is running in a local or remote server.
A standard mechanism to allow an application to control how memory is allocated within its process,
particularly memory that needs to be passed between cooperating objects so that it can be freed properly.
To use basic COM services, all COM threads of execution in clients and out-of-process servers must call either the
CoInitialize or the CoInitializeEx function before calling any other COM function except memory allocation
calls. CoInitializeEx replaces the other function, adding a parameter that allows you to specify the threading
model of the thread—either apartment-threaded or free-threaded. A call to CoInitialize simply sets the
threading model to apartment-threaded.
OLE compound document applications call the OleInitialize function, which calls CoInitializeEx and also does
some initialization required for compound documents. Therefore, threads that call OleInitialize cannot be free-
threaded. For information on threading in clients and servers, see Processes, Threads, and Apartments.
In-process servers do not call the initialization functions because they are being loaded into a process that has
already done so. As a result, in-process servers must set their threading model in the registry under the
InprocServer32 key. For detailed information on threading issues in in-process servers, see In-Process Server
Threading Issues.
It is also important to uninitialize the library. For each call to CoInitialize or CoInitializeEx, there must be a
corresponding call to CoUninitialize. For each call to OleInitialize, there must be a corresponding call to
OleUninitialize.
In-process servers can assume that the process they are being loaded into has already performed these steps.
Related topics
T
h
e
C
o
m
p
o
n
e
n
t
O
b
j
e
c
t
M
o
d
e
l
Managing Memory Allocation
1/7/2020 • 2 minutes to read • Edit Online
In COM, many, if not most, interface methods are called by code written by one programming organization and
implemented by code written by another. Many of the parameters and return values of these functions are of types
that can be passed around by value. Sometimes, however, it is necessary to pass data structures for which this is
not the case, so it is necessary for both caller and called to have a compatible allocation and de-allocation policy.
COM defines a universal convention for memory allocation, because it is more reasonable than defining case-by-
case rules and so that the COM remote procedure call implementation can correctly manage memory.
The methods of a COM interface always provide memory management of pointers to the interface by calling the
AddRef and Release functions found in the IUnknown interface, from which all other COM interfaces derive.
(See Rules for Managing Reference Counts for more information.)
This section describes only how to allocate memory for parameters that are not passed by value — not pointers to
interfaces, but more mundane things like strings, pointers to structures, and so forth.
For more information, see the following topics:
The OLE Memory Allocator
Memory Management Rules
Debugging Memory Allocations
The OLE Memory Allocator
1/7/2020 • 2 minutes to read • Edit Online
The COM library provides an implementation of a memory allocator that is thread-safe. (That is, it cannot cause
problems in multithreaded situations.) Whenever ownership of an allocated chunk of memory is passed through a
COM interface or between a client and the COM library, you must use this COM allocator to allocate the memory.
Allocation internal to an object can use any allocation scheme desired, but the COM memory allocator is a handy,
efficient, and thread-safe allocator.
A call to the API function CoGetMalloc provides a pointer to the OLE allocator, which is an implementation of the
IMalloc interface. However, it is more efficient to call the helper functions CoTaskMemAlloc,
CoTaskMemRealloc, and CoTaskMemFree, which wrap getting a pointer to the task memory allocator, calling
the corresponding IMalloc method, and then releasing the pointer to the allocator.
Related topics
M
a
n
a
g
i
n
g
M
e
m
o
r
y
A
l
l
o
c
a
t
i
o
n
T
h
e
C
O
M
L
i
b
r
a
r
y
Memory Management Rules
1/7/2020 • 2 minutes to read • Edit Online
The lifetime of pointers to interfaces is always managed through the AddRef and Release methods on every
COM interface. For more information, see Rules for Managing Reference Counts.
For all other parameters, it is important to adhere to certain rules for managing memory. The following rules apply
to all parameters of interface methods—including the return value—that are not passed by value:
In-parameters must be allocated and freed by the caller.
Out-parameters must be allocated by the one called; they are freed by the caller using the standard COM task
memory allocator. See The OLE Memory Allocator for more information.
In/out-parameters are initially allocated by the caller, and then freed and reallocated by the one called, if
necessary. As is true for out parameters, the caller is responsible for freeing the final returned value. The
standard COM memory allocator must be used.
In the latter two cases, where one piece of code allocates the memory and a different piece of code frees it, using
the COM allocator ensures that the two pieces of code are using the same allocation methods.
Another area that needs special attention is the treatment of out and in-out parameters in failure conditions. If a
function returns a failure code, the caller typically has no way to clean up the out or in-out parameters. This leads
to the following additional rules:
In case of an error condition, parameters must always be reliably set to a value that will be cleaned up without
any action by the caller.
All out pointer parameters must explicitly be set to NULL. These are usually passed in a pointer-to-pointer
parameter but can also be passed as members of a structure that the caller allocates and the called code fills.
The most straightforward way to ensure this is (in part) to set these values to NULL on function entry. This rule
is important because it promotes more robust application interoperability.
Under error conditions, all in-out parameters must either be left alone by the code called (thus remaining at the
value to which they were initialized by the caller) or be explicitly set, as in the out parameter error return case.
Remember that these memory management conventions for COM applications apply only across public interfaces
and APIs—there is no requirement at all that memory allocation strictly internal to a COM application need be
done using these mechanisms.
COM internally uses Remote Procedure Calls (RPC ) to communicate between clients and servers. For more
information about managing memory in RPC server stubs, see the Server-stub Memory Management topic.
Related topics
M
a
n
a
g
i
n
g
M
e
m
o
r
y
A
l
l
o
c
a
t
i
o
n
Debugging Memory Allocations
1/7/2020 • 2 minutes to read • Edit Online
COM provides the IMallocSpy interface for developers to use to debug their memory allocations. For each
method in IMalloc, there are two methods in IMallocSpy, a "pre" method and a "post" method. After a developer
implements it and publishes it to the system, the system calls the IMallocSpy "pre" method just before the
corresponding IMalloc method, effectively allowing the debug code to "spy" on the allocation operation, and calls
the "post" method to release the spy.
For example, when COM detects that the next call is a call to IMalloc::Alloc, it calls IMallocSpy::PreAlloc,
executing whatever debug operations the developer wants during the Alloc execution, and then, when the Alloc
call returns, calls IMallocSpy::PostAlloc to release the spy and return control to the code.
Related topics
M
a
n
a
g
i
n
g
M
e
m
o
r
y
A
l
l
o
c
a
t
i
o
n
Processes, Threads, and Apartments
1/7/2020 • 5 minutes to read • Edit Online
A process is a collection of virtual memory space, code, data, and system resources. A thread is code that is to be
serially executed within a process. A processor executes threads, not processes, so each application has at least
one process, and a process always has at least one thread of execution, known as the primary thread. A process
can have multiple threads in addition to the primary thread.
Processes communicate with one another through messages, using Microsoft's Remote Procedure Call (RPC )
technology to pass information to one another. There is no difference to the caller between a call coming from a
process on a remote machine and a call coming from another process on the same machine.
When a thread begins to execute, it continues until it is killed or until it is interrupted by a thread with higher
priority (by a user action or the kernel's thread scheduler). Each thread can run separate sections of code, or
multiple threads can execute the same section of code. Threads executing the same block of code maintain
separate stacks. Each thread in a process shares that process's global variables and resources.
The thread scheduler determines when and how often to execute a thread, according to a combination of the
process's priority class attribute and the thread's base priority. You set a process's priority class attribute by
calling the SetPriorityClass function , and you set a thread's base priority with a call to SetThreadPriority.
Multithreaded applications must avoid two threading problems: deadlocks and races. A deadlock occurs when
each thread is waiting for the other to do something. The COM call control helps prevent deadlocks in calls
between objects. A race condition occurs when one thread finishes before another on which it depends, causing
the former to use an uninitialized value because the latter has not yet supplied a valid one. COM supplies some
functions specifically designed to help avoid race conditions in out-of-process servers. (See Out-of-Process
Server Implementation Helpers.)
NOTE
Using multiple threads is not a guarantee of better performance. In fact, because thread factoring is a difficult problem,
using multiple threads often causes performance problems. The key is to use multiple threads only if you are very sure of
what you are doing.
In general, the simplest way to view the COM threading architecture is to think of all the COM objects in the
process as divided into groups called apartments. A COM object lives in exactly one apartment, in the sense that
its methods can legally be directly called only by a thread that belongs to that apartment. Any other thread that
wants to call the object must go through a proxy.
There are two types of apartments: single-threaded apartments, and multithreaded apartments.
Single-threaded apartments consist of exactly one thread, so all COM objects that live in a single-threaded
apartment can receive method calls only from the one thread that belongs to that apartment. All method calls
to a COM object in a single-threaded apartment are synchronized with the windows message queue for the
single-threaded apartment's thread. A process with a single thread of execution is simply a special case of this
model.
Multithreaded apartments consist of one or more threads, so all COM objects that live in an multithreaded
apartment can receive method calls directly from any of the threads that belong to the multithreaded
apartment. Threads in a multithreaded apartment use a model called free-threading. Calls to COM objects in
a multithreaded apartment are synchronized by the objects themselves.
NOTE
For a description of communication between single-threaded apartments and multithreaded apartments within the same
process, see Single-Threaded and Multithreaded Communication.
A process can have zero or more single-threaded apartments and zero or one multithreaded apartment.
In a process, the main apartment is the first to be initialized. In a single-threaded process, this is the only
apartment. Call parameters are marshaled between apartments, and COM handles the synchronization through
messaging. If you designate multiple threads in a process to be free-threaded, all free threads reside in a single
apartment, parameters are passed directly to any thread in the apartment, and you must handle all
synchronization. In a process with both free-threading and apartment threading, all free threads reside in a
single apartment and all other apartments are single-threaded apartments. A process that does COM work is a
collection of apartments with, at most, one multithreaded apartment but any number of single-threaded
apartments.
The threading models in COM provide the mechanism for clients and servers that use different threading
architectures to work together. Calls among objects with different threading models in different processes are
naturally supported. From the perspective of the calling object, all calls to objects outside a process behave
identically, no matter how the object being called is threaded. Likewise, from the perspective of the object being
called, arriving calls behave identically, regardless of the threading model of the caller.
Interaction between a client and an out-of-process object is straightforward, even when they use different
threading models because the client and object are in different processes. COM, interposed between the client
and the server, can provide the code for the threading models to interoperate, using standard marshaling and
RPC. For example, if a single-threaded object is called simultaneously by multiple free-threaded clients, the calls
will be synchronized by COM by placing corresponding window messages in the server's message queue. The
object's apartment will receive one call each time it retrieves and dispatches messages. However, some care
must be taken to ensure that in-process servers interact properly with their clients. (See In-Process Server
Threading Issues.)
The most important issue in programming with a multithreaded model is to make your code thread-safe so that
messages intended for a particular thread go only to that thread and access to threads is protected.
For more information, see the following topics:
Choosing the Threading Model
Single-Threaded Apartments
Multithreaded Apartments
Single-Threaded and Multithreaded Communication
In-Process Server Threading Issues
Accessing Interfaces Across Apartments
Choosing the Threading Model
1/7/2020 • 2 minutes to read • Edit Online
Choosing the threading model for an object depends on the object's function. An object that does extensive I/O
might support free-threading to provide maximum response to clients by allowing interface calls during I/O
latency. On the other hand, an object that interacts with the user might support apartment threading to
synchronize incoming COM calls with its window operations.
It is easier to support apartment threading in single-threaded apartments because COM provides synchronization
on a per-call basis. Supporting free-threading is more difficult because the object must implement
synchronization; however, response to clients may be better because synchronization can be implemented for
smaller sections of code.
Related topics
A
c
c
e
s
s
i
n
g
I
n
t
e
r
f
a
c
e
s
A
c
r
o
s
s
A
p
a
r
t
m
e
n
t
s
M
u
l
t
i
t
h
r
e
a
d
e
d
A
p
a
r
t
m
e
n
t
s
I
n
-
P
r
o
c
e
s
s
S
e
r
v
e
r
T
h
r
e
a
d
i
n
g
I
s
s
u
e
s
P
r
o
c
e
s
s
e
s
,
T
h
r
e
a
d
s
,
a
n
d
A
p
a
r
t
m
e
n
t
s
S
i
n
g
l
e
-
T
h
r
e
a
d
e
d
a
n
d
M
u
l
t
i
t
h
r
e
a
d
e
d
C
o
m
m
u
n
i
c
a
t
i
o
n
S
i
n
g
l
e
-
T
h
r
e
a
d
e
d
A
p
a
r
t
m
e
n
t
s
Single-Threaded Apartments
1/7/2020 • 5 minutes to read • Edit Online
Using single-threaded apartments (the apartment model process) offers a message-based paradigm for dealing
with multiple objects running concurrently. It enables you to write more efficient code by allowing a thread, while
it waits for some time-consuming operation to complete, to allow another thread to be executed.
Each thread in a process that is initialized as an apartment model process, and that retrieves and dispatches
window messages, is a single-threaded apartment thread. Each thread lives within its own apartment. Within an
apartment, interface pointers can be passed without marshaling, and therefore, all objects in one single-threaded
apartment thread communicate directly.
A logical grouping of related objects that all execute on the same thread, and therefore must have synchronous
execution, could live on the same single-threaded apartment thread. However, an apartment model object cannot
reside on more than one thread. Calls to objects in other processes must be made within the context of the
owning process, so distributed COM switches threads for you automatically when you call on a proxy.
The interprocess and interthread models are similar. When it is necessary to pass an interface pointer to an object
in another apartment (on another thread) within the same process, you use the same marshaling model that
objects in different processes use to pass pointers across process boundaries. By getting a pointer to the standard
marshaling object, you can marshal interface pointers across thread boundaries (between apartments) in the
same way you do between processes. (Interface pointers must be marshaled when passed between apartments.)
Rules for single-threaded apartments are simple, but it is important to follow them carefully:
Every object should live on only one thread (within a single-threaded apartment).
Initialize the COM library for each thread.
Marshal all pointers to objects when passing them between apartments.
Each single-threaded apartment must have a message loop to handle calls from other processes and
apartments within the same process. Single-threaded apartments without objects (client only) also need a
message loop to dispatch the broadcast messages that some applications use.
DLL -based or in-process objects do not call the COM initialization functions; instead, they register their
threading model with the ThreadingModel named-value under the InprocServer32 key in the registry.
Apartment-aware objects must also write DLL entry points carefully. There are special considerations that
apply to threading in-process servers. For more information, see In-Process Server Threading Issues.
While multiple objects can live on a single thread, no apartment model object can live on more than one thread.
Each thread of a client process or out-of-process server must call CoInitialize, or call CoInitializeEx and specify
COINIT_APARTMENTTHREADED for the dwCoInit parameter. The main apartment is the thread that calls
CoInitializeEx first. For information on in-process servers, see In-Process Server Threading Issues.
All calls to an object must be made on its thread (within its apartment). It is forbidden to call an object directly
from another thread; using objects in this free-threaded manner could cause problems for applications. The
implication of this rule is that all pointers to objects must be marshaled when passed between apartments. COM
provides the following two functions for this purpose:
CoMarshalInterThreadInterfaceInStream marshals an interface into a stream object that is returned to the
caller.
CoGetInterfaceAndReleaseStream unmarshals an interface pointer from a stream object and releases it.
These functions wrap calls to CoMarshalInterface and CoUnmarshalInterface functions, which require the
use of the MSHCTX_INPROC flag.
In general, the marshaling is accomplished automatically by COM. For example, when passing an interface
pointer as a parameter in a method call on a proxy to an object in another apartment, or when calling
CoCreateInstance, COM does the marshaling automatically. However, in some special cases, where the
application writer is passing interface pointers between apartments without using the normal COM mechanisms,
the writer must handle the marshaling manually.
If one apartment (Apartment 1) in a process has an interface pointer and another apartment (Apartment 2)
requires its use, Apartment 1 must call CoMarshalInterThreadInterfaceInStream to marshal the interface. The
stream that is created by this function is thread-safe and must be stored in a variable that is accessible by
Apartment 2. Apartment 2 must pass this stream to CoGetInterfaceAndReleaseStream to unmarshal the
interface and will get back a pointer to a proxy through which it can access the interface. The main apartment
must remain alive until the client has completed all COM work (because some in-process objects are loaded in
the main apartment, as described in In-Process Server Threading Issues). After one object has been passed
between threads in this manner, it is very easy to pass interface pointers as parameters. That way, distributed
COM does the marshaling and thread switching for the application.
To handle calls from other processes and apartments within the same process, each single-threaded apartment
must have a message loop. This means that the thread's work function must have a
GetMessage/DispatchMessage loop. If other synchronization primitives are being used to communicate between
threads, the MsgWaitForMultipleObjects function can be used to wait both for messages and for thread
synchronization events. The documentation for this function has an example of this sort of combination loop.
COM creates a hidden window using the Windows class "OleMainThreadWndClass" in each single-threaded
apartment. A call to an object is received as a window message to this hidden window. When the object's
apartment retrieves and dispatches the message, the hidden window will receive it. The window procedure will
then call the corresponding interface method of the object.
When multiple clients call an object, the calls are queued in the message queue and the object will receive a call
each time its apartment retrieves and dispatches messages. Because the calls are synchronized by COM and the
calls are always delivered by the thread that belongs to the object's apartment, the object's interface
implementations need not provide synchronization. Single-threaded apartments can implement IMessageFilter
to permit them to cancel calls or receive window messages when necessary.
The object can be reentered if one of its interface method implementations retrieves and dispatches messages or
makes an ORPC call to another thread, thereby causing another call to be delivered to the object (by the same
apartment). OLE does not prevent reentrancy on the same thread, but it can help provide thread safety. This is
identical to the way in which a window procedure can be reentered if it retrieves and dispatches messages while
processing a message. However, calling an out-of-process single-threaded apartment server that calls another
single-threaded apartment server will allow the first server to be reentered.
Related topics
A
c
c
e
s
s
i
n
g
I
n
t
e
r
f
a
c
e
s
A
c
r
o
s
s
A
p
a
r
t
m
e
n
t
s
C
h
o
o
s
i
n
g
t
h
e
T
h
r
e
a
d
i
n
g
M
o
d
e
l
M
u
l
t
i
t
h
r
e
a
d
e
d
A
p
a
r
t
m
e
n
t
s
I
n
-
P
r
o
c
e
s
s
S
e
r
v
e
r
T
h
r
e
a
d
i
n
g
I
s
s
u
e
s
P
r
o
c
e
s
s
e
s
,
T
h
r
e
a
d
s
,
a
n
d
A
p
a
r
t
m
e
n
t
s
S
i
n
g
l
e
-
T
h
r
e
a
d
e
d
a
n
d
M
u
l
t
i
t
h
r
e
a
d
e
d
C
o
m
m
u
n
i
c
a
t
i
o
n
Multithreaded Apartments
1/7/2020 • 4 minutes to read • Edit Online
In a multithreaded apartment model, all the threads in the process that have been initialized as free-threaded
reside in a single apartment. Therefore, there is no need to marshal between threads. The threads need not
retrieve and dispatch messages because COM does not use window messages in this model.
Calls to methods of objects in the multithreaded apartment can be run on any thread in the apartment. There is
no serialization of calls; many calls may occur to the same method or to the same object simultaneously. Objects
created in the multithreaded apartment must be able to handle calls on their methods from other threads at any
time.
Because calls to objects are not serialized in any way, multithreaded object concurrency offers the highest
performance and takes the best advantage of multiprocessor hardware for cross-thread, cross-process, and cross-
machine calling. This means, however, that the code for objects must provide synchronization in their interface
implementations, typically through the use of synchronization primitives such as event objects, critical sections,
mutexes, or semaphores, which are described later in this section. In addition, because the object doesn't control
the lifetime of the threads that are accessing it, no thread-specific state may be stored in the object (in thread local
storage).
Following are some important considerations regarding synchronization for multithreaded apartments:
COM provides call synchronization for single-threaded apartments only.
Multithreaded apartments do not receive calls while making calls (on the same thread).
Multithreaded apartments cannot make input-synchronized calls.
Asynchronous calls are converted to synchronous calls in multithreaded apartments.
The message filter is not called for any thread in a multithreaded apartment.
To initialize a thread as free-threaded, call CoInitializeEx, specifying COINIT_MULTITHREADED. For
information on in-process server threading, see In-Process Server Threading Issues.
Multiple clients can simultaneously call, from different threads, an object that supports free-threading. In free-
threaded out-of-process servers, COM, through the RPC subsystem, creates a pool of threads in the server
process and a client call (or multiple client calls) can be delivered by any of these threads at any time. An out-of-
process server must also implement synchronization in its class factory. Free-threaded, in-process objects can
receive direct calls from multiple threads of the client.
The client can do COM work in multiple threads. All threads belong to the same multithreaded apartment.
Interface pointers are passed directly from thread to thread within a multithreaded apartment, so interface
pointers are not marshaled between its threads. Message filters (implementations of IMessageFilter) are not
used in multithreaded apartments. The client thread will suspend when it makes a COM call to out-of-apartment
objects and will resume when the call returns. Calls between processes are still handled by RPC.
Threads initialized with the free-threaded model must implement their own synchronization. As mentioned earlier
in this section, Windows enables this implementation through the following synchronization primitives:
Event objects provide a way of signaling one or more threads that an event has occurred. Any thread within a
process can create an event object. A handle to the event is returned by the event-creating function,
CreateEvent. Once an event object has been created, threads with a handle to the object can wait on it before
continuing execution.
Critical sections are used for a section of code that requires exclusive access to some set of shared data before
it can be executed and that is used only by the threads within a single process. A critical section is like a
turnstile through which only one thread at a time may pass, working as follows:
To ensure that no more than one thread at a time accesses shared data, a process's primary thread
allocates a global CRITICAL_SECTION data structure and initializes its members. A thread entering a
critical section calls the EnterCriticalSection function and modifies the data structure's members.
A thread attempting to enter a critical section calls EnterCriticalSection which checks to see whether
the CRITICAL_SECTION data structure has been modified. If so, another thread is currently in the
critical section and the subsequent thread is put to sleep. A thread leaving a critical section calls
LeaveCriticalSection, which resets the data structure. When a thread leaves a critical section, the
system wakes one of the sleeping threads, which then enters the critical section.
Mutexes performs the same function as a critical section, except that the mutex is accessible to threads running
in different processes. Owning a mutex object is like having the floor in a debate. A process creates a mutex
object by calling the CreateMutex function, which returns a handle. The first thread requesting a mutex object
obtains ownership of it. When the thread has finished with the mutex, ownership passes to other threads on a
first-come, first-served basis.
Semaphores are used to maintain a reference count on some available resource. A thread creates a semaphore
for a resource by calling the CreateSemaphore function and passing a pointer to the resource, an initial
resource count, and the maximum resource count. This function returns a handle. A thread requesting a
resource passes its semaphore handle in a call to the WaitForSingleObject function. The semaphore object
polls the resource to determine whether it is available. If so, the semaphore decrements the resource count
and wakes the waiting thread. If the count is zero, the thread remains asleep until another thread releases a
resource, causing the semaphore to increment the count to one.
Related topics
A
c
c
e
s
s
i
n
g
I
n
t
e
r
f
a
c
e
s
A
c
r
o
s
s
A
p
a
r
t
m
e
n
t
s
C
h
o
o
s
i
n
g
t
h
e
T
h
r
e
a
d
i
n
g
M
o
d
e
l
I
n
-
P
r
o
c
e
s
s
S
e
r
v
e
r
T
h
r
e
a
d
i
n
g
I
s
s
u
e
s
P
r
o
c
e
s
s
e
s
,
T
h
r
e
a
d
s
,
a
n
d
A
p
a
r
t
m
e
n
t
s
S
i
n
g
l
e
-
T
h
r
e
a
d
e
d
a
n
d
M
u
l
t
i
t
h
r
e
a
d
e
d
C
o
m
m
u
n
i
c
a
t
i
o
n
S
i
n
g
l
e
-
T
h
r
e
a
d
e
d
A
p
a
r
t
m
e
n
t
s
Single-Threaded and Multithreaded Communication
1/7/2020 • 2 minutes to read • Edit Online
A client or server that supports both single-threaded and multithreaded apartments will have one multithreaded
apartment, containing all threads initialized as free-threaded, and one or more single-threaded apartments.
Interface pointers must be marshaled between apartments but can be used without marshaling within an
apartment. Calls to objects in a single-threaded apartment will be synchronized by COM. Calls to objects in the
multithreaded apartment will not be synchronized by COM.
All of the information on single-threaded apartments applies to the threads marked as apartment model, and all
of the information on multithreaded apartments applies to all of the threads marked as free-threaded. Apartment
threading rules apply to inter-apartment communication, requiring that interface pointers be marshaled between
apartments with calls to CoMarshalInterThreadInterfaceInStream and CoGetInterfaceAndReleaseStream,
as described in Single-Threaded Apartments.
NOTE
Some special considerations apply when dealing with in-process servers. For more information, see In-Process Server
Threading Issues.
Related topics
A
c
c
e
s
s
i
n
g
I
n
t
e
r
f
a
c
e
s
A
c
r
o
s
s
A
p
a
r
t
m
e
n
t
s
C
h
o
o
s
i
n
g
t
h
e
T
h
r
e
a
d
i
n
g
M
o
d
e
l
M
u
l
t
i
t
h
r
e
a
d
e
d
A
p
a
r
t
m
e
n
t
s
I
n
-
P
r
o
c
e
s
s
S
e
r
v
e
r
T
h
r
e
a
d
i
n
g
I
s
s
u
e
s
P
r
o
c
e
s
s
e
s
,
T
h
r
e
a
d
s
,
a
n
d
A
p
a
r
t
m
e
n
t
s
S
i
n
g
l
e
-
T
h
r
e
a
d
e
d
A
p
a
r
t
m
e
n
t
s
In-Process Server Threading Issues
1/7/2020 • 5 minutes to read • Edit Online
An in-process server does not call CoInitialize, CoInitializeEx, or OleInitialize to mark its threading model.
For thread-aware DLL -based or in-process objects, you need to set the threading model in the registry. The
default model when you do not specify a threading model is single-thread-per-process. To specify a model, you
add the ThreadingModel value to the InprocServer32 key in the registry.
DLLs that support instantiation of a class object must implement and export the functions DllGetClassObject
and DllCanUnloadNow. When a client wants an instance of the class the DLL supports, a call to
CoGetClassObject (either directly or through a call to CoCreateInstance) calls DllGetClassObject to get a
pointer to its class object when the object is implemented in a DLL. DllGetClassObject should therefore be
able to give away multiple class objects or a single thread-safe object (essentially just using
InterlockedIncrement/InterlockedDecrement on their internal reference counts).
As its name implies, DllCanUnloadNow is called to determine whether the DLL that implements it is in use,
enabling the caller to safely unload it if it is not. Calls to CoFreeUnusedLibraries from any thread always route
through the main apartment's thread to call DllCanUnloadNow.
Like other servers, in-process servers can be single-threaded, apartment-threaded, or free-threaded. These
servers can be used by any OLE client, regardless of the threading model used by that client.
All combinations of threading model interoperability are allowed between clients and in-process objects.
Interaction between a client and an in-process object that use different threading models is exactly like the
interaction between clients and out-of-process servers. For an in-process server, when the threading model of
the client and in-process server differ, COM must interpose itself between the client and the object.
When an in-process object that supports the single-threaded model is called simultaneously by multiple
threads of a client, COM cannot allow the client threads to directly access the object's interface—the object was
not designed for such access. Instead, COM must ensure that calls are synchronized and are made only by the
client thread that created the object. Therefore, COM creates the object in the client's main apartment and
requires all the other client apartments to access the object by using proxies.
When a free-threaded apartment (multithreaded apartment model) in a client creates an apartment-threaded
in-process server, COM spins up a single-threaded apartment model "host" thread in the client. This host thread
will create the object, and the interface pointer will be marshaled back to the client's free-threaded apartment.
Similarly, when a single-threaded apartment in an apartment-model client creates a free-threaded in-process
server, COM spins up a free-threaded host thread (multithreaded apartment on which the object will be created
and then marshaled back to the client single-threaded apartment).
NOTE
In general, if you design a custom interface on an in-process server, you should also provide the marshaling code for it so
that COM can marshal the interface between client apartments.
COM helps protect access to objects provided by a single-threaded DLL by requiring access from the same
client apartment in which they were created. In addition, all of the DLL entry points (like DllGetClassObject
and DllCanUnloadNow) and global data should always be accessed by the same apartment. COM creates
such objects in the main apartment of the client, giving the main apartment direct access to the object's
pointers. Calls from the other apartments use interthread marshaling to go from the proxy to the stub in the
main apartment and then to the object. This allows COM to synchronize calls to the object. Interthread calls are
slow, so it is recommended that these servers be rewritten to support multiple apartments.
Like a single-threaded in-process server, an object provided by an apartment model DLL must be accessed by
the same client apartment from which it was created. However, objects provided by this server can be created in
multiple apartments of the client, so the server must implement its entry points (like DllGetClassObject and
DllCanUnloadNow) for multithreaded use. For example, if two apartments of a client try to create two
instances of the in-process object simultaneously, DllGetClassObject can be called simultaneously by both
apartments. DllCanUnloadNow must be written so that the DLL does not unload while code is still executing
in the DLL.
If the DLL provides only one instance of the class factory to create all the objects, the class factory
implementation must also be designed for multithreaded use, because it will be accessed by multiple client
apartments. If the DLL creates a new instance of the class factory each time DllGetClassObject is called, the
class factory need not be thread-safe.
Objects created by the class factory need not be thread-safe. Once created by a thread, the object is always
accessed through that thread and all calls to the object are synchronized by COM. The apartment model
apartment of a client that creates this object will get a direct pointer to the object. Client apartments that are
different from the apartment in which the object was created must access the object through proxies. These
proxies are created when the client marshals the interface between its apartments.
When an in-process DLL ThreadingModel value is set to "Both", an object provided by this DLL can be
created and used directly (without a proxy) in single-threaded or multithreaded client apartments. However, it
can be used directly only within the apartment in which it was created. To give the object to any other
apartment, the object must be marshaled. The DLL object must implement its own synchronization and can be
accessed by multiple client apartments at the same time.
To speed performance for free-threaded access to in-process DLL objects, COM provides the
CoCreateFreeThreadedMarshaler function. This function creates a free-threaded marshaling object that can
be aggregated with an in-process server object. When a client apartment in the same process needs access to
an object in another apartment, aggregating the free-threaded marshaler provides the client with a direct
pointer to the server object, rather than to a proxy, when the client marshals the object's interface to a different
apartment. The client does not need to do any synchronization. This works only within the same
process—standard marshaling is used for a reference to the object that is sent to another process.
An object provided by an in-process DLL that supports only free threading is a free-threaded object. It
implements its own synchronization and can be accessed by multiple client threads at the same time. This
server does not marshal interfaces between threads, so this server can be created and used directly (without a
proxy) only by multithreaded apartments in a client. Single-threaded apartments that create it will access it
through a proxy.
Related topics
A
c
c
e
s
s
i
n
g
I
n
t
e
r
f
a
c
e
s
A
c
r
o
s
s
A
p
a
r
t
m
e
n
t
s
C
h
o
o
s
i
n
g
t
h
e
T
h
r
e
a
d
i
n
g
M
o
d
e
l
M
u
l
t
i
t
h
r
e
a
d
e
d
A
p
a
r
t
m
e
n
t
s
P
r
o
c
e
s
s
e
s
,
T
h
r
e
a
d
s
,
a
n
d
A
p
a
r
t
m
e
n
t
s
S
i
n
g
l
e
-
T
h
r
e
a
d
e
d
a
n
d
M
u
l
t
i
t
h
r
e
a
d
e
d
C
o
m
m
u
n
i
c
a
t
i
o
n
S
i
n
g
l
e
-
T
h
r
e
a
d
e
d
A
p
a
r
t
m
e
n
t
s
Accessing Interfaces Across Apartments
1/7/2020 • 2 minutes to read • Edit Online
COM provides a way for any apartment in a process to get access to an interface implemented on an object in
any other apartment in the process. This is done through the IGlobalInterfaceTable interface. This interface has
three methods, which allow you to do the following:
Register an interface as a global (processwide) interface.
Get a pointer to that interface from any other apartment through a cookie.
Revoke the global registration of an interface.
The IGlobalInterfaceTable interface is an efficient way for a process to store an interface pointer in a memory
location that can be accessed from multiple apartments within the process, such as process-wide variables and
agile objects (free-threaded, marshaled objects) containing interface pointers to other objects.
An agile object is unaware of the underlying COM infrastructure in which it runs; in other words, what apartment,
context, and thread it is executing on. The object may be holding on to interfaces that are specific to an apartment
or context. For this reason, calling these interfaces from wherever the agile component is executing might not
always work properly. The global interface table avoids this problem by guaranteeing that a valid proxy (or direct
pointer) to the object is used, based on where the agile object is executing.
NOTE
The global interface table is not portable across process or machine boundaries, so it cannot be used in place of the normal
parameter-passing mechanism.
For information about creating and using a global interface table, see the following topics:
Creating the Global Interface Table
When to Use the Global Interface Table
Related topics
C
h
o
o
s
i
n
g
t
h
e
T
h
r
e
a
d
i
n
g
M
o
d
e
l
M
u
l
t
i
t
h
r
e
a
d
e
d
A
p
a
r
t
m
e
n
t
s
I
n
-
P
r
o
c
e
s
s
S
e
r
v
e
r
T
h
r
e
a
d
i
n
g
I
s
s
u
e
s
P
r
o
c
e
s
s
e
s
,
T
h
r
e
a
d
s
,
a
n
d
A
p
a
r
t
m
e
n
t
s
S
i
n
g
l
e
-
T
h
r
e
a
d
e
d
a
n
d
M
u
l
t
i
t
h
r
e
a
d
e
d
C
o
m
m
u
n
i
c
a
t
i
o
n
S
i
n
g
l
e
-
T
h
r
e
a
d
e
d
A
p
a
r
t
m
e
n
t
s
Creating the Global Interface Table
1/7/2020 • 2 minutes to read • Edit Online
Use the following call to create the global interface table object and get a pointer to IGlobalInterfaceTable:
HRESULT hr;
hr = CoCreateInstance(CLSID_StdGlobalInterfaceTable,
NULL,
CLSCTX_INPROC_SERVER,
IID_IGlobalInterfaceTable,
(void **)&gpGIT);
if (hr != S_OK) {
exit(0); // Handle errors here.
}
NOTE
When creating the global interface table object using the preceding call, it is necessary to link to the library uuid.lib. This will
resolve the external symbols CLSID_StdGlobalInterfaceTable and IID_IGlobalInterfaceTable.
There is a single instance of the global interface table per process, so all calls to this function in a process return the
same instance.
After the call to the CoCreateInstance function, register the interface from the apartment in which it resides with
a call to the RegisterInterfaceInGlobal method. This method supplies a cookie that identifies the interface and its
location. An apartment seeking a pointer to this interface then calls the GetInterfaceFromGlobal method with
this cookie, and the implementation then supplies an interface pointer to the calling apartment. To revoke the
interface's global registration, any apartment can call the RevokeInterfaceFromGlobal method.
A simple example of using IGlobalInterfaceTable would be when you want to pass an interface pointer on an
object in a single-threaded apartment (STA) to a worker thread in another apartment. Rather than having to
marshal it into a stream and pass the stream to the worker thread as a thread parameter, IGlobalInterfaceTable
allows you simply to pass a cookie.
When you register the interface in the global interface table, you get a cookie that you can use instead of passing
the actual pointer (whenever you need to pass the pointer), either to a nonmethod parameter that is going to
another apartment (as a parameter to ThreadProc through CreateThread) or to in-process memory accessible
outside your apartment.
Care is required because using global interfaces places the extra burden on the programmer of managing
problems such as race conditions and mutual exclusion, which are associated with accessing global state from
multiple threads simultaneously.
COM provides a standard implementation of the IGlobalInterfaceTable interface. It is highly recommended that
you use this standard implementation because it provides complete thread-safe functionality.
Related topics
W
h
e
n
t
o
U
s
e
t
h
e
G
l
o
b
a
l
I
n
t
e
r
f
a
c
e
T
a
b
l
e
When to Use the Global Interface Table
1/7/2020 • 2 minutes to read • Edit Online
If you are unmarshaling an interface pointer multiple times between apartments in a process, you might use the
IGlobalInterfaceTable interface. With other techniques, you would have to remarshal each time.
NOTE
If the interface pointer is unmarshaled only once, you may want to use the CoMarshalInterThreadInterfaceInStream
function. It can also be used to pass an interface pointer from one thread to another thread in the same process.
The IGlobalInterfaceTable interface also makes another previously difficult problem simpler for the
programmer. This problem occurs when the following conditions apply:
An in-process agile object aggregates the free-threaded marshaler.
This same agile object also holds (as member variables) interface pointers to other objects that are not agile
and do not aggregate the free-threaded marshaler.
In this situation, if the outer object gets marshaled to another apartment and the application calls on it, and the
object tries to call on any of its member variable interface pointers that are not free-threaded or are proxies to
objects in other apartments, it might get incorrect results or the error RPC_E_WRONG_THREAD. This error
occurs because the inner interface is designed to be callable only from the apartment in which it was first stored in
the member variable.
To solve this problem, the outer object aggregating the free-threaded marshaler should call
IGlobalInterfaceTable::RegisterInterfaceInGlobal on the inner interface and store the resulting cookie in its
member variable, instead of storing the actual interface pointer. When the outer object wants to call on an inner
object's interface pointer, it should call IGlobalInterfaceTable::GetInterfaceFromGlobal, use the returned
interface pointer, and then release it. When the outer object goes away, it should call
IGlobalInterfaceTable::RevokeInterfaceFromGlobal to remove the interface from the global interface table.
Related topics
C
r
e
a
t
i
n
g
t
h
e
G
l
o
b
a
l
I
n
t
e
r
f
a
c
e
T
a
b
l
e
COM Clients and Servers
1/7/2020 • 2 minutes to read • Edit Online
A critical aspect of COM is how clients and servers interact. A COM client is whatever code or object gets a
pointer to a COM server and uses its services by calling the methods of its interfaces. A COM server is any object
that provides services to clients; these services are in the form of COM interface implementations that can be
called by any client that is able to get a pointer to one of the interfaces on the server object.
There are two main types of servers, in-process and out-of-process. In-process servers are implemented in a
dynamic linked library (DLL ), and out-of-process servers are implemented in an executable file (EXE ). Out-of-
process servers can reside either on the local computer or on a remote computer. In addition, COM provides a
mechanism that allows an in-process server (a DLL ) to run in a surrogate EXE process to gain the advantage of
being able to run the process on a remote computer. For more information, see DLL Surrogates.
The COM programming model and constructs have now been extended so that COM clients and servers can
work together across the network, not just within a given computer. This enables existing applications to interact
with new applications and with each other across networks with proper administration, and new applications can
be written to take advantage of networking features.
COM client applications do not need to be aware of how server objects are packaged, whether they are packaged
as in-process objects (in DLLs) or as local or remote objects (in EXEs). Distributed COM further allows objects to
be packaged as service applications, synchronizing COM with the rich administrative and system-integration
capabilities of Windows.
NOTE
Throughout this documentation the acronym COM is used in preference to DCOM. This is because DCOM is not
separate;it is just COM with a longer wire. In cases where what is being described is specifically a remote operation, the
term distributed COM is used.
COM is designed to make it possible to add the support for location transparency that extends across a network.
It allows applications written for single computers to run across a network and provides features that extend
these capabilities and add to the security necessary in a network. (For more information, see Security in COM.)
COM specifies a mechanism by which the class code can be used by many different applications.
For more information, see the following topics:
Getting a Pointer to an Object
Creating an Object Through a Class Object
COM Server Responsibilities
Persistent Object State
Providing Class Information
Inter-Object Communication
Related topics
C
a
l
l
S
y
n
c
h
r
o
n
i
z
a
t
i
o
n
S
e
c
u
r
i
t
y
i
n
C
O
M
Getting a Pointer to an Object
1/7/2020 • 2 minutes to read • Edit Online
Because COM does not have a strict class model, there are four ways that a client can instantiate or get a pointer to
an interface on an object:
Call a COM library function that creates an object of a predetermined type—that is, the function will return a
pointer to only one specific interface for a specific object class.
Call a COM library function that can create an object based on a class identifier (CLSID ) and that returns any
type of interface pointer requested.
Call a method of some interface that creates another object (or connects to an existing one) and returns an
interface pointer on that separate object.
Implement an object with an interface through which other objects pass their interface pointer to the client
directly.
For information on getting pointers to other interfaces on an object after you have the first one, see
QueryInterface: Navigating in an Object.
Related topics
C
O
M
C
l
i
e
n
t
s
a
n
d
S
e
r
v
e
r
s
C
O
M
S
e
r
v
e
r
R
e
s
p
o
n
s
i
b
i
l
i
t
i
e
s
Creating an Object Through a Class Object
1/7/2020 • 2 minutes to read • Edit Online
With the increasing importance of computer networks, it has become necessary for clients and servers to interact
easily and efficiently, whether they reside on the same machine or across a network. Crucial to this is a client's
ability to launch a server, create an instance of the server's object, and have access to the methods of the interfaces
on the object.
COM provides extensions to this basic COM process that make it virtually seamless across a network. If a client is
able to identify the server through its CLSID, calling a few simple functions permit COM to do all the work of
locating and launching the server and activating the object. Subkeys in the registry allow remote servers to
register their location, so the client does not require that information. For applications that want to take advantage
of networking features, the COM object creation functions allow more flexibility and efficiency.
For more information, see the following topics:
COM Class Objects and CLSIDs
Locating a Remote Object
Instance Creation Helper Functions
Related topics
C
O
M
C
l
i
e
n
t
s
a
n
d
S
e
r
v
e
r
s
COM Class Objects and CLSIDs
1/7/2020 • 3 minutes to read • Edit Online
A COM server is implemented as a COM class. A COM class is an implementation of a group of interfaces in code
executed whenever you interact with a given object. There is an important distinction between a C++ class and a
COM class: In C++, a class is a type, while a COM class is simply a definition of the object and carries no type,
although a C++ programmer might implement it by using a C++ class. COM is designed to allow a class to be
used by different applications, including applications written without knowledge of that particular class's existence.
Therefore, class code for a given type of object exists either in a dynamic linked library (DLL ) or in another
executable application (EXE ).
Each COM class is identified by a CLSID, a unique 128-bit GUID, which the server must register. COM uses this
CLSID, at the request of a client, to associate specific data with the DLL or EXE containing the code that
implements the class, thus creating an instance of the object.
For clients and servers on the same computer, the CLSID of the server is all the client ever needs. On each
computer, COM maintains a database (it makes use of the system registry on Microsoft Windows and Macintosh
platforms) of all the CLSIDs for the servers installed on the system. This is a mapping between each CLSID and
the location of the DLL or EXE that houses the code for that CLSID. COM consults this database whenever a client
wants to create an instance of a COM class and use its services, so the client never needs to know the absolute
location of the code on the computer.
For distributed systems, COM provides registry entries that allow a remote server to register itself for use by a
client. While applications need know only a server's CLSID, because they can rely on the registry to locate the
server, COM allows clients to override registry entries and to specify server locations, to take full advantage of the
network. (See Locating a Remote Object.)
The basic way to create an instance of a class is through a COM class object. This is simply an intermediate object
that supports functions common to creating new instances of a given class. Most class objects used to create
objects from a CLSID support the IClassFactory interface, an interface that includes the important
CreateInstance method. You implement an IClassFactory interface for each class of object that you offer to be
instantiated. (For more information about implementing IClassFactory, see Implementing IClassFactory.)
NOTE
Servers that support some other custom class factory interface are not required to support IClassFactory specifically.
However, calls to activation functions other than CoGetClassObject (such as CoCreateInstanceEx) require that the server
support IClassFactory.
When a client wants to create an instance of the server's object, it uses the desired object's CLSID in a call to
CoGetClassObject. (This call can be either direct or implicit, through one of the object creation helper functions.)
This function locates the code associated with the CLSID, and creates a class object, and supplies a pointer to the
interface requested. (CoGetClassObject takes a riid param that specifies the client's desired interface pointer.)
NOTE
COM has just a few functions upon which many of the others are built. The most important of these is probably
CoGetClassObject, which underlies all of the instance creation functions.
With this pointer, the caller can create an instance of the object and retrieve a pointer to a requested interface on
the object. This is usually an initialization interface, used to activate the object (put it in the running state) so that
the client can do whatever work with the object that it wants to. Using COM's basic functions, the client must also
take care to release all object pointers.
Another mechanism for activating object instances is through the class moniker. Class monikers bind to the class
object of the class for which they are created. For more information, see Class Monikers.
COM provides several helper functions that reduce the work of creating object instances. These are described in
Instance Creation Helper Functions.
Related topics
C
r
e
a
t
i
n
g
a
n
O
b
j
e
c
t
T
h
r
o
u
g
h
a
C
l
a
s
s
O
b
j
e
c
t
Locating a Remote Object
1/7/2020 • 2 minutes to read • Edit Online
With the advent of COM for distributed systems, COM uses the basic model for object creation described in COM
Class Objects and CLSIDs and adds more than one way to locate an object that might reside on another system in
a network, without overburdening the client application.
COM has added registry keys that permit a server to register the name of the machine on which it resides or the
machine where an existing storage is located. Therefore, client applications need know only the CLSID of the
server.
However, for cases where it is desired, COM has replaced a previously reserved parameter of CoGetClassObject
with a COSERVERINFO structure, which allows a client to specify the location of a server. Another important
value in the CoGetClassObject function is the CLSCTX enumeration, which specifies whether the expected object
is to be run in-process, out-of-process local, or out-of-process remote. Taken together, these two values and the
values in the registry determine how and where the object is to be run.
NOTE
Instance creation calls, when they specify a server location, can override a registry setting. The algorithm COM uses for
doing this is described in the reference for the CLSCTX enumeration.
Remote activation depends on the security relationship between client and server. For more information, see
Security in COM.
Related topics
C
O
M
C
l
a
s
s
O
b
j
e
c
t
s
a
n
d
C
L
S
I
D
s
C
r
e
a
t
i
n
g
a
n
O
b
j
e
c
t
T
h
r
o
u
g
h
a
C
l
a
s
s
O
b
j
e
c
t
Instance Creation Helper Functions
1/7/2020 • 2 minutes to read • Edit Online
In previous releases of COM, the primary mechanism used to create an object instance was the
CoCreateInstance function. This function encapsulates the process of creating a class object, using that to create
a new instance and releasing the class object. Another function of this kind is the more specific OleCreate, the
OLE compound document helper that creates a class object and retrieves a pointer to a requested object.
To smooth the process of instance creation on distributed systems, COM has introduced four important new
instance creation mechanisms:
Class monikers and IClassActivator
CoCreateInstanceEx
CoGetInstanceFromFile
CoGetInstanceFromIStorage
A class moniker permits you to identify the class of an object and is typically used with another moniker, like a file
moniker, to indicate the location of the object. This permits you to bind to an object and specify the server that is to
be launched for that object. Class monikers may also be composed to the right of monikers supporting binding to
the IClassActivator interface. For more information, see Class Monikers.
CoCreateInstanceEx extends CoCreateInstance to make it possible to create a single uninitialized object
associated with the given CLSID on a specified remote machine. In addition, rather than requesting a single
interface and obtaining a single pointer to that interface, CoCreateInstanceEx makes it possible to query for
multiple interfaces and (if available) receive pointers to them in a single round-trip, thus permitting fewer round-
trips between machines. This can make remote object interaction much more efficient. To do this, the function uses
an array of MULTI_QI structures.
Creating an object through CoCreateInstanceEx still requires that the object be initialized through a call to one
of the initialization interfaces (such as IPersistStorage::Load). The helper functions CoGetInstanceFromFile
and CoGetInstanceFromIStorage encapsulate both the instance creation power of CoCreateInstanceEx and
the initialization, the former from a file and the latter from a storage.
Related topics
C
r
e
a
t
i
n
g
a
n
O
b
j
e
c
t
T
h
r
o
u
g
h
a
C
l
a
s
s
O
b
j
e
c
t
COM Server Responsibilities
1/7/2020 • 2 minutes to read • Edit Online
One of the most important ways for a client to get a pointer to an object is for the client to ask that a server be
launched and that an instance of the object provided by the server be created and activated. It is the responsibility
of the server to ensure that this happens properly. There are several important parts to this.
The server must implement code for a class object through an implementation of either the IClassFactory or
IClassFactory2 interface.
The server must register its CLSID in the system registry on the machine on which it resides and further, has the
option of publishing its machine location to other systems on a network to allow clients to call it without requiring
the client to know the server's location.
The server is primarily responsible for security; that is, for the most part, the server determines whether it will
provide a pointer to one of its objects to a client.
In-process servers should implement and export certain functions that allow the client process to instantiate
them.
The following topics detail the responsibilities of the COM server:
Implementing IClassFactory
Licensing and IClassFactory2
Registering COM Servers
Out-of-Process Server Implementation Helpers
GUID Creation and Optimizations
Related topics
C
O
M
C
l
i
e
n
t
s
a
n
d
S
e
r
v
e
r
s
Implementing IClassFactory
1/7/2020 • 2 minutes to read • Edit Online
When a client uses a CLSID to request the creation of an object instance, the first step is creation of a class object,
an intermediate object that contains an implementation of the methods of the IClassFactory interface. While
COM provides several instance creation functions, the first step in the implementation of these functions is the
creation of a class object.
As a result, all servers must implement the methods of the IClassFactory interface, which contains two methods:
CreateInstance. This method must create an uninitialized instance of the object and return a pointer to a
requested interface on the object.
LockServer. This method just increments the reference count on the class object to ensure that the server
stays in memory and does not shut down before the client is ready for it to do so.
To enable a server to be responsible for its own licensing, COM defines IClassFactory2, which inherits its
definition from IClassFactory. Thus, a server implementing IClassFactory2 must, by definition, implement the
methods of IClassFactory.
COM also provides helper functions for implementing out-of-process servers. For more information, see Out-of-
Process Server Implementation Helpers.
Related topics
C
O
M
S
e
r
v
e
r
R
e
s
p
o
n
s
i
b
i
l
i
t
i
e
s
L
i
c
e
n
s
i
n
g
a
n
d
I
C
l
a
s
s
F
a
c
t
o
r
y
2
Licensing and IClassFactory2
1/7/2020 • 3 minutes to read • Edit Online
The IClassFactory interface on a class object provides the basic object creation mechanism of COM. Using
IClassFactory, a server can control object creation on a machine basis. The implementation of the
IClassFactory::CreateInstance method can allow or disallow object creation based on the existence of a machine
license. A machine license is a piece of information separate from the application that exists on a machine to
indicate that the software was installed from a valid source, such as the vendor's installation disks. If the machine
license does not exist, the server can disallow object creation. Machine licensing prevents piracy in cases where a
user attempts to copy the software from one machine to another, because the license information is not copied
with the software and the machine that receives the copy is not licensed.
However, in a component software industry, vendors need a finer level of control over licensing. In addition to
machine license control, a vendor needs to allow some clients to create a component object while denying other
clients the same capability. This requires that the client application obtain a license key from the component while
the client application is still under development. The client application uses the license key at run time to create
objects on an unlicensed machine.
For example, if a vendor provides a library of controls to developers, the developer who purchases the library will
have a full machine license, allowing the objects to be created on the development machine. The developer can
then build a client application on the licensed machine incorporating one or more of the controls. When the
resulting client application is run on another machine, the controls used in the client application must be created
on the other machine even if that machine does not possess a machine license for the controls from the original
vendor.
The IClassFactory2 interface provides this level of control. To allow key-based licensing for any given component,
you implement IClassFactory2 on the class factory object for that component. IClassFactory2is derived from
IClassFactory, so by implementing IClassFactory2, the class factory object fulfills the basic COM requirements.
To incorporate a licensed component into your client application, use the following methods in IClassFactory2:
The GetLicInfo method fills a LICINFO structure with information describing the licensing behavior of the
class factory. For example, the class factory can provide license keys for run-time licensing if the
fRunTimeKeyAvail member is TRUE.
The RequestLicKey method provides a license key for the component. A machine license must be available
when the client calls this method.
The CreateInstanceLic method creates an instance of the licensed component if the license key parameter
(BSTRÂ bstrKey) is valid.
NOTE
In its type information, a component uses the attribute licensed to mark the coclass that supports licensing through
IClassFactory2.
First, you need a separate development tool that is also a client of the licensed component. The purpose of this tool
is to obtain the run-time license key and save it in your client application. This tool runs only on a machine that
possesses a machine license for the component. The tool calls the GetLicInfo and RequestLicKey methods to
obtain the run-time license key and then saves the license key in your client application. For example, the
development tool could create a header (.h) file containing the BSTR license key, and then you would include that
.h file in your client application.
To instantiate the component within your client application, first try to instantiate the object directly with
IClassFactory::CreateInstance. If CreateInstance succeeds, the second machine is licensed for the component
and objects can be created at will. If CreateInstancefails with the return code CLASS_E_NOTLICENSED, the only
way to create the object is to pass the run-time key to the CreateInstanceLic method. CreateInstanceLic verifies
the key and creates the object if the key is valid.
In this way, an application built with components (such as controls) can run on a machine that has no other license
—only the client application containing the run-time license is allowed to create the component objects in
question.
The IClassFactory2 interface supports flexibility in licensing schemes. For example, the server implementor can
encrypt license keys in the component for added security. Server implementers can also enable or disable levels of
functionality in their objects by providing different license keys for different functions. For example, one key might
allow a base level of functionality while another allows basic and advanced functionality, and so on.
Related topics
C
O
M
S
e
r
v
e
r
R
e
s
p
o
n
s
i
b
i
l
i
t
i
e
s
Registering COM Servers
1/7/2020 • 2 minutes to read • Edit Online
After you have defined a class in code (ensuring that it implements IClassFactory or IClassFactory2) and
assigned it a CLSID, you need to put information in the registry that will allow COM, on request of a client with
the CLSID, to create instances of its objects. This information tells the system, for a given CLSID, where the DLL
or EXE code for that class is located and how it is to be launched.
There is more than one way of registering a class in the registry. In addition, there are other ways of "registering"
a class with the system when it is running, so that the system is aware that a running object is currently in the
system.
See the following topics for more information about registering:
Registering a Class at Installation
Registering a Running EXE Server
Registering Objects in the ROT
Self-Registration
Installing as a Service Application
Related topics
C
O
M
S
e
r
v
e
r
R
e
s
p
o
n
s
i
b
i
l
i
t
i
e
s
Registering a Class at Installation
1/7/2020 • 2 minutes to read • Edit Online
If a class is intended to be available to clients at any time, as most applications are, you usually register it through
an installation and setup program. This means putting information about the application into the registry,
including how and where its objects are to be instantiated. This information must be registered for all CLSIDs.
Other information is optional. Tools such as Regsvr32 make it simple to write a setup program that registers
servers at installation.
If you are not relying on system defaults, there are two important keys in the registry: the CLSID and the AppID.
Among the important pieces of information under these keys is how the object is to be instantiated. Objects can be
designated as in-process, out-of-process local, or out-of-process remote.
Under the AppID key are several values that define information specific to that application. Among these are
RemoteServerName and ActivateAtStorage, both of which can be used to permit a client to create an object, with
the client having no built-in knowledge of the location of the server. (For more information about remote
instantiation, see Locating a Remote Object and Instance Creation Helper Functions.)
A server can also be installed as a service, or to run under a specific user account. For more information, see
Installing as a Service Application.
A server or ROT object that is not a service or running under a specific user account can be referred to as an
"activate as activator" server. For these servers, the security context and the window station/desktop of the client
must match the server's. A client attempting to connect to a remote server is considered to have a NULL window
station/desktop, so only the server security context is compared in this instance. (For more information about
SIDs, see Security in COM.) COM caches the window station/desktop of a process when the process first connects
to the distributed COM service. Therefore, COM clients and servers should not change their window station or
thread desktops of the process after calling CoInitialize or CoInitializeEx.
When a class is registered as in-process, a call to CoGetClassObject to create its class object is automatically
passed by COM to the DllGetClassObject function, which the class must implement to give the calling object a
pointer to its class object.
Classes implemented in executables can specify that COM should execute their process and wait for the process to
register their class object's IClassFactory interface through a call to the CoRegisterClassObject function.
Related topics
C
O
M
R
e
g
i
s
t
r
y
K
e
y
s
I
n
s
t
a
l
l
i
n
g
a
s
a
S
e
r
v
i
c
e
A
p
p
l
i
c
a
t
i
o
n
R
e
g
i
s
t
e
r
i
n
g
a
R
u
n
n
i
n
g
E
X
E
S
e
r
v
e
r
R
e
g
i
s
t
e
r
i
n
g
C
o
m
p
o
n
e
n
t
s
R
e
g
i
s
t
e
r
i
n
g
O
b
j
e
c
t
s
i
n
t
h
e
R
O
T
S
e
l
f
-
R
e
g
i
s
t
r
a
t
i
o
n
Registering a Running EXE Server
1/7/2020 • 2 minutes to read • Edit Online
When an executable (EXE ) server is launched, it should call CoRegisterClassObject, which registers the CLSID
for the server in what is called the class table (a different table than the running object table). When a server is
registered in the class table, it allows the service control manager (SCM ) to determine that it is not necessary to
launch the class again, because the server is already running. Only if the server is not listed in the class table will
the SCM check the registry for appropriate values and launch the server associated with the given CLSID.
You pass CoRegisterClassObject the CLSID for the class and a pointer to its IUnknown interface. Clients who
subsequently call CoGetClassObject with this CLSID will retrieve a pointer to their requested interface, as long
as security does not forbid it. (See Instance Creation Helper Functions for a description of several instance creation
and activation functions.)
The server for a class object should call CoRevokeClassObject to revoke the class object (remove its registration)
when all of the following are true:
There are no existing instances of the object definition.
There are no locks on the class object.
The application providing services to the class object is not under user control (not visible to the user on the
display).
Related topics
I
n
s
t
a
l
l
i
n
g
a
s
a
S
e
r
v
i
c
e
A
p
p
l
i
c
a
t
i
o
n
R
e
g
i
s
t
e
r
i
n
g
a
C
l
a
s
s
a
t
I
n
s
t
a
l
l
a
t
i
o
n
R
e
g
i
s
t
e
r
i
n
g
O
b
j
e
c
t
s
i
n
t
h
e
R
O
T
S
e
l
f
-
R
e
g
i
s
t
r
a
t
i
o
n
Registering Objects in the ROT
1/7/2020 • 2 minutes to read • Edit Online
Typically, when a client asks a server to create an object instance, the server typically creates a moniker for the
object and registers it in the running object table (ROT) through a call to IRunningObjectTable::Register.
When the server calls CreateFileMoniker to create a file moniker to be registered in the ROT, servers should
pass local file names that are drive-based, not in UNC format. This ensures that the moniker comparison data that
is generated by the ROT register call will match what is used while doing a ROT lookup on the part of a remote
client. This is because when the distributed COM service receives an activation request for a file local to the server
from a remote client, the file is converted to a local-drive-based path.
Related topics
I
n
s
t
a
l
l
i
n
g
a
s
a
S
e
r
v
i
c
e
A
p
p
l
i
c
a
t
i
o
n
R
e
g
i
s
t
e
r
i
n
g
a
C
l
a
s
s
a
t
I
n
s
t
a
l
l
a
t
i
o
n
R
e
g
i
s
t
e
r
i
n
g
a
R
u
n
n
i
n
g
E
X
E
S
e
r
v
e
r
S
e
l
f
-
R
e
g
i
s
t
r
a
t
i
o
n
Self-Registration
1/7/2020 • 2 minutes to read • Edit Online
As component software continues to grow as a market, there will be more and more instances where a user
obtains a new software component as a single DLL or EXE module, such as when downloading a new component
from an on-line service or receiving one from a friend on a floppy disk. In these cases, it is not practical to require
the user to go through a lengthy installation procedure or setup program. Besides the licensing issues, which are
handled through IClassFactory2, an installation procedure typically creates the necessary registry entries for a
component to run properly in the COM and OLE context.
Self-registration is the standard means through which a server module can package its own registry operations,
both registration and unregistration, into the module itself. When used with licensing handled through
IClassFactory2, a server can become an entirely self-contained module with no need for external installation
programs or .reg files.
Any self-registering module, DLL or EXE, should first include an "OleSelfRegister" string in the StringFileInfo
section of its version information resource, as shown here.
VS_VERSION_INFO VERSIONINFO
...
BEGIN
BLOCK "StringFileInfo"
BEGIN
#ifdef UNICODE
BLOCK "040904B0" // Lang=US English, CharSet=Unicode
#else
BLOCK "040904E4" // Lang=US English, CharSet=Windows Multilingual
#endif
BEGIN
...
VALUE "OLESelfRegister", "\0"
END
...
END
...
END
The existence of this data allows any interested party, such as an application that wishes to integrate this new
component, to determine whether the server supports self-registration without having to load the DLL or EXE
first.
If the server is packaged in a DLL module, the DLL must export the functions DllRegisterServer and
DllUnregisterServer. Any application that wishes to instruct the server to register itself (that is, all its CLSIDs
and type library IDs) can obtain a pointer to DllRegisterServer through the GetProcAddress function. Within
DllRegisterServer, the DLL creates all its necessary registry entries, storing the correct path to the DLL for all
InprocServer32 or InprocHandler32 entries.
When an application wishes to remove the component from the system, it should unregister that component by
calling DllUnregisterServer. Within this call, the server removes exactly those entries it previously created in
DllRegisterServer. The server should not blindly remove all entries for its classes because other software may
have stored additional entries, such as a TreatAs key.
If the server is packaged in an EXE module, the application wishing to register the server launches the EXE server
with the command-line argument /RegServer or -RegServer (case-insensitive). If the application wishes to
unregister the server, it launches the EXE with the command-line argument /UnregServer or -UnregServer. The
self-registering EXE detects these command-line arguments and invokes the same operations as a DLL would
within DllRegisterServerand DllUnregisterServer, respectively, registering its module path under
LocalServer32 instead of InprocServer32 or InprocHandler32.
The server must register the full path to the installation location of the DLL or EXE module for their respective
InprocServer32, InprocHandler32, and LocalServer32 keys in the registry. The module path is easily obtained
through the GetModuleFileName function.
Related topics
I
n
s
t
a
l
l
i
n
g
a
s
a
S
e
r
v
i
c
e
A
p
p
l
i
c
a
t
i
o
n
R
e
g
i
s
t
e
r
i
n
g
a
C
l
a
s
s
a
t
I
n
s
t
a
l
l
a
t
i
o
n
R
e
g
i
s
t
e
r
i
n
g
a
R
u
n
n
i
n
g
E
X
E
S
e
r
v
e
r
R
e
g
i
s
t
e
r
i
n
g
O
b
j
e
c
t
s
i
n
t
h
e
R
O
T
Installing as a Service Application
1/7/2020 • 2 minutes to read • Edit Online
In addition to running as a local server executable (EXE ), a COM object may also package itself to run as a service
application when activated by a local or remote client. Services support numerous useful and user
interface–integrated administrative features, including local and remote starting, stopping, pausing, and
restarting, as well as the ability to establish the server to run under a specific user account and window station.
An object written as a service is installed for use by COM by establishing a LocalService value under its AppID
key and performing a standard service installation.
Classes may also be configured to run under a specific user account when activated by a remote client without
being written as a service application. To do this, the class installs a user name and a password to be used when
the SCM launches its local server process.
When a class is configured in this fashion, calls to CoRegisterClassObject with this CLSID will fail unless the
process was launched by COM on behalf of an actual activation request. In other words, classes configured to run
as a particular user may not be registered under any other identity.
The user name is taken from the RunAs named-value under the class's APPID key. If the user name is "Interactive
User", the class code is run in the security context of the currently logged on user and is connected to the
interactive window station.
Otherwise, the password is retrieved from a hidden portion of the registry available only to administrators of the
machine and to the system. The user name and password are then used to create a logon session in which the
class code is run. When launched in this way, the class code runs with its own desktop and window -station and
does not share window handles, the clipboard, or other user interface elements with the interactive user or other
classes running in other user accounts.
A server registered either with LocalService or RunAs can register an object in the running object table to allow
any client to connect to it. To do so, the server's call to IRunningObjectTable::Register must set the
ROTFLAGS_ALLOWANYCLIENT flag. A server setting this bit must have its executable name in the AppID
section of the registry that refers to the AppID for the executable. An "activate as activator" server (not registered
as either LocalService or RunAs) may not register an object with this flag.
Related topics
R
e
g
i
s
t
e
r
i
n
g
a
C
l
a
s
s
a
t
I
n
s
t
a
l
l
a
t
i
o
n
R
e
g
i
s
t
e
r
i
n
g
a
R
u
n
n
i
n
g
E
X
E
S
e
r
v
e
r
R
e
g
i
s
t
e
r
i
n
g
O
b
j
e
c
t
s
i
n
t
h
e
R
O
T
S
e
l
f
-
R
e
g
i
s
t
r
a
t
i
o
n
Out-of-Process Server Implementation Helpers
1/7/2020 • 5 minutes to read • Edit Online
Four helper functions that can be called by out-of-process servers are available to simplify the job of writing
server code. COM clients and COM in-process servers typically would not call them. These functions are designed
to help prevent race conditions in server activation when the servers have multiple apartments or multiple class
objects. They can also, however, as easily be used for single-threaded and single class object servers. The functions
are as follows:
CoAddRefServerProcess
CoReleaseServerProcess
CoSuspendClassObjects
CoResumeClassObjects
To shut down properly, a COM server must keep track of how many object instances it has instantiated and how
many times its IClassFactory::LockServer method has been called. Only when both of these counts reach zero
can a server shut down. In single-threaded COM servers, the decision to shut down was coordinated with
incoming activation requests, which were serialized by the message queue. The server, upon receiving a release on
its final object instance and deciding to shut down, would revoke its class objects before any more activation
requests were dispatched. If an activation request did come in after this point, COM would recognize that the class
objects were revoked and would return an error to the Service Control Manager (SCM ), which would then cause a
new instance of the local server process to be run.
However, in an apartment model server, in which different class objects are registered on different apartments,
and in all free-threaded servers, this decision to shut down must be coordinated with activation requests across
multiple threads so that one thread of the server does not decide to shut down while another thread of the server
is busy handing out class objects or object instances. One classical but cumbersome approach to solving this is to
have the server, after it has revoked its class objects, recheck its instance count and stay alive until all instances
have been released.
To make it easier for server writers to handle these types of race conditions, COM provides two reference counting
functions:
CoAddRefServerProcess increments a global per-process reference count.
CoReleaseServerProcess decrements the global per-process reference count.
When the global per-process reference count reaches zero, COM automatically calls CoSuspendClassObjects,
which prevents any new activation requests from coming in. The server can then deregister its various class
objects from its various threads at leisure without worry that another activation request may come in. All new
activation requests are henceforth handled by the SCM launching a new instance of the local server process.
The simplest way for a local server application to make use of these functions is to call CoAddRefServerProcess
in the constructor for each of its instance objects and in each of its IClassFactory::LockServer methods when the
fLock parameter is TRUE. The server application should also call CoReleaseServerProcess in the destructor of
each of its instance objects and in each of its IClassFactory::LockServer methods when the fLock parameter is
FALSE.
Finally, the server application should pay attention to the return code from CoReleaseServerProcess, and if it
returns 0, the server application should initiate its cleanup, which, for a server with multiple threads, typically
means that it should signal its various threads to exit their message loops and call CoAddRefServerProcess and
CoReleaseServerProcess. If the server process lifetime management functions are used, they must be used in
both the object instances and the LockServer method; otherwise, the server application may be shut down
prematurely.
When a CoGetClassObject request is made, COM contacts the server, marshals the IClassFactory interface of
the class object, returns to the client process, unmarshals the IClassFactory interface, and returns this to the
client. At this point, clients typically call LockServer with TRUE to prevent the server process from shutting down.
However, there is a window of time between when the class object is marshaled and when the client calls
LockServer in which another client could connect to the same server, get an instance, and release that instance,
thus causing the server to shut down and leaving the first client high and dry with a disconnected IClassFactory
pointer. To prevent this race condition, COM adds an implicit call to LockServer with TRUE to the class object
when it marshals the IClassFactory interface and an implicit call to LockServer with FALSE when the client
releases the IClassFactory interface. Therefore, it is not necessary to remote LockServer calls back to the server,
and the proxy for LockServer simply returns S_OK without actually remoting the call.
There is another activation-related race condition during initialization of an out-of-process server process. A COM
server that registers multiple classes typically calls CoRegisterClassObject with REGCLS_LOCAL_SERVER for
each CLSID it supports. After it has done this for all classes, the server enters its message loop. For a single-
threaded COM server, all activation requests are blocked until the server enters the message loop. However, for an
apartment model server that registers different class objects in different apartments and for all free-threaded
servers, activation requests can arrive earlier than this. In the case of apartment model servers, activation requests
could arrive as soon as any one thread has entered its message loop. In the case of free-threaded servers, an
activation request could arrive as soon as the first class object is registered. Since an activation can happen this
early, it is also possible for the final release to occur (and therefore cause the server to begin shutting down)
before the rest of the server has had a chance to finish initializing.
To eliminate these race conditions and simplify the job of the server writer, any server that wants to register
multiple class objects with COM should call CoRegisterClassObject with REGCLS_LOCAL_SERVER |
REGCLS_SUSPENDED for each different CLSID the server supports. After all classes have been registered and
the server process is ready to accept incoming activation requests, the server should make one call to
CoResumeClassObjects. This function tells COM to inform the SCM about all the registered classes, and it
begins letting activation requests into the server process. Using these functions provides the following
advantages:
Only one call is made to the SCM, regardless of how many CLSIDs are registered, thus reducing the overall
registration time (and hence startup time of the server application).
If the server has multiple apartments and different CLSIDs are registered in different apartments, or if the
server is a free-threaded server, no activation requests will come in until the server calls
CoResumeClassObjects, giving the server a chance to register all of its CLSIDs and get properly set up
before having to deal with activation requests and possible shut down requests.
Related topics
C
O
M
S
e
r
v
e
r
R
e
s
p
o
n
s
i
b
i
l
i
t
i
e
s
GUID Creation and Optimizations
1/7/2020 • 2 minutes to read • Edit Online
Because a CLSID, like an interface identifier (IID ), is a GUID, no other class, no matter who writes it, has a duplicate
CLSID. Server implementers generally obtain CLSIDs through the CoCreateGuid function. This function is
guaranteed to produce unique CLSIDs, so server implementers across the world can independently develop and
deploy their software without fear of accidental collision with software written by others.
Using unique CLSIDs avoids the possibility of name collisions among classes because CLSIDs are in no way
connected to the names used in the underlying implementation. For example, two different vendors can write
classes called "StackClass," but each would have a unique CLSID and therefore could not be confused.
COM frequently must map GUIDs (IIDs and CLSIDs) to some arbitrarily large set of other values. As an
application developer, you can help speed up such searches, and thereby enhance system performance, by
generating the GUIDs for your application as a block of consecutive values.
The most efficient way to generate a block of consecutive GUIDs is to run the uuidgen utility using the -n and -x
switches, which generates a block of UUIDs, each of whose first DWORD value is incremented by one.
For example, if you were to type
uuidgen -n5 -x
the uuidgen utility would generate a block of UUIDs similar to the following:
12340001-4980-1920-6788-123456789012
12340002-4980-1920-6788-123456789012
12340003-4980-1920-6788-123456789012
12340004-4980-1920-6788-123456789012
12340005-4980-1920-6788-123456789012
One method for generating and tracking GUIDs for an entire project begins with generating a block of some
arbitrarily large number of UUIDs, say 500. For example, if you were to type
uuidgen -n500 -x > guids.txt
the utility would generate 500 consecutive UUIDs and write them to the specified text file. You could then check
this file into your source tree, providing a single repository for all GUIDs to be used in a project. As people require
GUIDs for their portions of the project, they can check out the file, take however many GUIDs they need, marking
them as taken and leaving a note about where in the code or "spec" they are using them.
In addition to improving system performance, generating blocks of consecutive GUIDs in this way has the
following benefits:
A central file containing all GUIDs for an application makes it easy to keep track of which GUIDs are for what
and which people are using them.
A block of consecutive GUIDs associated with a particular application helps developers and testers recognize
internal GUIDs during debugging and makes it easier to find them in the system registry because they are
stored sequentially.
Related topics
C
O
M
S
e
r
v
e
r
R
e
s
p
o
n
s
i
b
i
l
i
t
i
e
s
Persistent Object State
1/7/2020 • 2 minutes to read • Edit Online
Some COM objects can save their internal state when asked to do so by a client.
COM defines standards through which clients can request objects to be initialized, loaded, and saved to and from a
data store (for example, flat file, structured storage, or memory). It is the client's responsibility to manage the
location where the object's persistent data is stored but not the format of the data. COM objects that adhere to
these standards are called persistent objects.
For more information, see the following topics:
Persistent Object Interfaces
Initializing Persistent Objects
Related topics
C
O
M
C
l
i
e
n
t
s
a
n
d
S
e
r
v
e
r
s
Persistent Object Interfaces
1/7/2020 • 2 minutes to read • Edit Online
A persistent object implements one or more persistent object interfaces. Clients use persistent object interfaces to
tell those objects when and where to store their state. All persistent object interfaces are derived from IPersist, so
any object that implements any persistent object interface also implements IPersist.
The following persistent object interfaces are currently defined:
IPersistStream
IPersistStreamInit
IPersistStorage
IPersistFile
IPersistMoniker
IPersistMemory
IPersistPropertyBag
Implementers choose which persistent object interfaces an object supports depending on how the object is to be
used. By not supporting any persistent object interfaces, the implementer is effectively saying, "This object's state
cannot be persistently stored." By supporting one or more persistent object interfaces, the implementer is
effectively saying, "This object's state can be persistently stored in one or more data store mediums."
For example, the following table lists several object types that allow support for different persistent object
interfaces.
Monikers IPersistStream
Client implementers can also choose which persistent object interfaces the client can use. The interfaces a client
uses is usually determined by where the client can store its own data. A client that can store its data only in a flat
file will probably use only IPersistStreamInit, IPersistMoniker, and IPersistPropertyBag. (IPersistStreamInit
can replace IPersistStream in most applications, because it contains that definition and adds an initialization
method.) A client that can save its data to a structured storage file will, in addition, use IPersistStorage.
Related topics
I
n
i
t
i
a
l
i
z
i
n
g
P
e
r
s
i
s
t
e
n
t
O
b
j
e
c
t
s
Initializing Persistent Objects
1/7/2020 • 2 minutes to read • Edit Online
Related topics
P
e
r
s
i
s
t
e
n
t
O
b
j
e
c
t
I
n
t
e
r
f
a
c
e
s
Providing Class Information
1/7/2020 • 2 minutes to read • Edit Online
It is often useful for a client of an object to examine the object's type information. Given the object's CLSID, a client
can locate the object's type library using registry entries and then can scan the type library for the coclass entry in
the library matching the CLSID.
However, not all objects have a CLSID, although they still need to provide type information. In addition, it is
convenient for a client to have a way to simply ask an object for its type information instead of going through all
the tedium to extract the same information from registry entries. This capability is important when dealing with
outgoing interfaces on connectable objects. (See Using IProvideClassInfo for more information on how
connectable objects provide this capability.)
In these cases, a client can query the object for IProvideClassInfo or IProvideClassInfo2. If these interfaces
exist, the client calls the GetClassInfo method to get the type information for the interface.
By implementing IProvideClassInfo or IProvideClassInfo2, an object specifies that it can provide type
information for its entire class; that is, what it would describe in its coclass section of its type library, if it has one.
GetClassInfo returns an ITypeInfo pointer corresponding to the object's coclass information. Through this
ITypeInfo pointer, the client can examine all the object's incoming and outgoing interface definitions.
The object can also provide IProvideClassInfo2. The IProvideClassInfo2 interface is a simple extension to
IProvideClassInfo that makes it quick and easy to retrieve an object's outgoing interface identifiers for its default
event set. IProvideClassInfo2 is derived from IProvideClassInfo.
Related topics
C
O
M
C
l
i
e
n
t
s
a
n
d
S
e
r
v
e
r
s
Inter-Object Communication
1/7/2020 • 5 minutes to read • Edit Online
COM is designed to allow clients to communicate transparently with objects, regardless of where those objects
are running—in the same process, on the same computer, or on a different computer. This provides a single
programming model for all types of objects, and for both object clients and object servers.
From a client's point of view, all objects are accessed through interface pointers. A pointer must be in-process. In
fact, any call to an interface function always reaches some piece of in-process code first. If the object is in-process,
the call reaches it directly, with no intervening system-infrastructure code. If the object is out-of-process, the call
first reaches what is called a "proxy" object provided either by COM or by the object (if the implementor wishes).
The proxy packages call parameters (including any interface pointers) and generate the appropriate remote
procedure call (or other communication mechanism in the case of custom generated proxies) to the other process
or the other computer where the object implementation is located. This process of packaging pointers for
transmission across process boundaries is called marshaling.
From a server's point of view, all calls to an object's interface functions are made through a pointer to that
interface. Again, a pointer has context only in a single process, and the caller must always be some piece of in-
process code. If the object is in-process, the caller is the client itself. Otherwise, the caller is a "stub" object
provided either by COM or by the object itself. The stub receives the remote procedure call (or other
communication mechanism in the case of custom generated proxies) from the "proxy" in the client process,
unmarshals the parameters, and calls the appropriate interface on the server object. From the points of view of
both clients and servers, they always communicate directly with some other in-process code.
COM provides an implementation of marshaling, referred to as standard marshaling. This implementation works
very well for most objects and greatly reduces programming requirements, making the marshaling process
effectively transparent.
The clear separation of interface from implementation of COM's process transparency can, however, get in the
way in some situations. The design of an interface that focuses on its function from the client's point of view can
sometimes lead to design decisions that conflict with efficient implementation of that interface across a network.
In cases like this, what is needed is not pure process transparency but "process transparency, unless you need to
care." COM provides this capability by allowing an object implementor to support custom marshaling (also called
IMarshal marshaling). Standard marshaling is, in fact, an instance of custom marshaling; it is the default
implementation used when an object does not require custom marshaling.
You can implement custom marshaling to allow an object to take different actions when used from across a
network than it takes under local access—and it is completely transparent to the client. This architecture makes it
possible to design client/object interfaces without regard to network performance issues and then later to address
network performance issues without disrupting the established design.
COM does not specify how components are structured; it specifies how they interact. COM leaves the concern
about the internal structure of a component to programming languages and development environments.
Conversely, programming environments have no set standards for working with objects outside of the immediate
application. Microsoft Visual C++, for example, works extremely well for manipulating objects inside an
application but has no support for working with objects outside the application. Generally, all other programming
languages are the same in this regard. Therefore, to provide networkwide interoperability, COM, through
language-independent interfaces, picks up where programming languages leave off.
The double indirection of the vtbl structure means that the pointers in the table of function pointers do not need
to point directly to the real implementation in the real object. This is the heart of process transparency.
For in-process servers, where the object is loaded directly into the client process, the function pointers in the table
point directly to the actual implementation. In this case, a function call from the client to an interface method
directly transfers execution control to the method. However, this cannot work for local, let alone remote, objects
because pointers to memory cannot be shared between processes. Nevertheless, the client must be able to call
interface methods as if it were calling the actual implementation. Thus, the client uniformly transfers control to a
method in some object by making the call.
A client always calls interface methods in some in-process object. If the actual object is local or remote, the call is
made to a proxy object, which then makes a remote procedure call to the actual object.
So what method is actually executed? The answer is that whenever there is a call to an out-of-process interface,
each interface method is implemented by a proxy object. The proxy object is always an in-process object that acts
on behalf of the object being called. This proxy object knows that the actual object is running in a local or remote
server.
The proxy object packages up the function parameters in some data packets and generates an RPC call to the
local or remote object. That packet is picked up by a stub object in the server's process on the local or a remote
computer, which unpacks the parameters and makes the call to the real implementation of the method. When that
function returns, the stub packages up any out-parameters and the return value and sends it back to the proxy,
which unpacks them and returns them to the original client.
Thus, client and server always talk to each other as if everything was in-process. All calls from the client and all
calls to the server are, at some point, in-process. But because the vtbl structure allows some agent, like COM, to
intercept all function calls and all returns from functions, that agent can redirect those calls to an RPC call as
necessary. Although in-process calls are faster than out-of-process calls, the process differences are completely
transparent to the client and server.
For more information, see the following topics:
Marshaling Details
Proxy
Stub
Channel
Microsoft RPC
Related topics
C
O
M
C
l
i
e
n
t
s
a
n
d
S
e
r
v
e
r
s
I
n
t
e
r
f
a
c
e
M
a
r
s
h
a
l
i
n
g
Marshaling Details
1/7/2020 • 4 minutes to read • Edit Online
If you use standard marshaling, COM handles all of the details described here for you. However, there are those
few programmers who need these details and for those interested in the underlying information. Marshaling is the
process of packaging and unpackaging parameters so a remote procedure call can take place.
Different parameter types are marshaled in different ways. For example, marshaling an integer parameter involves
simply copying the value into the message buffer. (Although even in this simple case, there are issues such as byte
ordering to deal with in cross-computer calls.) Marshaling an array, however, is a more complex process. Array
members are copied in a specific order so that the other side can reconstruct the array exactly. When a pointer is
marshaled, the data that the pointer is pointing to is copied following rules and conventions for dealing with
nested pointers in structures. Unique functions exist to handle the marshaling of each parameter type.
With standard marshaling, the proxies and stubs are systemwide resources for the interface and they interact with
the channel through a standard protocol. Standard marshaling can be used both by standard COM -defined
interfaces and by custom interfaces, as follows:
In the case of most COM interfaces, the proxies and stubs for standard marshaling are in-process component
objects which are loaded from a systemwide DLL provided by COM in Ole32.dll.
In the case of custom interfaces, the proxies and stubs for standard marshaling are generated by the interface
designer, typically with MIDL. These proxies and stubs are statically configured in the registry, so any potential
client can use the custom interface across process boundaries. These proxies and stubs are loaded from a DLL
that is located via the system registry, using the interface ID (IID ) for the custom interface they marshal.
An alternative to using MIDL to generate proxies and stubs for custom interfaces, a type library can be
generated instead and the system provided, type-library–driven marshaling engine will marshal the interface.
As an alternative to standard marshaling, an interface (standard or custom) can use custom marshaling. With
custom marshaling, an object dynamically implements the proxies at run time for each interface that it supports.
For any given interface, the object can select COM -provided standard marshaling or custom marshaling. This
choice is made by the object on an interface-by-interface basis. Once the choice is made for a given interface, it
remains in effect during the object's lifetime. However, one interface on an object can use custom marshaling
while another uses standard marshaling.
Custom marshaling is inherently unique to the object that implements it. It uses proxies implemented by the
object and provided to the system on request at run time. Objects that implement custom marshaling must
implement the IMarshal interface, whereas objects that support standard marshaling do not.
If you decide to write a custom interface, you must provide marshaling support for it. Typically, you will provide a
standard marshaling DLL for the interface you design. You can create the proxy/stub code and the proxy/stub
DLL, or you can create a type library that COM will use to do data-driven marshaling (using the data in the type
library).
For a client to make a call to an interface method in an object in another process involves the cooperation of
several components. The standard proxy is a piece of interface-specific code that resides in the client's process
space and prepares the interface parameters for transmittal. It packages, or marshals, them in such a way that they
can be re-created and understood in the receiving process. The standard stub, also a piece of interface-specific
code, resides in the server's process space and reverses the work of the proxy. The stub unpackages, or
unmarshals, the sent parameters and forwards them to the object application. It also packages reply information
to send back to the client.
NOTE
Readers more familiar with RPC than COM may be used to seeing the terms client stub and server stub. These terms are
analogous to proxy and stub.
Related topics
C
h
a
n
n
e
l
I
n
t
e
r
-
O
b
j
e
c
t
C
o
m
m
u
n
i
c
a
t
i
o
n
M
i
c
r
o
s
o
f
t
R
P
C
P
r
o
x
y
S
t
u
b
Proxy
1/7/2020 • 2 minutes to read • Edit Online
A proxy resides in the address space of the calling process and acts as a surrogate for the remote object. From the
perspective of the calling object, the proxy is the object. Typically, the proxy's role is to package the interface
parameters for calls to methods in its object interfaces. The proxy packages the parameters into a message buffer
and passes the buffer onto the channel, which handles the transport between processes. The proxy is implemented
as an aggregate, or composite, object. It contains a system-provided, manager piece called the proxy manager and
one or more interface-specific components called interface proxies. The number of interface proxies equals the
number of object interfaces that have been exposed to that particular client. To the client complying with the
component object model, the proxy appears to be the real object.
NOTE
With custom marshaling, the proxy can be implemented similarly or it can communicate directly with the object without
using a stub.
Each interface proxy is a component object that implements the marshaling code for one of the object's interfaces.
The proxy represents the object for which it provides marshaling code. Each proxy also implements the
IRpcProxyBuffer interface. Although the object interface represented by the proxy is public, the
IRpcProxyBuffer implementation is private and is used internally within the proxy. The proxy manager keeps
track of the interface proxies and also contains the public implementation of the controlling IUnknown interface
for the aggregate. Each interface proxy can exist in a separate DLL that is loaded when the interface it supports is
materialized to the client.
Related topics
C
h
a
n
n
e
l
I
n
t
e
r
-
O
b
j
e
c
t
C
o
m
m
u
n
i
c
a
t
i
o
n
M
a
r
s
h
a
l
i
n
g
D
e
t
a
i
l
s
M
i
c
r
o
s
o
f
t
R
P
C
S
t
u
b
Stub
1/7/2020 • 2 minutes to read • Edit Online
The stub, like the proxy, is made up of one or more interface pieces and a manager. Each interface stub provides
code to unmarshal the parameters and code that calls one of the object's supported interfaces. Each stub also
provides an interface for internal communication. The stub manager keeps track of the available interface stubs.
There are, however, the following differences between the stub and the proxy:
The most important difference is that the stub represents the client in the object's address space.
The stub is not implemented as an aggregate object because there is no requirement that the client be viewed
as a single unit; each piece in the stub is a separate component.
The interface stubs are private rather than public.
The interface stubs implement IRpcStubBuffer, not IRpcProxyBuffer.
Instead of packaging parameters to be marshaled, the stub unpackages them after they have been marshaled
and then packages the reply.
Related topics
C
h
a
n
n
e
l
I
n
t
e
r
-
O
b
j
e
c
t
C
o
m
m
u
n
i
c
a
t
i
o
n
M
a
r
s
h
a
l
i
n
g
D
e
t
a
i
l
s
M
i
c
r
o
s
o
f
t
R
P
C
P
r
o
x
y
Channel
1/7/2020 • 2 minutes to read • Edit Online
The channel has the responsibility of transmitting all messages between client and object across the process
boundary. The channel has been designed to work transparently with different channel types, is compatible with
OSF DCE standard RPC, and supports single and multithreaded applications.
Related topics
I
n
t
e
r
-
O
b
j
e
c
t
C
o
m
m
u
n
i
c
a
t
i
o
n
M
a
r
s
h
a
l
i
n
g
D
e
t
a
i
l
s
M
i
c
r
o
s
o
f
t
R
P
C
P
r
o
x
y
S
t
u
b
Microsoft RPC
1/7/2020 • 2 minutes to read • Edit Online
Microsoft RPC is a model for programming in a distributed computing environment. The goal of RPC is to
provide transparent communication so that the client appears to be directly communicating with the server.
Microsoft's implementation of RPC is compatible with the Open Software Foundation (OSF ) Distributed
Computing Environment (DCE ) RPC.
You can configure RPC to use one or more transports, one or more name services, and one or more security
servers. The interfaces to those providers are handled by RPC. Because Microsoft RPC is designed to work with
multiple providers, you can choose the providers that work best for your network. The transport is responsible for
transmitting the data across the network. The name service takes an object name, such as a moniker, and finds its
location on the network. The security server offers applications the option of denying access to specific users
and/or groups. See Interface Design Rules for more detailed information about application security.
In addition to the RPC run-time libraries, Microsoft RPC includes the Interface Definition Language (IDL ) and its
compiler. Although the IDL file is a standard part of RPC, Microsoft has enhanced it to extend its functionality to
support custom COM interfaces. The Microsoft Interface Definition Language (MIDL ) compiler uses the IDL file
that describes your custom interface to generate several files discussed in Building and Registering a Proxy DLL.
Related topics
C
h
a
n
n
e
l
I
n
t
e
r
-
O
b
j
e
c
t
C
o
m
m
u
n
i
c
a
t
i
o
n
M
a
r
s
h
a
l
i
n
g
D
e
t
a
i
l
s
P
r
o
x
y
S
t
u
b
Making and Processing Asynchronous Calls
1/7/2020 • 2 minutes to read • Edit Online
COM objects can support asynchronous calling. When a client makes an asynchronous call, control returns to the
client immediately. While the server processes the call, the client is free to do other work. When the client can no
longer proceed without the results of the call, it can get the results of the call at that time.
For example, a request for a large or complex recordset can be time-consuming. A client can request the recordset
by an asynchronous call and then do other work. When the recordset is available, the client can obtain it quickly
without blocking.
Clients do not make asynchronous calls directly on the server object. Instead, they obtain a call object that
implements an asynchronous version of a synchronous interface on the server object. The asynchronous interface
on the call object has a name of the form AsyncInterfaceName. For example, if a server object implements a
synchronous interface named IMyInterface, there will be a call object that implements an asynchronous interface
named AsyncIMyInterface.
NOTE
Asynchronous support is not available for IDispatch or for interfaces that inherit IDispatch.
Server objects that support asynchronous calls implement the ICallFactory interface. This interface exposes a
single method, CreateCall, which creates an instance of a specified call object. Clients can query for ICallFactory
to determine whether an object supports asynchronous calling.
For each method on a synchronous interface, the corresponding asynchronous interface implements two methods.
These methods attach the prefixes Begin_ and Finish_ to the name of the synchronous method. For example, if an
interface named ISimpleStream has a Read method, the AsyncISimpleStream interface will have a Begin_Read and
a Finish_Read method. To begin an asynchronous call, the client calls the Begin_ method.
When you implement a server object, you do not have to provide a call object for every interface the object
implements. If the server object implements the ICallFactory interface and uses standard marshaling, a
marshaled client can always obtain a proxy call object, even if there is no call object on the server side. This proxy
will marshal the Begin_ method as a synchronous call, the server will process the call synchronously, and the client
can obtain the out parameters by calling the Finish_ method.
Conversely, if a client makes a marshaled synchronous call on an interface for which there is a call object on the
server side, the server will always process the call asynchronously. This behavior will not be apparent to the client,
because the client will receive the same out parameters and the same return value it would have received from the
synchronous method.
In either case, the interaction between client and server is marshaled as if the call were synchronous: The output of
synchronous and asynchronous proxies is indistinguishable, as is the output of the corresponding stubs. This
behavior greatly simplifies the programming model both of clients and of servers. If a server object implements
ICallFactory, a marshaled client does not have to attempt to create a call object that may not be available — to the
client, a call object is always available.
When client and server are in the same apartment, the server object will process whichever call the client makes. If
a call object is not available, the client must explicitly obtain the synchronous interface and make a synchronous
call.
For more information, see the following topics:
Making an Asynchronous Call
Canceling an Asynchronous Call
Canceling Method Calls
Call Synchronization
Making an Asynchronous Call
1/29/2020 • 3 minutes to read • Edit Online
The procedure for making a synchronous call is straightforward: The client obtains an interface pointer on the
server object and calls methods through that pointer. Asynchronous calling involves a call object, so it involves a
few more steps.
For each method on a synchronous interface, the corresponding asynchronous interface implements two methods.
These methods attach the prefixes Begin_ and Finish_ to the name of the synchronous method. For example, if an
interface named ISimpleStream has a Read method, the AsyncISimpleStream interface will have a Begin_Read
and a Finish_Read method. To begin an asynchronous call, the client calls the Begin_ method.
To begin an asynchronous call
1. Query the server object for the ICallFactory interface. If QueryInterface returns E_NOINTERFACE, the
server object does not support asynchronous calling.
2. Call ICallFactory::CreateCall to create a call object corresponding to the interface you want, and then
release the pointer to ICallFactory.
3. If you did not request a pointer to the asynchronous interface from the call to CreateCall, query the call
object for the asynchronous interface.
4. Call the appropriate Begin_ method.
The server object is now processing the asynchronous call, and the client is free to do other work until it needs the
results of the call.
A call object can process only one asynchronous call at a time. If the same or a second client calls a Begin_ method
before a pending asynchronous call is finished, the Begin_ method will return RPC_E_CALL_PENDING.
If the client does not need the results of the Begin_ method, it can release the call object at the end of this
procedure. COM detects this condition and cleans up the call. The Finish_ method is not called, and the client does
not get any out parameters or a return value.
When the server object is ready to return from the Begin_ method, it signals the call object that it is done. When
the client is ready, it checks to see whether the call object has been signaled. If so, the client can complete the
asynchronous call.
The mechanism for this signaling and checking between client and server is the ISynchronize interface on the call
object. The call object normally implements this interface by aggregating a system-supplied synchronization
object. The synchronization object wraps an event handle, which the server signals just before returning from the
Begin_ method by calling ISynchronize::Signal.
To complete an asynchronous call
1. Query the call object for the ISynchronize interface.
2. Call ISynchronize::Wait.
3. If Wait returns RPC_E_TIMEOUT, the Begin_ method is not finished processing. The client can continue
with other work and call Wait again later. It cannot call the Finish_ method until Wait returns S_OK.
If Wait returns S_OK, the Begin_ method has returned. Call the appropriate Finish_ method.
The Finish_ method passes the client any out parameters. The behavior of the asynchronous methods, including
the return value of the Finish_ method, should match exactly that of the corresponding synchronous method.
The client can release the call object as soon as the Finish_ method returns, or it can hold a pointer to the call
object to make additional calls. In either case, the client is responsible for releasing the call object when the object
is no longer needed.
If you call a Finish_ method when no call is in progress, the method will return RPC_E_CALL_COMPLETE.
NOTE
If the client and server objects are in the same apartment, calls to ICallFactory::CreateCall are not guaranteed to succeed.
If the server object does not support asynchronous calling on a particular interface, the attempt to create a call object will
fail and the client must use the synchronous interface.
Related topics
C
a
n
c
e
l
i
n
g
a
n
A
s
y
n
c
h
r
o
n
o
u
s
C
a
l
l
C
l
i
e
n
t
S
e
c
u
r
i
t
y
D
u
r
i
n
g
a
n
A
s
y
n
c
h
r
o
n
o
u
s
C
a
l
l
I
m
p
e
r
s
o
n
a
t
i
o
n
a
n
d
A
s
y
n
c
h
r
o
n
o
u
s
C
a
l
l
s
Client Security During an Asynchronous Call
1/7/2020 • 2 minutes to read • Edit Online
The proxy manager created by MIDL for objects that use standard marshaling implements the IClientSecurity
interface. Clients can manage the security of marshaled calls by querying for IClientSecurity on the call object
and obtaining or changing security settings.
Related topics
M
a
k
i
n
g
a
n
A
s
y
n
c
h
r
o
n
o
u
s
C
a
l
l
Impersonation and Asynchronous Calls
1/7/2020 • 2 minutes to read • Edit Online
The server cannot impersonate the client after the server's call to ISynchronize::Signal completes, even if the
Begin_ method has not yet completed. For example, suppose a client calls the Begin_ method, the server processes
the call immediately, and the server calls Signal to indicate it is finished processing. Even if work remains to be
done in the Begin_ method, the server cannot impersonate the client after the call to Signal completes.
If the server impersonates the client before it calls Signal, the impersonation token will not be removed from the
thread until the server calls IServerSecurity::RevertToSelf or until the server's call to Begin_ returns, whichever
comes first.
Related topics
D
e
l
e
g
a
t
i
o
n
a
n
d
I
m
p
e
r
s
o
n
a
t
i
o
n
M
a
k
i
n
g
a
n
A
s
y
n
c
h
r
o
n
o
u
s
C
a
l
l
Canceling an Asynchronous Call
1/29/2020 • 2 minutes to read • Edit Online
A client can cancel an asynchronous call that is in progress if the call object implements the ICancelMethodCalls
interface. For objects that use standard marshaling, ICancelMethodCalls is always available for marshaled calls.
For objects that use custom marshaling or for calls to server objects within the same apartment, this functionality
is available only if the call object implements ICancelMethodCalls.
The client can cancel the call at any time, from when the Begin_ method is called until the Finish_ method returns.
If the client cancels the call before calling the Finish_ method, it must call the Finish_ method to clean up the state
of the call object. Until the client has done so, any calls to any Begin_ method on the call object will return
RPC_E_CALL_PENDING.
To cancel an asynchronous call
1. Query the call object for ICancelMethodCalls.
2. Call ICancelMethodCalls::Cancel, and then call Release to release the pointer obtained by the
QueryInterface call in step 1.
3. If the client has not called the Finish_ method already, call it now.
There is no guarantee that the server actually stopped execution of the call. If the client's further work depends on
some server state that the call may or may not have changed, the client should determine that state before
proceeding.
Related topics
M
a
k
i
n
g
a
n
A
s
y
n
c
h
r
o
n
o
u
s
C
a
l
l
Canceling Method Calls
1/7/2020 • 2 minutes to read • Edit Online
With the introduction of distributed and Web-based applications, some method calls can take an unacceptably long
time to return. The latency of the network connection may be high, the server machine may be serving many
clients, or the server component may be passing a large amount of data, such as a multimedia file. Users should be
able to cancel a request that is taking too long, and the application should be able to handle cancellation requests
and continue with its other work. In COM, you can use the IMessageFilter interface to cancel a pending call that
originates from a single-threaded apartment.
When a call is marshaled, the proxy creates a cancel object, which implements the ICancelMethodCalls interface.
The cancel object is associated with both the call and the thread on which the call is pending.
To cancel the pending call, the client passes a cancellation request through the cancel object, which handles the
details of notifying the server object that the call has been canceled. If the called method has not returned, the
server object, on detecting the cancellation request, cleans up any program resources it has allocated and notifies
its client, by returning an appropriate HRESULT value, that it canceled execution of the call. If the called method
has already returned, the cancel object notifies the client. In either case, the client thread is unblocked and can
continue processing.
How the server object responds to a cancellation request is at the discretion of the server implementer, but the
calling thread on the client will always be unblocked and will ignore whatever results the server tries to pass to it.
Cancel objects provide a means to request that a currently running method be canceled, but there is no guarantee
that the server object will stop processing the call. For example, the call may have already returned, or the server
object may not support cancel objects.
COM automatically provides a standard implementation of cancel objects for client objects and interfaces that use
standard marshaling. For objects and interfaces that use custom marshaling, you will need to implement your own
cancel object.
At this time, cancel objects handle only synchronous calls.
Related topics
C
a
n
c
e
l
i
n
g
a
n
A
s
y
n
c
h
r
o
n
o
u
s
C
a
l
l
C
o
G
e
t
C
a
n
c
e
l
O
b
j
e
c
t
C
o
S
e
t
C
a
n
c
e
l
O
b
j
e
c
t
C
o
T
e
s
t
C
a
n
c
e
l
Call Synchronization
1/7/2020 • 2 minutes to read • Edit Online
COM applications must be able to deal correctly with user input while processing one or more calls from COM or
the operating system. COM provides call synchronization for single-threaded apartments only. Multithreaded
apartments (containing free-threaded threads) do not receive calls while making calls (on the same thread).
Multithreaded apartments cannot make input synchronized calls. Asynchronous calls are converted to
synchronous calls in multithreaded apartments. The message filter is not called for any thread in a multithreaded
apartment. For more information about threading issues, see Processes, Threads, and Apartments.
COM calls between processes fall into three categories, as follows:
S
y
n
c
h
r
o
n
o
u
s
c
a
l
l
s
Most of the communication that takes place within COM is synchronous. When making synchronous calls,
the caller waits for the reply before continuing and can receive incoming messages while waiting. COM
enters a modal loop to wait for the reply, receiving and dispatching other messages in a controlled manner.
A
s
y
n
c
h
r
o
n
o
u
s
n
o
t
i
f
i
c
a
t
i
o
n
s
When sending asynchronous notifications, the caller does not wait for the reply. COM uses PostMessage or
high-level events to send asynchronous notifications, depending on the platform. COM defines five
asynchronous methods of IAdviseSink:
OnDataChange
OnViewChange
OnRename
OnSave
OnClose
NOTE
While COM is processing an asynchronous call, synchronous calls cannot be made. For example, a container
application's implementation of OnDataChange cannot contain a call to IPersistStorage::Save. These calls are the
only asynchronous calls supported by COM. There is no way to create a custom interface that is asynchronous at this
time.
I
n
p
u
t
-
s
y
n
c
h
r
o
n
i
z
e
d
c
a
l
l
s
When making input-synchronized calls, the object called must complete the call before yielding control. This
helps ensure that focus management works correctly and that data entered by the user is processed
appropriately. These calls are made by COM through the SendMessage function, without entering a modal
loop. While processing an input-synchronized call, the object called must not call any function or method
(including synchronous methods) that might yield control. The following methods are input synchronized
IOleWindow::GetWindow
IOleInPlaceActiveObject::OnFrameWindowActivate
IOleInPlaceActiveObject::OnDocWindowActivate
IOleInPlaceActiveObject::ResizeBorder
IOleInPlaceUIWindow::GetBorder
IOleInPlaceUIWindow::RequestBorderSpace
IOleInPlaceUIWindow::SetBorderSpace
IOleInPlaceFrame::SetMenu
IOleInPlaceFrame::SetStatusText
IOleInPlaceObject::SetObjectRects
To minimize problems that can arise from asynchronous message processing, the majority of COM method calls
are synchronous. With synchronous communication, there is no need for special code to dispatch and handle
incoming messages. When an application makes a synchronous method call, COM enters a modal wait loop that
handles the required replies and dispatches incoming messages to applications capable of processing them.
COM manages method calls by assigning an identifier called a logical thread ID. A new one is assigned when a
user selects a menu command or when the application initiates a new COM operation. Subsequent calls that relate
to the initial COM call are assigned the same logical thread ID as the initial call.
Defining COM Interfaces
1/7/2020 • 2 minutes to read • Edit Online
Microsoft defines many COM interfaces. In most cases, you can reuse these generic interfaces. However, some
applications have specific requirements that make it desirable or necessary to define your own object interfaces.
All COM interfaces must derive, directly or indirectly, from the IUnknown interface. Within that constraint, your
custom interface can support almost any method or parameter, including asynchronous methods. You can also
generate a type library for your custom interfaces so that clients can access information about your object's
methods at run time. After you define an interface, describe it in Microsoft Interface Definition Language (MIDL ),
compile and register it, you use it just like any generic interface. With distributed COM, interface methods are
available both to remote processes and to other processes on the same computer.
Finally, building COM interfaces requires a development environment that includes a C/C++ compiler and the
Midl.exe compiler.
The steps in creating a COM interface are as follows:
Decide how you want to provide marshaling support for your interface; either with type-library–driven
marshaling or with a proxy/stub DLL. Even in-process interfaces must be marshaled if they are to be used
across apartment boundaries. It is a good idea to build marshaling support into every COM interface, even if
you don't think you will need it. See Interface Marshaling for more information.
Describe the interface or interfaces in an interface definition (IDL ) file. In addition, you can specify certain local
aspects of your interface in an application configuration file (ACF ). If you are using type-library–driven
marshaling, add a library statement that references the interfaces for which you want to generate type
information.
Use the MIDL compiler to generate a type library file and header file, or C -language proxy/stub files, interface
identifier file, DLL data file and header file. See MIDL Compilation for more information.
Depending on the marshaling method you chose, write a module definition (DEF ) file, compile and link all the
MIDL -generated files into a single proxy DLL, and register the interface in the system registry, or register the
type library. See Loading and Registering a Type Library and Building and Registering a Proxy DLL for more
information.
Related topics
A
n
a
t
o
m
y
o
f
a
n
I
D
L
F
i
l
e
C
O
M
C
l
i
e
n
t
s
a
n
d
S
e
r
v
e
r
s
I
n
t
e
r
f
a
c
e
D
e
s
i
g
n
R
u
l
e
s
T
h
e
C
o
m
p
o
n
e
n
t
O
b
j
e
c
t
M
o
d
e
l
Interface Marshaling
1/7/2020 • 2 minutes to read • Edit Online
Unless you know beyond all doubt that your interface will never be used across apartment, thread, or process
boundaries, you need to decide how to provide marshaling support for your interfaces. There are three ways to
provide marshaling support:
Write your own proxy/stub code that calls the COM channel, which in turn calls the RPC run-time libraries.
Theoretically, it is possible to do this, but in practice it is almost impossible to do without a significant amount
of effort.
Describe your interfaces in an interface definition language (IDL ) file and use the MIDL compiler to generate a
proxy/stub DLL. This method provides the best performance and the most flexibility in terms of acceptable data
types. Using MIDL -generated proxy stubs, you can control not only memory management but even the
marshaling and unmarshaling of complex data types across different platforms.
Use MIDL to generate a type library that the system uses to provide marshaling support at run time. This is the
easiest way to implement marshaling support. All you have to do is generate a type library and register it. Your
interfaces must be Automation-compatible (either oleautomation or dual), which places some restrictions on
the kinds of data types you can use as method parameters. However, in most cases, the advantage of having
your interfaces accessible to programs written in other languages, such as Microsoft Visual Basic and Java,
outweighs the limitations on data types.
Related topics
I
n
t
e
r
-
O
b
j
e
c
t
C
o
m
m
u
n
i
c
a
t
i
o
n
Anatomy of an IDL File
1/7/2020 • 4 minutes to read • Edit Online
These example IDL files demonstrate the fundamental constructs of interface definition. Memory allocation,
custom marshaling, and asynchronous messaging are just a few of the features you can implement in a custom
COM interface. MIDL attributes are used to define COM interfaces. For more information about implementing
interfaces and type libraries, including a summary of MIDL attributes, see Interface Definitions and Type Libraries
in the MIDL Programmer's Guide and Reference. For a complete reference of all MIDL attributes, keywords, and
directives, see the MIDL Language Reference.
Example.idl
The following example IDL file defines two COM interfaces. From this IDL file, Midl.exe will generate proxy/stub
and marshaling code and header files. A line-by-line dissection follows the example.
//
// Example.idl
//
import "mydefs.h","unknwn.idl";
[
object,
uuid(a03d1420-b1ec-11d0-8c3a-00c04fc31d2f),
] interface IFace1 : IUnknown
{
HRESULT MethodA([in] short Bread, [out] BKFST * pBToast);
HRESULT MethodB([in, out] BKFST * pBPoptart);
};
[
object,
uuid(a03d1421-b1ec-11d0-8c3a-00c04fc31d2f),
pointer_default(unique)
] interface IFace2 : IUnknown
{
HRESULT MethodC([in] long Max,
[in, max_is(Max)] BkfstStuff[ ],
[out] long * pSize,
[out, size_is( , *pSize)] BKFST ** ppBKFST);
};
The IDL import statement is used here to bring in a header file, Mydefs.h, which contains user-defined types, and
Unknwn.idl, which contains the definition of IUnknown, from which IFace1 and IFace2 derive.
The object attribute identifies the interface as an object interface and tells the MIDL compiler to generate
proxy/stub code instead of RPC client and server stubs. Object interface methods must have a return type of
HRESULT, to allow the underlying RPC mechanism to report errors for calls that fail to complete due to network
problems.
The uuid attribute specifies the interface identifier (IID ). Each interface, class, and type library must be identified
with its own unique identifier. Use the utility Uuidgen.exe to generate a set of unique IDs for your interfaces and
other components.
The interface keyword defines the interface name. All object interfaces must derive, directly or indirectly, from
IUnknown.
The in directional parameter specifies a parameter that is set only by the caller. The out parameter specifies data
that is passed back to the caller. Using both directional attributes on one parameter specifies that the parameter is
used both to send data to the method and to pass data back to the caller.
The pointer_default attribute specifies the default pointer type (unique, ref, or ptr) for all pointers except for
those included in parameter lists. If no default type is specified, MIDL assumes that single pointers are unique.
However, when you have multiple levels of pointers, you must explicitly specify a default pointer type, even if you
want the default type to be unique.
In the preceding example, the array BkfstStuff[ ] is a conformant array, the size of which is determined at run time.
The max_is attribute specifies the variable that contains the maximum value for the array index.
The size_is attribute is also used to specify the size of an array or, as in the preceding example, multiple levels of
pointers. In the example, the call can be made without knowing in advance how much data will be returned.
Example2.idl
The following IDL example (which reuses the interfaces described in the previous IDL example) shows the various
ways to generate type library information for interfaces.
//
// Example2.idl
//
import "example.idl","oaidl.idl";
[
uuid(a03d1422-b1ec-11d0-8c3a-00c04fc31d2f),
helpstring("IFace3 interface"),
pointer_default(unique);
dual,
oleautomation
]
interface IFace3 : IDispatch
{
HRESULT MethodD([in] BSTR OrderIn,
[out, retval] * pTakeOut);
}; //end IFace3 def
[
uuid(a03d1423-b1ec-11d0-8c3a-00c04fc31d2f),
version(1.0),
helpstring("Example Type Library"),
] library ExampleLib
{
importlib("stdole32.tlb");
interface IFace3;
[
uuid(a03d1424-b1ec-11d0-8c3a-00c04fc31d2f),
helpstring("Breakfast Component Class")
] coclass BkfstComponent
{
[default]interface IFace1;
interfaceIFace2
}; //end coclass def
[
uuid(a03d1424-b1ec-11d0-8c3a-00c04fc31d2f),
helpstring("IFace4 interface"),
pointer_default(unique);
dual,
oleautomation
]
interface IFace4 : IDispatch
{
[propput] HRESULT MethodD([in] BSTR OrderIn);
[propget] HRESULT MethodE([out, retval] * pTakeOut);
}; //end IFace4 def
The helpstring attribute is optional; you use it to briefly describe the object or to provide a status line. These help
strings are readable with an object browser such as the one provided with Microsoft Visual Basic.
The dual attribute on IFace3 creates an interface that is both a dispatch interface and a COM interface. Because it
is derived from IDispatch, a dual interface supports Automation, which is what the oleautomation attribute
specifies. IFace3 imports Oaidl.idl to get the definition of IDispatch.
The library statement defines the ExampleLib type library, which has its own uuid, helpstring, and version
attributes.
Within the type library definition, the importlib directive brings in a compiled type library. All type library
definitions should bring in the base type library defined in Stdole32.tlb.
This type library definition demonstrates three different ways to include interfaces in the type library. IFace3 is
included merely by referencing it within the library statement.
The coclass statement defines an entirely new component class, BkfstComponent, that includes two previously
defined interfaces, IFace1 and IFace2. The default attribute designates IFace1 as the default interface.
IFace4 is described within the library statement. The propput attribute on MethodD indicates that the method
performs a set action on a property of the same name. The propget attribute indicates that the method retrieves
information from a property of the same name as the method. The retval attribute in MethodD designates an
output parameter that contains the return value of the function.
MIDL Compilation
1/7/2020 • 2 minutes to read • Edit Online
Given an IDL file, such as Example2.idl, that defines one or more COM interfaces and a type library, the MIDL
compiler (Midl.exe) generates the files described in the following table as the default output.
FILENAME DESCRIPTION
Example2_p.c The proxy/stub file, which includes the surrogate entry points
both for clients and for servers.
Example2_i.c The interface ID file, which defines the GUID for every
interface specified in the IDL file.
You use the header file and all of the .c files to create a proxy DLL that can support the interface when used both by
client applications and by object servers. You use the interface header file (Example2.h) and the interface ID
(Example2_i.c) file when creating the executable file for a client application that uses the interface. You can choose
to include the type library file as a resource in your EXE or DLL, or you can ship it as a separate file.
Related topics
F
i
l
e
s
G
e
n
e
r
a
t
e
d
f
o
r
a
C
O
M
I
n
t
e
r
f
a
c
e
M
I
D
L
C
o
m
p
i
l
e
r
O
p
t
i
o
n
s
MIDL Compiler Options
1/7/2020 • 2 minutes to read • Edit Online
You can use the following command-line options to override some of the default behavior of the MIDL compiler
and to choose optimizations appropriate for your application. For a complete listing of MIDL command-line
options, see the MIDL Command-Line Reference.
/dlldata Specifies a filename for the generated DLL data file for a proxy
DLL. The default filename is Dlldata.c.
/header, /h Specifies the name of the interface header file. The default
name is that of the IDL file with an .h extension.
/lcid Provides full DBCS support so that you can use international
characters in your input files, filenames, and directory paths.
/Oi, /Oic, /Oif Directs MIDL to use a fully interpreted marshaling method.
The /Oic and /Oicf switches provide additional performance
enhancements.
/proxy Specifies the name of the interface proxy file for a COM
interface. The default name is that of the IDL file plus "_p.c".
/tlb Specifies the name of the type library file. The default name is
that of the IDL file, with a .tlb extension.
Related topics
M
I
D
L
C
o
m
p
i
l
a
t
i
o
n
Loading and Registering a Type Library
1/7/2020 • 2 minutes to read • Edit Online
The Automation dynamic link library, Oleaut32.dll, provides several functions that you can call to load and register
a type library. Calling LoadTypeLibEx, as shown in the following example, both loads the library and creates the
registry entries.
Example
ITypeLib *pTypeLib;
HRESULT hr;
hr = LoadTypeLibEx("example.tlb", REGKIND_REGISTER, &pTypeLib);
if(SUCCEEDED(hr))
{
pTypeLib->Release();
} else {
exit(0); // Handle errors here.
}
Building and Registering a Proxy DLL
1/7/2020 • 2 minutes to read • Edit Online
If you chose proxy/stub marshaling for your application, the .c and .h files that MIDL generated must be compiled
and linked to create a proxy DLL, and that DLL must be entered into the system registry so that clients can locate
your interfaces. The MIDL -generated file Dlldata.c contains the necessary routines and other information to build
and register a proxy/stub DLL.
The first step in building the DLL is to write a module definition file for the linker, as shown in the following
example:
LIBRARY example.dll
DESCRIPTION 'generic proxy/stub DLL'
EXPORTS DllGetClassObject @1 PRIVATE
DllCanUnloadNow @2 PRIVATE
DllRegisterServer @4 PRIVATE
DllUnregisterServer @5 PRIVATE
Alternatively, you can specify these exported functions on the LINK command line of your makefile.
The exported functions are declared in Rpcproxy.h, which Dlldata.c includes, and default implementations are part
of the RPC run-time library. COM uses these functions to create a class factory, unload DLLs (after making sure
that no objects or locks exist), retrieve information about the proxy DLL, and to self-register and unregister the
proxy DLL. To take advantage of these predefined functions, you need to invoke the Cpreprocessor /D (or -D )
option when you compile the Dlldata.c and Example_p.c files, as shown in the following makefile:
If you do not specify these preprocessor definitions at compile time, these functions are not automatically defined.
(That is, the macros in Rpcproxy.c expand to nothing.) You would have to have defined them explicitly in another
source file, whose module would also be included in the final linking and compilation on the C compiler command
line.
When REGISTER_PROXY_DLL is defined, Rpcproxy.h provides for additional conditional compilation control with
PROXY_CLSID=guid, PROXY_CLSID_IS=explicit value of guid, and ENTRY_PREFIX=prefix string. These macro
definitions are described in greater detail in C -Compiler Definitions for Proxy/Stubs in the MIDL Programmer's
Guide.
HKEY_CLASSES_ROOT
Interface
iid
(Default) = ICustomInterfaceName
ProxyStubClsid32 = {clsid}
HKEY_CLASSES_ROOT
CLSID
clsid
(Default) = ICustomInterfaceName_PSFactory
InprocServer32 = proxstub.dll
Related topics
C
-
C
o
m
p
i
l
e
r
D
e
f
i
n
i
t
i
o
n
s
f
o
r
P
r
o
x
y
/
S
t
u
b
s
R
e
g
i
s
t
e
r
i
n
g
C
O
M
S
e
r
v
e
r
s
S
e
l
f
-
R
e
g
i
s
t
r
a
t
i
o
n
Interface Design Rules
1/7/2020 • 2 minutes to read • Edit Online
This section provides a short summary of interface design rules and guidelines. Some of these rules are specific to
the COM architecture, while others are restrictions imposed by the interface design language, MIDL. For details of
COM interface design, see Anatomy of an IDL File.
By definition, an object is not a COM object unless it implements either the IUnknown interface or an interface
that is derived from IUnknown. In addition, the following rules apply to all interfaces implemented on a COM
object:
They must have a unique interface identifier (IID ).
They must be immutable. Once they are created and published, no part of their definition may change.
All interface methods must return an HRESULT value so that the portions of the system that handle remote
processing can report RPC errors.
All string parameters in interface methods must be Unicode.
Your data types must be remotable. If you cannot convert a data type to a remotable type, you will have to
create your own marshaling and unmarshaling routines. Also, LPVOID, or void *, has no meaning on a remote
computer. Use a pointer to IUnknown, if necessary.
NOTE
The current implementation of MIDL does not handle function overloading or multiple inheritance.
Related topics
I
n
t
e
r
f
a
c
e
D
e
f
i
n
i
t
i
o
n
s
a
n
d
T
y
p
e
L
i
b
r
a
r
i
e
s
Designing Remotable Interfaces
1/29/2020 • 2 minutes to read • Edit Online
With the advent of the distributed component object model, it is important that your custom interface be
remotable, even if you intend to use it in-process only.
MIDL is more than just a way to generate header files for your interfaces. It is a programming language for
remoting that allows you to use your interfaces across machine, process, and thread boundaries. This means that
you need to verify the behavior of your MIDL -defined interfaces under those conditions before you release your
program to customers. If you made a mistake in your IDL and the interface is not remoted correctly, it can be
difficult to remedy that mistake. Either you have to revise your interface with a new IID and leave the old one in for
backward compatibility or you have to convert every client and every server machine everywhere at the same
time.
Even if your interface will never be used out-of-process, it may be used cross-thread. The worst problem for an
unchecked IDL file can arise for in-process servers that do not support multiple single-threaded apartments ). A
server that does not specify a threading model is implicitly single-threaded. Everything marked single-threaded is
forced over to the thread that first called CoInitialize or CoInitializeEx. If some other thread was the one that
activated the object, all the interfaces on that single-threaded server must be remoted back to the activating thread,
which can result in a return of REGDB_E_IIDNOTREG in response to a call to QueryInterface). Unless you can
absolutely assert that your interface is both in-process and always going to be called on the same thread, you will
get remoted at some time.
Finally, as an interface designer, you need to consider how client applications will use your interface. Two things,
together, determine whether an interface will be efficient across process and machine boundaries: the frequency of
method calls across the interface boundary, and the amount of data to be transferred in a given method call.
Although COM makes cross-process and cross-network calls transparent to programs, it cannot make high-
frequency and high-bandwidth calls efficient across address spaces. In some cases, it is more appropriate to design
interfaces that will normally be implemented only as in-process servers while other interfaces are more
appropriate for remote use.
Using a COM Interface
1/7/2020 • 2 minutes to read • Edit Online
The client code is the user of the COM interface. To use any COM interface, custom or standard, a client must know
its IID. In the following example, the driver that calls CustomRpt passes it the name of the object that is converted
to a wide-character format. The object name is fed to CreateFileMoniker so that a file moniker can be created
and the client can bind to the running object. After the object is running, CustomRpt can access a pointer to either
an interface in the standard proxy/stub, such as IPersistFile, or to the custom interface, ICustomInterface.
if(FAILED(hr))
{
printf("Client: CreateFileMoniker for Object failed");
return;
}
if (FAILED(hr)) {
printf("Client: QueryInterface IPersistFile failed (%x)\n", hr);
pIUnk->Release();
return;
}
if (FAILED(hr)) {
printf("Client: QueryInterface failed (%x)\n", hr);
pIUnk->Release();
pIPersistFile->Release();
return;
}
if (FAILED(hr))
{
printf("Client: pICustomInterface->CustomReport failed (%x)\n", hr);
pIUnk->Release();
pIPersistFile->Release();
return;
}
The registry is a system database that contains information about the configuration of system hardware and
software as well as about users of the system. Any Windows-based program can add information to the registry
and read information back from the registry. Clients search the registry for interesting components to use.
The registry maintains information about all the COM objects installed in the system. Whenever an application
creates an instance of a COM component, the registry is consulted to resolve either the CLSID or ProgID of the
component into the pathname of the server DLL or EXE that contains it. After determining the component's
server, Windows either loads the server into the process space of the client application (in-process components)
or starts the server in its own process space (local and remote servers). The server creates an instance of the
component and returns to the client a reference to one of the component's interfaces.
For more information about the Windows registry, see the following topics:
Registry Hierarchy
Classes and Servers
Classifying Components
Using OleView
Registering Components
Checking Registration
Unknown User Types
COM Registry Keys
Registry Hierarchy
1/7/2020 • 2 minutes to read • Edit Online
The registry is structured as a hierarchy of keys, subkeys, and named values or single default values. Subkeys can
have multiple subkeys and values. Keys are named by backslash-delimited strings. Each key in the registry can
have one or more values, which can contain strings, integral values, or binary data.
Related topics
R
e
g
i
s
t
e
r
i
n
g
C
O
M
A
p
p
l
i
c
a
t
i
o
n
s
Classes and Servers
1/7/2020 • 2 minutes to read • Edit Online
COM uses HKEY_CLASSES_ROOT for computer-wide settings but also allows per-user configuration of CLSIDS
for greater security and flexibility. COM first consults HKEY_CURRENT_USER\Software\Classes before looking
under HKEY_CLASSES_ROOT. COM keeps computer-wide information related to CLSIDs under
HKEY_CLASSES_ROOT\CLSID and keeps per-user class information under
HKEY_CURRENT_USER\Software\Classes\CLSID.
COM servers support self-registration. For an in-process server, this means that the DLL must export the
following functions:
DllRegisterServer
DllUnregisterServer
You must explicitly export these functions by using a module definition file, linker switches, or compiler directives.
The class store uses these functions to configure the local registry after downloading the file to the client machine.
In addition to class store, these functions are also used by other environments to install servers on host computers.
Related topics
R
e
g
i
s
t
e
r
i
n
g
C
O
M
A
p
p
l
i
c
a
t
i
o
n
s
Classifying Components
1/7/2020 • 2 minutes to read • Edit Online
While a client is able to browse through the list of CLSIDs in the registry and select a component to use, loading
each component in the registry and querying it for its supported interfaces is very time-consuming. To determine
whether a component supports the interfaces required before creating an instance of the component, a method to
classify components into categories was developed.
A component category is a set of interfaces that have been assigned a GUID named CATID. Components that
implement all of the interfaces in a component category register themselves as members of that component
category. Components that belong to a certain component category can then be selected from the registry. By
registering itself as a member of a component category, the component is guaranteeing that it supports all of the
member interfaces in the component category.
A component can be a member of many categories. It is not limited to supporting interfaces in a component
category. It can support any interface, in addition to those in a component category.
In contrast to the standard registration of components, in which developers must write code that manually
registers objects, component categories automates much of this work. The six methods of the ICatRegister
interface define component categories and register objects that implement or require them. The Component
Categories Manager object implements this interface. See ICatRegister and ICatInformation for additional
information on using component categories.
Related topics
R
e
g
i
s
t
e
r
i
n
g
C
O
M
A
p
p
l
i
c
a
t
i
o
n
s
Using OleView
1/7/2020 • 2 minutes to read • Edit Online
While the Registry Editor shows an unprocessed view of the registry and is helpful for learning the organization of
the registry, using the Registry Editor can be time-consuming.
OleView provides a higher-level view of the information contained in the registry. Rather than looking at a long list
of CLSIDs, OleView features tree controls with friendly names.
Related topics
R
e
g
i
s
t
e
r
i
n
g
C
O
M
A
p
p
l
i
c
a
t
i
o
n
s
Registering Components
1/7/2020 • 2 minutes to read • Edit Online
When the following types of applications are installed, installation information must be added to the registry,
usually through a setup program:
Server applications
Container/server applications
Container applications that allow linking to embedded objects
For all three instances, register COM library (DLL ) information and application-specific information.
The DLL registers the information for all its components by exporting DllRegisterServer and
DllUnregisterServer. Use the following functions to register and unregister a component:
RegOpenKeyEx
RegCreateKeyEx
RegSetValueEx
RegEnumKeyEx
RegDeleteKey
RegCloseKey
Related topics
R
e
g
i
s
t
e
r
i
n
g
C
O
M
A
p
p
l
i
c
a
t
i
o
n
s
Checking Registration
1/7/2020 • 2 minutes to read • Edit Online
Each time an application loads, it should check its registration to determine the following:
Whether the CLSIDs are present in the registry. If they are not present, the application should register as the
original setup.
Whether the application's CLSIDs are present in the register but have no OLE 2-related information in them. If
this is the case, the application should register as the original setup.
Whether the path containing server entries ( LocalServer and LocalServer32, InprocServer and InprocServer32,
and DefaultIcon) points to the location at which the application is currently installed. If the path does not,
rewrite the path entries to point to the current location.
Related topics
R
e
g
i
s
t
e
r
i
n
g
C
O
M
A
p
p
l
i
c
a
t
i
o
n
s
Unknown User Types
1/7/2020 • 2 minutes to read • Edit Online
You can ease product localization by adding the following registry key:
HKEY_LOCAL_MACHINES\SOFTWARE\Microsoft\OLE2\UnknownUserType = usertype
This key allows functions to return a specified string rather than a default value of "Unknown", enabling localizers
to specify a user type of a different language.
The COM default handler's implementation of IOleObject::GetUserType examines the registry by calling
OleRegGetUserType. If the object's class is not found in the registry, the user type from the object's IStorage
instance is returned. If the class is not found in the object's IStorage instance, the string "Unknown" is returned.
Related topics
R
e
g
i
s
t
e
r
i
n
g
C
O
M
A
p
p
l
i
c
a
t
i
o
n
s
COM Registry Keys
1/7/2020 • 2 minutes to read • Edit Online
The registry contains a wealth of information used by COM. The most important information is stored in the
following keys.
KEY DESCRIPTION
Related topics
R
e
g
i
s
t
e
r
i
n
g
C
O
M
A
p
p
l
i
c
a
t
i
o
n
s
Security in COM
1/7/2020 • 2 minutes to read • Edit Online
Security in COM is firmly based on the security provided by Windows and the underlying RPC security
mechanisms. COM security relies on authentication (the process of verifying a caller's identity) and
authorization (the process of determining whether a caller is authorized to do what it is asking to do). There
are two main types of security in COM: activation security and call security. Activation security determines
whether a client can launch a server at all. After a server has been launched, you can use call security to control
access to a server's objects.
In this security model, servers manage and help protect objects, clients get access to objects through servers,
and servers can attempt access while impersonating the client.
The system implements the Kerberos v5 authentication protocol and the Schannel security package. It also
includes features such as delegate-level impersonation, mutual authentication, the ability to set authentication
levels for an AppID in the registry, and cloaking. Using COM security, you can implement objects that can
perform privileged operations without compromising security.
Because there is a wide range of COM security features available, it is helpful to initially determine what kind of
security your application needs. For most applications, setting an acceptable level of security can be a painless
process, but you can also use COM security to support very complex security scenarios.
You can set security processwide, either by using Dcomcnfg.exe to set the registry or by calling
CoInitializeSecurity. Two primary interfaces, IClientSecurity and IServerSecurity (and associated helper
functions), allow you to set call-level security within your program.
To learn more about COM security, see the following topics:
Determining Your Security Needs
COM Security Defaults
Activation Security
Security Values
Setting Security for COM Applications
Enabling COM Security Using DCOMCNFG
Turning Off Security
Server-Side Security
Security Blanket Negotiation
COM and Security Packages
DCOM Security Enhancements in Windows XP Service Pack 2 and Windows Server 2003 Service Pack 1
Access Control Lists for COM
The COM Elevation Moniker
Determining Your Security Needs
1/7/2020 • 2 minutes to read • Edit Online
How you set up COM security for your application depends on what kind of security your application needs. There
are several common situations that determine what you should do.
If you decide to use the COM security defaults, you do not have to do anything—COM handles it all. For
information on what these default settings are, see COM Security Defaults.
You can also prevent any remote calls into your machine by disabling DCOM altogether (COM between remote
computers). For more information, see Setting System-Wide Security Using DCOMCNFG.
For legacy or new applications, you can set process-wide security in the registry. For more information, see Setting
Processwide Security Through the Registry.
You can also override default security settings for calls to certain interfaces in the process while setting default
security for the remainder of the process (to allow COM to handle the general cases). For more information, see
Setting Security at the Interface Proxy Level.
For complex security requirements, you can handle all security programmatically rather than allowing COM to
handle it for you. To do this, call CoInitializeSecurity to disable automatic authentication, and then control all the
security settings by setting security on a per-interface proxy basis. For more information, see Setting Processwide
Security with CoInitializeSecurity and Setting Security at the Interface Proxy Level.
In some scenarios, you might want to turn off security completely. You might decide that your application does not
need any security, or you might want to disable security during development time so that you can enable security
features individually. To learn how to disable COM security, see Turning Off Security.
Security in COM relies on authentication services administered by security packages. NTLMSSP works well for
many applications but does not provide the more robust security offered by other packages. Therefore, COM
supports the Schannel security package and the Kerberos v5 security protocol. For more details on using these
security packages, see COM and Security Packages.
Related topics
S
e
c
u
r
i
t
y
i
n
C
O
M
COM Security Defaults
1/7/2020 • 2 minutes to read • Edit Online
You can use the COM security defaults for your application rather than specifying your own security settings. In
that case, COM will initialize and manage security for you. You do not need to configure the registry or call any
security functions in your program.
However, if certain registry named values have been set or modified, the security defaults that COM uses will be
affected. The list below describes COM security default values and explains how some values are influenced by
registry settings.
Following are the default security values that COM uses:
The default security service provider is the one that is determined by COM to be the most compatible with the
environment. COM chooses either the Kerberos v5 protocol or NTLMSSP, with the Kerberos protocol being
the default choice. None of the protocols provided by Schannel are ever chosen as the default.
The system identifies a caller through user name and password and automatically creates an identification
token used by the security system.
If the LegacyAuthenticationLevel named value exists and if its value has been set, that value is used. Otherwise,
the authentication level is set at connect (RPC_C_AUTHN_LEVEL_CONNECT). This level means that at the first
call a client makes to the server, COM does an authentication check. If the client passes the check, no further
authentication is done. The AuthenticationLevel value can also be set under the AppID key.
If the LegacyImpersonationLevel named value exists and if its value has been set, that value is used. Otherwise,
the impersonation level is set to identify (RPC_C_IMP_LEVEL_IDENTIFY ). Impersonation rights are granted by
the client to the server. Identify level means that the server can obtain the client's identity. The server can
impersonate the client for access control list (ACL ) checking but cannot access system objects as the client. For
more information, see Impersonation Levels and Cloaking.
If the AccessPermission named value under AppID exists and has been set, that value is used. Otherwise, COM
checks for a DefaultAccessPermission entry. If present, that value is used. If this value is not present, COM
constructs an ACL that grants permissions to the server identity and the local system.
If the SRPTrustLevel named value under AppID exists and has been set, that value is used. Otherwise, the
Software Restriction Policy (SRP ) trust level is set to Disallowed (SAFER_LEVELID_DISALLOWED ), which
indicates that the application is run in a constrained environment and is disallowed from accessing any
security-sensitive user privileges of the user.
Related topics
S
e
c
u
r
i
t
y
i
n
C
O
M
Activation Security
1/7/2020 • 2 minutes to read • Edit Online
Activation security (also called launch security) helps control who can launch a server. Activation security is
automatically applied by the service control manager (SCM ) of a particular computer. Upon receipt of a request
from a client to activate an object (as described in Instance Creation Helper Functions), the SCM checks the
request against activation-security information stored within its registry. (Activation security is also checked for
same-computer activations.)
When determining the identity of the client, activation examines the cloaking flag set in the client's call to
CoInitializeSecurity. If the cloaking flag is set (for either dynamic or static cloaking), the thread token is used, if
present, to determine the identity of the client. If no cloaking is set, the process token is used instead of the thread
token.
For more information about activation security, see COAUTHINFO and COSERVERINFO.
Related topics
S
e
c
u
r
i
t
y
i
n
C
O
M
Security Values
1/7/2020 • 2 minutes to read • Edit Online
Several values affect security for COM applications, including authentication level, impersonation level, cloaking,
application identity, software restriction policy configuration, and reference tracking.
For more information, see the following topics:
Authentication Level describes how to help control the amount of protection for communication between COM
objects.
Delegation and Impersonation explains how cloaking affects the identity presented to the server during
impersonation and how the client grants the server the authority to act on its behalf.
Application Identity identifies and explains the identities your application can use.
Software Restriction Policy explains how to help protect your system from the dangers associated with running
unknown code.
Reference Tracking explains how you can ensure that objects are not released too early.
Related topics
S
e
c
u
r
i
t
y
i
n
C
O
M
Authentication Level
1/7/2020 • 2 minutes to read • Edit Online
The authentication level controls how much security a client or server wants from its SSP. The authentication level
is set by passing an appropriate RPC_C_AUTHN_LEVEL_xxx value to CoInitializeSecurity or
CoSetProxyBlanket through the dwAuthnLevel parameter. The authentication levels from the client and server
are compared during the handshake, and the higher level security protection setting is used for the connection.
The different authentication levels are described as follows, from lowest level security protection to highest:
N
o
n
e
(
R
P
C
_
C
_
A
U
T
H
N
_
L
E
V
E
L
_
N
O
N
E
)
No authentication is performed during the communication between client and server. All security settings are
ignored. This authentication level can be set only if the authentication service level is
RPC_C_AUTHN_NONE.
D
e
f
a
u
l
t
(
R
P
C
_
C
_
A
U
T
H
N
_
L
E
V
E
L
_
D
E
F
A
U
L
T
)
COM chooses the authentication level by using its normal security blanket negotiation. It will never choose
an authentication level of None.
C
o
n
n
e
c
t
(
R
P
C
_
C
_
A
U
T
H
N
_
L
E
V
E
L
_
C
O
N
N
E
C
T
)
The normal authentication handshake occurs between the client and server, and a session key is established
but that key is never used for communication between the client and server. All communication after the
handshake is nonsecure.
C
a
l
l
(
R
P
C
_
C
_
A
U
T
H
N
_
L
E
V
E
L
_
C
A
L
L
)
Only the headers of the beginning of each call are signed. The rest of the data exchanged between the client
and server is neither signed nor encrypted. Most SSPs do not support this authentication level and silently
promote it to Packet.
P
a
c
k
e
t
(
R
P
C
_
C
_
A
U
T
H
N
_
L
E
V
E
L
_
P
K
T
)
The header of each packet is signed but not encrypted. The packets themselves are not signed or encrypted.
P
a
c
k
e
t
I
n
t
e
g
r
i
t
y
(
R
P
C
_
C
_
A
U
T
H
N
_
L
E
V
E
L
_
P
K
T
_
I
N
T
E
G
R
I
T
Y
)
Each packet of data is signed in its entirety but is not encrypted. Because all of the data is signed by the
sender, the recipient can be certain that none of the data has been tampered with during transit.
P
a
c
k
e
t
P
r
i
v
a
c
y
(
R
P
C
_
C
_
A
U
T
H
N
_
L
E
V
E
L
_
P
K
T
_
P
R
I
V
A
C
Y
)
Each data packet is signed and encrypted. This helps protect the entire communication between the client
and server.
Related topics
A
u
t
h
e
n
t
i
c
a
t
i
o
n
L
e
v
e
l
L
e
g
a
c
y
A
u
t
h
e
n
t
i
c
a
t
i
o
n
L
e
v
e
l
Delegation and Impersonation
1/7/2020 • 2 minutes to read • Edit Online
In client/server scenarios, it is common for one server to call another server to accomplish some task on a client's
behalf. The situation where a server is given the authority to act on a client's behalf is called delegation.
From a security standpoint, two issues arise regarding delegation:
What should the server be allowed to do when acting on the client's behalf?
What identity is presented by the server when it calls other servers on behalf of a client?
To deal with these issues, COM provides the following functionality. The client can set an impersonation level that
determines to what extent the server will be able to act as the client. If the client grants enough authority to the
server, the server can impersonate (pretend to be) the client. When impersonating the client, the server is given
access to only those objects or resources that the client has permission to use. The server, acting as a client, can
also enable cloaking to mask its own identity and project the client's identity in calls to other COM components.
Consider the scenario illustrated by the preceding figure, where A and B are processes on a different machine
from C. Process A calls B, and B calls C. Client A sets the impersonation level. B sets the cloaking capability. If A
sets an impersonation level that permits impersonation, B can impersonate A when calling C on A's behalf. The
identity that is presented to process C will be either A's identity or B's identity, depending on whether cloaking
was enabled by B. If cloaking is enabled, the identity presented to process C will be that of A. If cloaking is not
enabled, B's identity will be presented to C.
For more information, see the following topics:
Impersonation
Impersonation Levels
Cloaking
Impersonation
1/7/2020 • 2 minutes to read • Edit Online
Impersonation is the ability of a thread to execute in a security context that is different from the context of the
process that owns the thread. When running in the client's security context, the server "is" the client, to some
degree. The server thread uses an access token representing the client's credentials to obtain access to the objects
to which the client has access.
The primary reason for impersonation is to cause access checks to be performed against the client's identity. Using
the client's identity for access checks can cause access to be either restricted or expanded, depending on what the
client has permission to do. For example, suppose a file server has files containing confidential information and
that each of these files is protected by an ACL. To help prevent a client from obtaining unauthorized access to
information in these files, the server can impersonate the client before accessing the files.
Related topics
A
c
c
e
s
s
T
o
k
e
n
s
D
e
l
e
g
a
t
i
o
n
a
n
d
I
m
p
e
r
s
o
n
a
t
i
o
n
Impersonation Levels
1/7/2020 • 2 minutes to read • Edit Online
If impersonation succeeds, it means that the client has agreed to let the server be the client to some degree. The
varying degrees of impersonation are called impersonation levels, and they indicate how much authority is given
to the server when it is impersonating the client.
Currently, there are four impersonation levels: anonymous, identify, impersonate, and delegate. The following list
briefly describes each impersonation level:
a
n
o
n
y
m
o
u
s
(
R
P
C
_
C
_
I
M
P
_
L
E
V
E
L
_
A
N
O
N
Y
M
O
U
S
)
The client is anonymous to the server. The server process can impersonate the client, but the impersonation
token does not contain any information about the client. This level is only supported over the local
interprocess communication transport. All other transports silently promote this level to identify.
i
d
e
n
t
i
f
y
(
R
P
C
_
C
_
I
M
P
_
L
E
V
E
L
_
I
D
E
N
T
I
F
Y
)
The system default level. The server can obtain the client's identity, and the server can impersonate the
client to do ACL checks.
i
m
p
e
r
s
o
n
a
t
e
(
R
P
C
_
C
_
I
M
P
_
L
E
V
E
L
_
I
M
P
E
R
S
O
N
A
T
E
)
The server can impersonate the client's security context while acting on behalf of the client. The server can
access local resources as the client. If the server is local, it can access network resources as the client. If the
server is remote, it can access only resources that are on the same computer as the server.
d
e
l
e
g
a
t
e
(
R
P
C
_
C
_
I
M
P
_
L
E
V
E
L
_
D
E
L
E
G
A
T
E
)
The most powerful impersonation level. When this level is selected, the server (whether local or remote) can
impersonate the client's security context while acting on behalf of the client. During impersonation, the
client's credentials (both local and network) can be passed to any number of computers.
For impersonation to work at the delegate level, the following requirements must be met:
The client must set the impersonation level to RPC_C_IMP_LEVEL_DELEGATE.
The client account must not be marked "Account is sensitive and cannot be delegated" in the Active
Directory Service.
The server account must be marked with the "Trusted for delegation" attribute in the Active Directory
Service.
The computers hosting the client, the server, and any "downstream" servers must all be running in a
domain.
By choosing the impersonation level, the client tells the server how far it can go in impersonating the client. The
client sets the impersonation level on the proxy it uses to communicate with the server.
Related topics
D
e
l
e
g
a
t
i
o
n
a
n
d
I
m
p
e
r
s
o
n
a
t
i
o
n
Cloaking
1/7/2020 • 6 minutes to read • Edit Online
Cloaking is a COM security capability that determines what identity the client projects toward the server during
impersonation. When cloaking is set, the intermediate server masks its own identity and presents the client's
identity to the server that it calls on the client's behalf. Basically; the client identity that is seen by the server is the
identity associated with the proxy. The proxy's identity is determined by several factors, one of which is the type of
cloaking that is set (if any). Cloaking is not supported by the Schannel security provider.
The following topics provide more information about cloaking:
Types of Cloaking
How Cloaking Affects Client Identity
Setting Cloaking
Cloaking and Impersonation Levels
Cloaking Scenarios
Related topics
Types of Cloaking
There are two types of cloaking: static cloaking and dynamic cloaking:
With static cloaking (EOAC_STATIC_CLOAKING ), the server sees the thread token from the first call from a
client to the server. For the first call, if the proxy identity was previously set during a call to
CoSetProxyBlanket, that proxy identity is used. However, if the proxy identity was not previously set, the
thread token is used. If no thread token is present, the process token is used. For all future calls, the identity set
on the first call is used.
With dynamic cloaking (EOAC_DYNAMIC_CLOAKING ), on each call the current thread token (if there is a
thread token) is used to determine the client's identity. If there is no thread token, the process token is used.
This means that servers called on the client's behalf during impersonation see the identity of the COM client
that originated the call, which is generally the desired behavior. (Of course, for impersonation to succeed, the
client must have given the server authority to impersonate by setting an appropriate impersonation level. For
more information, see Impersonation Levels.) This type of cloaking is expensive.
The following flowchart illustrates how the proxy identity is determined in different situations.
Setting Cloaking
Cloaking is set as a capability flag in a call to CoInitializeSecurity, which sets cloaking for the entire process. The
cloaking capability is then set until the client changes it through a call to IClientSecurity::SetBlanket (or to
CoSetProxyBlanket), which sets cloaking for the proxy.
By default, cloaking is not set. To set it, pass EOAC_STATIC_CLOAKING or EOAC_DYNAMIC_CLOAKING to the
pCapabilities parameter in CoInitializeSecurity or SetBlanket.
When static cloaking is enabled using CoInitializeSecurity, each proxy picks up a token (thread or process) the
first time you make a call on the proxy. When static cloaking is enabled using SetBlanket, the proxy picks up the
token on the thread at that time. If no thread token is available when SetBlanket is called, the process token is
used for the proxy's identity. Basically, SetBlanket fixes the identity of the proxy.
With dynamic cloaking, the proxy's identity is determined the same way regardless of whether dynamic cloaking
is set using CoInitializeSecurity or with SetBlanket. The current thread token is used if there is one; otherwise,
the process token is used.
If cloaking is set for the entire process through a call to CoInitializeSecurity and you want to make calls with the
process token, do not impersonate while making calls.
With static cloaking, the server sees the proxy identity that was set during the first call from the client to the
server. The following figure shows an example of the proxy identity being set during a call from B to C. On a
subsequent call, Process D sees B's identity when static cloaking is set by B and C.
With dynamic cloaking, the identity of the caller during impersonation is based on the current thread token, if
there is one. The following illustration shows the situation where B and C set dynamic cloaking and D sees the
identity of A, despite an earlier call from B to C.
Related topics
D
e
l
e
g
a
t
i
o
n
a
n
d
I
m
p
e
r
s
o
n
a
t
i
o
n
Application Identity
1/7/2020 • 2 minutes to read • Edit Online
An application's identity is the account that is used to run the application. The identity can be that of the user that
is currently logged on (the interactive user), the user that launched the server, a specified user, or a service. To learn
how to set application identity using Dcomcnfg.exe, see Setting Processwide Security Using DCOMCNFG.
The following topics describe each of the four types of application identity and explain the limitations of each type:
Interactive User
Launching User
Specified User
Service Identity
Interactive User
1/7/2020 • 2 minutes to read • Edit Online
The interactive user is the user that is currently logged on to the computer where the COM server is running. If
the identity is set to be the interactive user, all clients use the same instance of the server if the server registers its
class factory as multi-use. If no user is logged on, the server will not run. If the server has a graphical user
interface (GUI) that the client needs to see, you should use interactive user for the server's identity. However,
choosing this identity carries some security risks because the server runs under the identity of the logged on user
without the logged on user's knowledge or consent. In addition, a service application cannot display a user
interface. For more information, see Interactive Services.
If a COM server is configured to run as the interactive user, in a terminal services environment, the server will be
launched in the interactive session that matches the client's user identity. However, the client application can use
the session moniker to reference an object provided by the server in a session that does not match the client
identity. When this is used, the client application can specify any session, in which case the server will run as the
user who owns the session, not the launching user. The default access permissions in this scenario would not allow
the launching user to call methods on the server. However, the following security risks remain:
If the COM server exposes interfaces that are not controlled by COM, such as TCP ports, named pipes, LPC
ports, shared memory sections, and so on, these could be used by the launching user to influence the server.
COM objects configured to run as the interactive user should reduce this attack surface as much as possible.
COM objects are free to set their own access permissions. If the object sets access permissions, either in its
AppID registration or by calling CoInitializeSecurity, to allow the launching user access, the user would be
able to launch the server to run as another user, then access the object.
Related topics
A
p
p
l
i
c
a
t
i
o
n
I
d
e
n
t
i
t
y
L
a
u
n
c
h
i
n
g
U
s
e
r
S
e
r
v
i
c
e
I
d
e
n
t
i
t
y
S
p
e
c
i
f
i
e
d
U
s
e
r
Launching User
1/7/2020 • 2 minutes to read • Edit Online
This is the default setting for the application identity. When the launching user is chosen for the application's
identity, each client account gets a new instance of the server and each server gets its own window station.
Because of the separate server instances, launching user is the highest-level security protection identity setting.
However, there are finite limits on resource consumption. Also, any GUI the server displays will not be seen by the
client.
If the application has the identity of the launching user, it runs with an impersonation token. For more information
about impersonation and access tokens, see Impersonation Levels and Cloaking.
Related topics
A
p
p
l
i
c
a
t
i
o
n
I
d
e
n
t
i
t
y
I
n
t
e
r
a
c
t
i
v
e
U
s
e
r
S
e
r
v
i
c
e
I
d
e
n
t
i
t
y
S
p
e
c
i
f
i
e
d
U
s
e
r
Specified User
1/7/2020 • 2 minutes to read • Edit Online
Specifying a particular user (and the user's password) is the preferred identity for COM servers. The reason this
identity is preferred is that no one has to be logged on the machine where the server is running for the server to
run, and every client talks to the same instance of the server if the server registers its class factory as multi-use. If
the server has a GUI, you should not choose this identity; if you do, the user will not be able to see the user
interface.
This type of server has a primary token and can access remote resources where a server that has the launching-
user identity might not be able to. For more information about impersonation and access tokens, see
Impersonation Levels and Cloaking.
Running as a fixed user account is more secure than the interactive user identity because this identity can be
assigned to the application only by someone who has the specific user's password.
Related topics
A
p
p
l
i
c
a
t
i
o
n
I
d
e
n
t
i
t
y
I
n
t
e
r
a
c
t
i
v
e
U
s
e
r
L
a
u
n
c
h
i
n
g
U
s
e
r
S
e
r
v
i
c
e
I
d
e
n
t
i
t
y
Service Identity
1/7/2020 • 2 minutes to read • Edit Online
Choosing this identity causes the application to be run as a service. You can set service accounts by choosing the
Services option from the Control Panel. For more information, see Installing as a Service Application.
Related topics
A
p
p
l
i
c
a
t
i
o
n
I
d
e
n
t
i
t
y
I
n
t
e
r
a
c
t
i
v
e
U
s
e
r
L
a
u
n
c
h
i
n
g
U
s
e
r
S
p
e
c
i
f
i
e
d
U
s
e
r
Software Restriction Policy
1/7/2020 • 2 minutes to read • Edit Online
The software restriction policy (SRP ) settings were introduced with the release of Windows XP to help protect
systems from unknown and possibly dangerous code. The SRP provides a mechanism where only trusted code is
given unrestricted access to a user's privileges. Unknown code, which might contain viruses or code that conflicts
with currently installed programs, is allowed to run only in a constrained environment (often called a sandbox)
where it is disallowed from accessing any security-sensitive user privileges. Properly using the SRP can make your
business more agile because it provides a proactive framework for preventing problems, rather than a reactive
framework that relies on the costly alternative of restoring a system after a problem has occurred.
The SRP depends upon assigning trust levels to the code that can run on a system. Currently, two trust levels exist:
Unrestricted and Disallowed. Code that has an Unrestricted trust level is given unrestricted access to the user's
privileges, so this trust level should be applied only to fully trusted code. Code with a Disallowed trust level is
disallowed from accessing any security-sensitive user privileges and can run only in a sandbox so that Unrestricted
code cannot load the Disallowed code into its address space.
The SRP configuration of individual COM applications is done through the SRPTrustLevel value in the
application's AppID key in the registry. If the SRP trust level is not specified for a COM application, the default
value of Disallowed is used. A COM application that has an Unrestricted trust level has unrestricted access to the
user's privileges but can load only components with an Unrestricted trust level, while a Disallowed COM
application can load components with any trust level but cannot access any security-sensitive user privileges.
In addition to the SRP trust levels of individual COM applications, two other SRP properties determine how the
SRP is used for all COM applications. If SRPRunningObjectChecks is enabled, attempts to connect to running
objects will be checked for appropriate SRP trust levels. The running object cannot have a less stringent SRP trust
level than the client object. For example, the running object cannot have a Disallowed trust level if the client object
has an Unrestricted trust level.
The second property determines how the SRP handles activate-as-activator connections. If
SRPActivateAsActivatorChecks is enabled, the SRP trust level that is configured for the server object is compared
with the SRP trust level of the client object and the more stringent trust level will be used to run the server object.
If SRPActivateAsActivatorChecks is not enabled, the server object runs with the SRP trust level of the client
object, regardless of the SRP trust level with which it was configured. By default, both
SRPRunningObjectChecks and SRPActivateAsActivatorChecks are enabled.
Reference Tracking
1/7/2020 • 2 minutes to read • Edit Online
Reference tracking can prevent the unintentional or malicious early release of objects.
When you enable reference tracking, you are requesting that distributed AddRef and Release calls be
authenticated by COM. When reference tracking is enabled, COM keeps track of per-user reference counts so that
a user can call Release only on objects that the user previously called AddRef on. Although reference tracking can
decrease performance, it ensures that no matter how many times a given user calls Release, the objects and stubs
will still exist if someone else has a reference to them.
The client can set reference tracking for a process by passing the EOAC_SECURE_REFS capability flag in a call to
CoInitializeSecurity. You can also enable or disable reference tracking for all applications on a computer by
using Dcomcnfg.exe.
If reference tracking is enabled, IUnknown always uses default security settings. In this case, calls to
CoSetProxyBlanket on IUnknown will fail.
Setting Security for COM Applications
1/7/2020 • 2 minutes to read • Edit Online
There are several ways you can help control security for your applications. You can change a computer's default
security settings, which are used by all applications on the computer that do not supply their own security values.
You can set security for a particular process, either by using Dcomcnfg.exe or by calling CoInitializeSecurity.
You can also programmatically control security settings at the interface proxy level.
The following topics provide procedures that explain how to set security:
Modifying the Security Defaults for a Computer
Setting Process-Wide Security
Setting Security at the Interface Proxy Level
Related topics
S
e
c
u
r
i
t
y
i
n
C
O
M
Modifying the Security Defaults for a Computer
1/7/2020 • 2 minutes to read • Edit Online
It is not recommended that you change the system-wide security settings, because this will affect all COM server
applications that do not set their own process-wide security, and might prevent them from working properly. If you
are changing the system-wide security settings to affect the security settings for a particular COM application, then
you should instead change the process-wide security settings for that particular COM application. For more
information about setting process-wide security, see Setting Process-Wide Security.
Certain values in the registry determine security settings for applications that do not call CoInitializeSecurity.
You can modify these settings using Dcomcnfg.exe.
For more information, see the following topics:
Registry Values for System-Wide Security
Setting System-Wide Security Using DCOMCNFG
Related topics
S
e
t
t
i
n
g
P
r
o
c
e
s
s
-
w
i
d
e
S
e
c
u
r
i
t
y
S
e
t
t
i
n
g
S
e
c
u
r
i
t
y
f
o
r
C
O
M
A
p
p
l
i
c
a
t
i
o
n
s
Registry Values for System-Wide Security
1/7/2020 • 2 minutes to read • Edit Online
It is not recommended that you change the system-wide security settings, because this will affect all COM server
applications that do not set their own process-wide security, and might prevent them from working properly. If you
are changing the system-wide security settings to affect the security settings for a particular COM application, then
you should instead change the process-wide security settings for that particular COM application. For more
information about setting process-wide security, see Setting Process-Wide Security.
Certain values in the registry are used to determine security settings for applications that do not call
CoInitializeSecurity. You can use Dcomcnfg.exe to modify these default security settings for a computer. For
step-by-step procedures that describe how to use Dcomcnfg.exe for this purpose, see Setting System-Wide
Security Using DCOMCNFG.
Another way to change default system-wide settings is to manipulate registry values directly. However, only
administrators and the system have full access to the portion of the registry that contains the default system-wide
call-security settings. All other users have read-access only.
The named values that affect system-wide security defaults are as follows:
DefaultLaunchPermission
DefaultAccessPermission
LegacyAuthenticationLevel
LegacyImpersonationLevel
LegacySecureReferences
SRPRunningObjectChecks
SRPActivateAsActivatorChecks
Related topics
S
e
t
t
i
n
g
P
r
o
c
e
s
s
-
W
i
d
e
S
e
c
u
r
i
t
y
Setting System-Wide Security Using DCOMCNFG
1/7/2020 • 7 minutes to read • Edit Online
Changing the system-wide security settings will affect all COM server applications that do not set their own
process-wide security. This may prevent such applications from working properly. If you are changing the system-
wide security settings to affect the security settings for a particular COM application, then you should instead
change the process-wide security settings for that particular COM application. For more information about setting
process-wide security, see Setting Process-wide Security.
When you want all of the applications on one computer that do not provide their own security to share the same
default security settings, you would set security on a system-wide basis. Using Dcomcnfg.exe makes it easy to set
default values in the registry that apply to all applications on a computer.
It is important to understand that if the client or server explicitly calls CoInitializeSecurity to set process-wide
security, the default settings in the registry will be ignored and the parameters to CoInitializeSecurity will be
used instead for the security settings for the process. Also, if you use Dcomcnfg.exe to specify security settings for
a particular process, the default computer settings are overridden by the settings for the process.
When enabling system-wide security, you must set the authentication level to a value other than None and you
must set launch and access permissions. You have the option of setting the default impersonation level, and you
also can enable reference tracking. The following topics provide step-by-step procedures:
Setting System-Wide Default Authentication Level
Setting System-Wide Launch Permissions
Setting System-Wide Access Permissions
Setting System-Wide Impersonation Level
Setting System-Wide Reference Tracking
Enabling and Disabling DCOM
Related topics
NOTE
If you disable DCOM on a remote computer, you will not be able to remotely access that computer afterward to re-enable
DCOM. To re-enable DCOM, you will need physical access to that computer.
Related topics
S
e
t
t
i
n
g
P
r
o
c
e
s
s
-
w
i
d
e
S
e
c
u
r
i
t
y
Setting Process-Wide Security
1/7/2020 • 2 minutes to read • Edit Online
There are several ways to set process-wide security. The first way, using the Dcomcnfg.exe tool, is easiest
because it requires no programming. The second technique offers the programmer more control, and it
requires a call to CoInitializeSecurity. Another technique is to set process-wide security in the registry by
using the AppID key.
For more information about these techniques, see the following topics:
Setting Process-Wide Security Using DCOMCNFG
Setting Process-Wide Security with CoInitializeSecurity
Setting Process-Wide Security Through the Registry
Related topics
S
e
t
t
i
n
g
S
e
c
u
r
i
t
y
a
t
t
h
e
I
n
t
e
r
f
a
c
e
P
r
o
x
y
L
e
v
e
l
S
e
t
t
i
n
g
S
e
c
u
r
i
t
y
f
o
r
C
O
M
A
p
p
l
i
c
a
t
i
o
n
s
Setting Process-Wide Security Using DCOMCNFG
1/7/2020 • 7 minutes to read • Edit Online
You might want to enable security for a particular application if an application has security needs that are different
from those required by other applications on the computer. For instance, you might decide to use system-wide
settings for your applications that require a low level of security while setting a higher level of security for a
particular application.
However, security settings in the registry that apply to a particular application are sometimes not used. For
example, the process-wide settings that you set in the registry using Dcomcnfg.exe will be overridden if a client
calls CoSetProxyBlanket to set security for a particular interface proxy. Similarly, if a client or server (or both)
call CoInitializeSecurity to set security for a process, the settings in the registry will be ignored and the
parameters specified to CoInitializeSecurity will be used instead.
When enabling security for an application, several settings may need to be modified. These include authentication
level, location, launch permissions, access permissions, and identity. For step-by-step procedures, see the
following:
Setting the Authentication Level for an Application
Setting the Location for an Application
Setting Launch Permissions for an Application
Setting Access Permissions for an Application
Setting the Identity for an Application
Browsing the User Database
Dcomcnfg.exe and 64-bit Applications
Related topics
Related topics
S
e
t
t
i
n
g
P
r
o
c
e
s
s
-
W
i
d
e
S
e
c
u
r
i
t
y
Setting Process-Wide Security with
CoInitializeSecurity
1/7/2020 • 2 minutes to read • Edit Online
The CoInitializeSecurity function allows you to control complex security scenarios by setting security for an
application programmatically. This topic describes scenarios when you might use CoInitializeSecurity and
provides some details on how you use it.
There are several reasons why you might want to use CoInitializeSecurity to set process-wide security within
your program. For example, although you can set the authentication level and the access permissions for the
application using dcomcnfg.exe, the default impersonation level for the computer might not be the one you want
for your process. The only way to change this setting for your process is to call CoInitializeSecurity.
If you want to use the Schannel security provider, you must specify it as an authentication service in a call to
CoInitializeSecurity.
Another common scenario in which you might set process-wide security programmatically is when you would like
to set default security for the entire process but you have one or more objects within that process that expose
interfaces with special security requirements. In this case, you can call CoInitializeSecurity to set security for the
process, allowing COM to handle most of the security checks, and you can call other methods to set security for
the objects with special security needs. Calling these methods and functions is described in Setting Security at the
Interface Proxy Level.
If your application has very specialized security requirements, such as allowing certain groups access to different
objects depending on the time of day, you might want to handle all of your security programmatically, ensuring
that COM does no automatic checking for you at all. To do this, you must call CoInitializeSecurity, setting the
dwAuthnLevel parameter to none and the pVoid parameter to NULL. If you have your own security package you
would also need to register it in the pAuthnSvc parameter. Then you can handle all of your own security
programmatically through calls to the proxy-level interface and functions described in Setting Security at the
Interface Proxy Level.
CoInitializeSecurity offers a rich set of capabilities. If you call CoInitializeSecurity, the registry values are
ignored and the security initialization values you pass in to the call are used instead. Depending on the result you
want, the first parameter, pVoid, can point to three different types of values: a SECURITY_DESCRIPTOR , an
IAccessControl object, or a pointer to an AppID. In most cases, you will use Windows functions to create a
SECURITY_DESCRIPTOR that pVoid will point to.
However, pVoid can also point to an IAccessControl object.
To indicate to CoInitializeSecurity that you are passing an IAccessControl object to pVoid, you must pass the
EOAC_ACCESS_CONTROL value to the dwCapabilities parameter. Since CoInitializeSecurity caches the results
of access checks, the access control list must not be changed after calling CoInitializeSecurity.
Another type of value you can pass to the pVoid parameter is a pointer to a GUID, which is the AppID of your
application. If pVoid is a pointer to an AppID, you must specify EOAC_APPID in the pCapabilities parameter so
that the function knows what value to expect in pVoid. If pVoid points to an AppID, CoInitializeSecurity uses
only the registry for authentication values and ignores all other parameters to CoInitializeSecurity.
Related topics
S
e
t
t
i
n
g
P
r
o
c
e
s
s
-
W
i
d
e
S
e
c
u
r
i
t
y
Setting Process-Wide Security Through the Registry
1/7/2020 • 2 minutes to read • Edit Online
If you want to set security for an entire process, one solution is to set the security levels you want in the registry. If
your application cannot call CoInitializeSecurity or if you prefer not to use programmatic security, this might be
a good option. If you decide to set process-wide security using the registry, you should be aware that if you call
CoInitializeSecurity within your program COM will use the values in CoInitializeSecurity and ignore the
registry values.
There are two ways to set security in the registry for your application:
You can use Dcomcnfg.exe, which provides a simple user interface for modifying security values. All COM
servers can be configured using Dcomcnfg.exe. For more information, see Setting Process-Wide Security Using
DCOMCNFG. However, client applications do not normally appear in Dcomcnfg.exe unless the client creates a
GUID and enters it in the registry.
You can set security values under the AppID key for the application. The rest of this topic explains how to set
security in the registry using the AppID key.
An AppID is a GUID that represents a server process for one or more classes. Each class is associated with exactly
one AppID, and AppIDs can be assigned only to EXEs. DLLs do not get AppIDs unless they are running in a
surrogate, and then it is the surrogate process that has the AppID. If multiple DLLs are loaded into a surrogate,
each surrogate has only one AppID.
For some COM servers, the registration code generates an AppID and places entries in the registry that map the
AppID to the name of the executable. But some COM servers do not provide this functionality. However, if the
server's registration code adds an entry for HKCR\CLSID {ServerCLSID }\LocalServer32 when dcomcnfg.exe is
run, it will automatically add an AppID for the CLSID.
For a COM client that is not a server, this mapping is not created because the client is never registered. Therefore,
to set security using the AppID key, the client must create the necessary registry entries, either programmatically
by using the registry functions or by using regedit.
If you decide to set process-wide security in the registry under the AppID key, be aware that there are two named
values under the AppID key that you can set without having administrator permissions:
AccessPermission
AuthenticationLevel
The AuthenticationLevel and AccessPermission values are set independently and have separate default values.
If the AuthenticationLevel value is not present, the LegacyAuthenticationLevel value is used as the default.
Similarly, if the AccessPermission value is not present, the DefaultAccessPermission value is used as the default.
However, the AuthenticationLevel and the AccessPermission values are interrelated in the following ways:
If the AuthenticationLevel is none, the AccessPermission and DefaultAccessPermission values are
ignored for that application.
If the AuthenticationLevel is not present and the LegacyAuthenticationLevel is none, the
AccessPermission and DefaultAccessPermission values are ignored for that application.
Related topics
S
e
t
t
i
n
g
P
r
o
c
e
s
s
-
W
i
d
e
S
e
c
u
r
i
t
y
Setting Security at the Interface Proxy Level
1/7/2020 • 2 minutes to read • Edit Online
Sometimes the client needs fine-grained control over the security on calls to particular interfaces. For example,
security might be set at a low level for the process but calls to a particular interface might require a higher
authentication level, such as encryption. The methods of the IClientSecurity interface allow the client to change
the security settings associated with calls to a particular interface by controlling the security settings at the
interface-proxy level.
The client can query an existing object for IClientSecurity and then call the IClientSecurity::QueryBlanket
method to find out what the current security settings are for a particular interface proxy. The
IClientSecurity::SetBlanket method can be used to modify the security settings for an individual interface
proxy on the object before calling one of the interface's methods. The new settings apply to any future callers of
this particular interface. The IClientSecurity::CopyProxy method provides a way for the client to copy an
interface proxy so that subsequent calls to SetBlanket on the copy do not affect callers of the original proxy.
SetBlanket is commonly used to raise the authentication level for a particular interface proxy to a higher level of
security protection. However, in some situations, it might also be helpful to lower the authentication level for a
particular interface proxy. For instance, suppose the default authentication level for the process is some value
other than RPC_C_AUTHN_LEVEL_NONE and the client and server are in separate domains that do not trust
each other. In this case, calls to the server will fail unless the client calls SetBlanket to lower the authentication
level to RPC_C_AUTHN_LEVEL_NONE.
Clients using the default implementation of IClientSecurity provided by the proxy manager can call the
CoQueryProxyBlanket, CoSetProxyBlanket, and CoCopyProxy helper functions instead of calling
IClientSecurity methods directly. The helper functions simplify the code but are slightly less efficient than calling
the corresponding IClientSecurity methods directly.
The IClientSecurity interface is implemented locally for the client by the proxy manager. Some custom
marshaled objects might not support IClientSecurity.
IClientSecurity works with all supported authentication services (currently NTLMSSP, Schannel, and the
Kerberos v5 protocol).
Related topics
S
e
t
t
i
n
g
S
e
c
u
r
i
t
y
f
o
r
C
O
M
A
p
p
l
i
c
a
t
i
o
n
s
Enabling COM Security Using DCOMCNFG
1/7/2020 • 2 minutes to read • Edit Online
Dcomcnfg.exe provides a user interface for modifying certain settings in the registry. By using Dcomcnfg.exe, you
can enable security either on a computer-wide or a process-wide basis. You can enable security for a particular
computer so that when a process does not provide its own security settings, either programmatically or through
registry values, the values set by Dcomcnfg.exe will be used. Or you can use Dcomcnfg.exe to enable security for a
particular application only.
When enabling security, there are two primary tasks to accomplish:
Set an authentication level that is not None.
Set permissions, including both launch and access permissions.
The steps taken to accomplish these tasks depend on whether you are enabling security for the whole computer or
just for a particular application. Also, you may want to set other values for the computer or application.
NOTE
You must be an administrator to run Dcomcnfg.exe.
The following topics provide step-by-step procedures on how to set security with Dcomcnfg.exe:
Setting System-Wide Security Using DCOMCNFG
Setting Processwide Security Using DCOMCNFG
Related topics
S
e
c
u
r
i
t
y
i
n
C
O
M
T
u
r
n
i
n
g
O
f
f
S
e
c
u
r
i
t
y
Turning Off Security
1/7/2020 • 2 minutes to read • Edit Online
There are several reasons why you might decide to turn off the security that COM provides. When developing
applications, it might be helpful to turn security off initially to allow you to focus on other functionality within your
application. Then, you can add security features to your design when you are ready. To facilitate debugging, you
may want to turn off security and then add security features one at a time. Finally, some applications do not need
security and might run faster if no security checks are done.
The following topics provide step-by-step procedures:
Turning Off Activation Security
Turning Off Call Security
Related topics
E
n
a
b
l
i
n
g
C
O
M
S
e
c
u
r
i
t
y
U
s
i
n
g
D
C
O
M
C
N
F
G
S
e
c
u
r
i
t
y
i
n
C
O
M
Turning Off Activation Security
1/7/2020 • 2 minutes to read • Edit Online
Normally, activation uses default security settings. However, you can control activation security by specifying a
COAUTHINFO structure, which is a member of the COSERVERINFO structure that is passed to the activation
functions. If the client specifies an authentication level of RPC_C_AUTHN_LEVEL_NONE in the COAUTHINFO
structure, authentication is not attempted. Otherwise, secure activation is attempted, and if authentication fails,
activation fails.
If the client does not specify an explicit COAUTHINFO structure and instead sets the pointer to NULL, COM will
attempt to authenticate the client. If it cannot authenticate the client, COM checks the launch permission security
descriptor to see whether there is a NULL DACL or an ACL that allows access to Everyone. If this check succeeds,
the server is launched. Therefore, even if the client does not specify a COAUTHINFOstructure, unsecure activation
may take place when the server allows it.
NOTE
To allow unauthenticated network users to run a COM application, the application roles must include the Anonymous user.
Starting with Windows Server 2003, by default, the Anonymous user is not included in the Everyone group.
Why would a client want to turn off activation security explicitly even though unsecure activation will eventually
take place if the server allows it? Because explicitly turning off activation security increases performance when the
client does not want or need security checks.
The following things must be done to explicitly turn off activation security:
The client must specify an authentication level of RPC_C_AUTHN_LEVEL_NONE in the COAUTHINFO
structure that is a member of the COSERVERINFO structure supplied to the activation function.
The client must specify an impersonation level of RPC_C_IMP_LEVEL_IMPERSONATE in the COAUTHINFO
structure that is a member of the COSERVERINFO structure supplied to the activation function. If this value is
not passed, you will get RPC_S_SERVER_UNAVAILABLE.
The server must specify Everyone for Default Launch Permissions. The recommended way to perform this
task is to use Dcomcnfg.exe as follows:
1. Run Dcomcnfg.exe.
2. On the Applications page, select the application that represents the server. Click the Properties button
(or double-click the selected application).
3. On the Security property page, click the Use Custom Launch Permissions button.
4. Click the Edit button in the Launch Permissions area.
5. In the Registry Value Permissions dialog box, click the Add button.
6. Select the entry for Everyone in the list box.
7. In the Type of Access list box, choose Allow Launch.
8. Click the OK button.
NOTE
In Windows Server 2003, the authentication capability for the COM+ system application includes the value
EOAC_DISABLE_AAA. This value, which disables activate-as-activator (AAA) activations, is used in the CoInitializeSecurity
call when launching the system application. Setting the authentication capability to EOAC_DISABLE_AAA allows an
application that runs under a privileged account (such as LocalSystem) to help prevent its identity from being used to launch
untrusted components.
Related topics
T
u
r
n
i
n
g
O
f
f
C
a
l
l
S
e
c
u
r
i
t
y
Turning Off Call Security
1/7/2020 • 2 minutes to read • Edit Online
Call security determines whether a client has permission to call a server's methods. There are two ways to disable
call security: One involves using Dcomcnfg.exe to modify the registry, and the other requires calls to
CoInitializeSecurity.
Turning Off Call Security Using DCOMCNFG
Turning Off Call Security Programmatically
Related topics
NOTE
Setting the computer-wide Authentication Level to None is extremely unsecure.
1. Run Dcomcnfg.exe.
2. Choose the Default Properties tab.
3. From the Default Authentication Level list box, choose (None).
4. Click the OK button.
Turning Off Call Security Programmatically
To turn call security off programmatically, both the client and the server must call CoInitializeSecurity, setting
the authentication level in the dwAuthnLevel parameter to RPC_C_AUTHN_LEVEL_NONE.
Related topics
T
u
r
n
i
n
g
O
f
f
A
c
t
i
v
a
t
i
o
n
S
e
c
u
r
i
t
y
Server-Side Security
1/7/2020 • 2 minutes to read • Edit Online
The server can retrieve security information about a caller or impersonate the caller by using the methods of
IServerSecurity. An implementation of IServerSecurity is supplied by COM on the context object for the current
call when standard marshaling is used. However, this interface may be absent for some custom-marshaled
interfaces.
When a call arrives at the server, the server can call CoGetCallContext to obtain a pointer to the IServerSecurity
interface. With this pointer, IServerSecurity methods can be called by the server to find out what the client's
authentication settings are and to impersonate the client, if needed. The IServerSecurity object is valid on any
thread in the apartment until the call represented by IServerSecurity completes. For more information about
impersonation, see Impersonation and Cloaking.
The following helper functions that rely on the call context object's IServerSecurity interface implementation are
also available:
CoQueryClientBlanket
CoImpersonateClient
CoRevertToSelf
Related topics
S
e
c
u
r
i
t
y
i
n
C
O
M
Security Blanket Negotiation
1/7/2020 • 2 minutes to read • Edit Online
A security blanket is a group of values that describe the security settings that apply to all proxies in a process or to
just a particular interface proxy. A security blanket comprises the following values:
Authentication service
Authorization service
Principal name
Authentication level
Impersonation level
Authentication identity
Capabilities
An access control list (ACL ) (servers only)
Security blanket negotiation is the process that COM uses to choose the security settings for a proxy when it is
created. This process involves comparing the server's security blanket with the client's security blanket and using
those values to create an appropriate default security blanket for the proxy. The following paragraphs explain
where the client's and the server's security blankets come from and describe how COM negotiates the security
blanket for the proxy using the client's and server's security blankets.
The client and the server can each call CoInitializeSecurity to specify their respective security blankets. If an
application doesn't call CoInitializeSecurity explicitly, COM calls it implicitly for the application, using
appropriate default values. For more information about these default values, see COM Security Defaults.
Some parameters to CoInitializeSecurity apply when the application is a server, and some apply when the
application is a client. When the application is acting as a server, these parameters are relevant: an ACL, a list of
authentication service/authorization service/principal name tuples, and an authentication level. A server's call to
CoInitializeSecurity, whether implicit or explicit, determines the server's security blanket, which remains fixed.
When the application is acting as a client, the following values passed to CoInitializeSecurity are relevant: an
authentication level, an impersonation level, the authentication identity, and capabilities. A client's implicit or
explicit call to CoInitializeSecurity indicates the security blanket that the client wants.
When a proxy is created, COM uses the values specified by the server's security blanket and the client's security
blanket to negotiate a default security blanket that is appropriate for the proxy. COM picks an authentication
service that works on both the client and server. The authorization service and principal name are chosen to work
with the authentication service. For the authentication level, COM chooses the higher of the authentication levels
specified by the client and the server. The impersonation level and the capabilities chosen by COM are the ones
specified by the client. The authentication identity is the one specified by the client for the chosen authentication
service.
Once the default security blanket has been computed, its values are assigned to the newly created proxy. The client
can override the security settings for the proxy by calling IClientSecurity::SetBlanket. The values specified to
SetBlanket are not negotiated; they are simply assigned to the specified proxy. However, if default parameters
(such as RPC_C_IMP_LEVEL_DEFAULT) are passed to SetBlanket, COM uses the previously described security
blanket negotiation algorithm to compute the default parameters.
Related topics
S
e
c
u
r
i
t
y
i
n
C
O
M
COM and Security Packages
1/7/2020 • 2 minutes to read • Edit Online
Windows supports NTLMSSP (LAN Manager Security Support Provider), the Kerberos v5 authentication
protocol, and the Schannel security package, which provides the PCT 1.0, SSL 2.0, SSL 3.0, and TLS 1.0 protocols.
Also supported is Snego, which checks for available security packages and selects the most appropriate one.
The following table shows the levels of authentication supported by the various security packages.
The client can authenticate the server, but not vice versa. Schannel
The client cannot discover the server, but the server can get NTLMSSP
the user ID of the client.
Mutual authentication: Both the client and server can know NTLMSSP (locally), Kerberos v5 protocol, and Schannel
the name of the other, if permission is granted.
For more information about these security packages, see the following topics in this section:
NTLMSSP
Kerberos v5 Protocol
Schannel
Snego
Related topics
S
e
c
u
r
i
t
y
i
n
C
O
M
NTLMSSP
1/7/2020 • 2 minutes to read • Edit Online
NTLMSSP, whose authentication service identifier is RPC_C_AUTHN_WINNT, is a security support provider that
is available on all versions of DCOM. It uses the NTLM protocol for authentication. NTLM never actually transmits
the user's password to the server during authentication. Therefore, the server cannot use the password during
impersonation to access network resources that the user would have access to. Only local resources can be
accessed.
NTLM works both locally and across computers. That is, if the client and server are on different computers, NTLM
can still make sure the client is who it claims to be.
With NTLM, the client's identity is represented by a domain name, user name, and a password or token. When a
server calls CoQueryClientBlanket, the client's domain name and user name are returned. However, when a
server calls CoImpersonateClient, the client's token is returned. If there is no trust relationship between client
and server and if the server has a local account with the same name and password as the client, that account will
be used to represent the client.
NTLM supports mutual authentication cross-thread and cross-process (locally only). If the client specifies the
principal name of the server in the form domain\user in a call to IClientSecurity::SetBlanket, the server's
identity must match that principal name or the call will fail. If the client specifies NULL, the server's identity will not
be checked.
NTLM additionally supports the delegate impersonation level cross-thread and cross-process (locally only).
Related topics
C
O
M
a
n
d
S
e
c
u
r
i
t
y
P
a
c
k
a
g
e
s
Kerberos v5 Protocol
1/7/2020 • 2 minutes to read • Edit Online
Related topics
C
O
M
a
n
d
S
e
c
u
r
i
t
y
P
a
c
k
a
g
e
s
Schannel
1/7/2020 • 11 minutes to read • Edit Online
The Secure Channel (Schannel) security package, whose authentication service identifier is
RPC_C_AUTHN_GSS_SCHANNEL, supports the following public-key based protocols: SSL (Secure Sockets
Layer) versions 2.0 and 3.0, Transport Layer Security (TLS ) 1.0, and Private Communication Technology (PCT) 1.0.
TLS 1.0 is a standardized, slightly modified version of SSL 3.0 that was issued by the Internet Engineering Task
Force (IETF ) in January 1999, in document RFC 2246. Because TLS has been standardized, developers are
encouraged to use TLS rather than SSL. PCT is included for backward compatibility only and should not be used
for new development. When the Schannel security package is used, DCOM automatically negotiates the best
protocol, depending on the client and server capabilities.
The following topics briefly describe the TLS protocol and how it works with DCOM.
When to Use TLS
Brief Overview of How TLS Works
X.509 Certificates
Client Certificates
Using TLS in COM
How a Server Sets the Security Blanket
How a Client Sets the Security Blanket
How a Client Changes the Security Blanket
Example: Client Changes the Security Blanket
Related topics
NOTE
All the information about the TLS protocol in these sections also applies to the SSL and PCT protocols.
X.509 Certificates
A critical issue that must be handled by a PKI is the ability to trust the authenticity of the public key that is being
used. When you use a public key issued to a company that you want to do business with, you want to be certain
that the key actually belongs to the company rather than to a thief who wants to discover your credit card number.
To guarantee the identity of a principal holding a key pair, the principal is issued an X.509 certificate by a
certification authority (CA). This certificate contains information that identifies the principal, contains the principal's
public key, and is digitally signed by the CA. This digital signature indicates that the CA believes that the public key
contained in the certificate truly belongs to the principal identified by the certificate.
And how do you trust the CA? Because the CA itself holds an X.509 certificate that has been signed by a higher-
level CA. This chain of certificate signatures continues until it reaches a root CA, which is a CA that signs its own
certificates. If you trust the integrity of the root CA of a certificate, you should be able to trust the authenticity of
the certificate itself. Therefore, picking root CAs that you are willing to trust is an important duty for a system
administrator.
Client Certificates
When security transport-layer protocols first emerged, their primary purpose was to guarantee that a client was
connecting to an authentic server and help protect the privacy of data while in transit. However, SSL 3.0 and TLS
1.0 also include support for the transmission of a client's certificate during the protocol's handshake. This optional
feature enables the mutual authentication of the client and server.
The decision of whether to use a client certificate should be made in the context of the application. Client
certificates are unnecessary if the primary requirement is authenticating the server. However, if client
authentication is essential, a client's certificate can be used rather than relying on custom authentication within the
application. Using client certificates is preferable over custom authentication because it gives users a single sign-
on scenario.
void ClientChangesSecurity ()
{
HCRYPTPROV provider = 0;
HCERTSTORE cert_store = NULL;
PCCERT_CONTEXT client_cert = NULL;
PCCERT_CONTEXT server_cert = NULL;
WCHAR *server_princ_name = NULL;
ISecret *pSecret = NULL;
MULTI_QI server_instance;
COSERVERINFO server_machine;
SOLE_AUTHENTICATION_LIST auth_list;
SOLE_AUTHENTICATION_INFO auth_info[1];
// Create a proxy.
CoCreateInstanceEx( CLSID_Secret, NULL, CLSCTX_REMOTE_SERVER,
&server_machine, 1, &server_instance);
pSecret = (ISecret *) server_instance.pItf;
//** The client obtained the server's certificate during the handshake.
//** The server requests a certificate from the client.
cleanup:
if (server_princ_name != NULL)
RpcStringFree( &server_princ_name );
if (client_cert != NULL)
CertFreeCertificateContext(client_cert);
if (server_cert != NULL)
CertFreeCertificateContext(server_cert);
if (cert_store != NULL)
CertCloseStore( cert_store, CERT_CLOSE_STORE_CHECK_FLAG );
if (provider != 0 )
CryptReleaseContext( provider, 0 );
if (pSecret != NULL)
pSecret->Release();
CoUninitialize();
}
Related topics
C
O
M
a
n
d
S
e
c
u
r
i
t
y
P
a
c
k
a
g
e
s
Snego
1/7/2020 • 2 minutes to read • Edit Online
Snego, whose authentication service identifier is RPC_C_AUTHN_GSS_NEGOTIATE, does not actually provide
authentication services itself. Instead, it takes a list of authentication services and negotiates a service that will work
between the client and server. The authentication parameters are not used by Snego but are passed to the chosen
authentication service, which does the actual authentication. Snego was standardized by the Internet Engineering
Task Force (IETF ) in December 1998, in document RFC 2478.
Snego is useful when you don't know what authentication services the remote computer can provide.
To use Snego, both the client and the server must specify Snego as the authentication service. The server specifies
RPC_C_AUTHN_GSS_NEGOTIATE as the dwAuthnSvc member of one of the
SOLE_AUTHENTICATION_SERVICE structures in the asAuthSvc array parameter that is passed to
CoInitializeSecurity. The client can specify Snego by calling CoSetProxyBlanket and passing
RPC_C_AUTHN_GSS_NEGOTIATE as the dwAuthnSvc parameter. The client should also provide a list of possible
authentication services for Snego through the PackageList member of the SEC_WINNT_AUTH_IDENTITY_EX
structure that is passed to the pAuthInfo parameter in the call to CoSetProxyBlanket. If pAuthInfo is NULL,
Snego composes a list of authentication services from the security packages installed on the computer. Then
Snego sends the list of authentication services to the server, compares the list to the server's available
authentication services, and picks an authentication service to use for the connection.
NOTE
Schannel cannot be on the list of authentication services that Snego uses.
Clients can also specify Snego when they call CoInitializeSecurity. The dwAuthnSvc and pAuthInfo parameters
of CoSetProxyBlanket become members of a SOLE_AUTHENTICATION_INFO structure that is passed to
CoInitializeSecurity through its pAuthList parameter. The details of the values of those members are the same as
described in the preceding paragraph.
If Snego is used, calls to CoQueryProxyBlanket or CoQueryClientBlanket will return Snego as the
authentication service, rather than the actual authentication service that Snego picked for establishing the
connection.
Related topics
C
O
M
a
n
d
S
e
c
u
r
i
t
y
P
a
c
k
a
g
e
s
DCOM Security Enhancements in Windows XP
Service Pack 2 and Windows Server 2003 Service
Pack 1
1/7/2020 • 17 minutes to read • Edit Online
Windows Server XP Service Pack 2 (SP2) and Windows Server 2003 Service Pack 1 (SP1) introduce enhanced
default security settings for the Distributed Component Object Model (DCOM ). Specifically, they introduce more
granular rights that enable an administrator to have independent control over local and remote permissions for
launching, activating, and accessing COM servers.
NOTE
Changing the computer-wide security settings will affect all COM server applications, and might prevent them from working
properly. If there are COM server applications that have restrictions that are less stringent than the computer-wide
restrictions, reducing the computer-wide restrictions might expose these applications to unwanted access. Conversely, if you
increase the computer-wide restrictions, some COM server applications might no longer be accessible by calling applications.
DISTRIBUTED COM
USERS (BUILT IN
PERMISSION ADMINISTRATOR GROUP) EVERYONE ANONYMOUS
NOTE
Distributed COM Users is a new built-in group included with Windows Server 2003 SP1 to expedite the process of adding
users to the DCOM computer restriction settings. This group is part of the ACL used by the MachineAccessRestriction and
MachineLaunchRestriction settings, so removing users from this group will affect those settings.
NOTE
Changing the computer-wide security settings will affect all COM server applications, and might prevent them from working
properly. If there are COM server applications that have restrictions that are less stringent than the computer-wide
restrictions, reducing the computer-wide restrictions may expose these applications to unwanted access. Conversely, if you
increase the computer-wide restrictions, some COM server applications might no longer be accessible by calling applications.
You can change the configuration settings using either the Component Services Microsoft Management Console
(MMC ) or the Windows registry.
If you use the Component Services MMC snap-in, these settings can be configured on the COM Security tab of
the Properties dialog box for the computer you are managing. The Access Permissions area has been modified
to enable you to set computer-wide limits in addition to the standard default settings for COM servers.
Additionally, you can provide separate ACL settings for local and remote access under both limits and defaults.
In the Launch and Activation Permissions area, you can control the local and remote permissions as well as the
computer-wide limits and the defaults. You can specify both local and remote activation and launch permissions
independently.
Alternatively, you can configure these ACL settings using the registry.
These ACLs are stored in the registry at the following locations:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole\MachineAccessRestriction=ACL
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole\MachineLaunchRestriction=ACL
These are named values of type REG_BINARY that contain data that describe the ACL of the principals that can
access any COM class or COM object on the computer. The access rights in the ACL are:
COM_RIGHTS_EXECUTE 1
COM_RIGHTS_EXECUTE_LOCAL 2
COM_RIGHTS_EXECUTE_REMOTE 4
COM_RIGHTS_ACTIVATE_LOCAL 8
COM_RIGHTS_ACTIVATE_REMOTE 16
NOTE
To provide backward compatibility, an ACL can exist in the format used before Windows XP SP2 and Windows Server 2003
SP1, which uses only the access right COM_RIGHTS_EXECUTE, or it can exist in the new format used in Windows XP SP2 and
Windows Server 2003 SP1, which uses COM_RIGHTS_EXECUTE together with a combination of
COM_RIGHTS_EXECUTE_LOCAL, COM_RIGHTS_EXECUTE_REMOTE, COM_RIGHTS_ACTIVATE_LOCAL, and
COM_RIGHTS_ACTIVATE_REMOTE. Note that COM_RIGHTS_EXECUTE> must always be present; the absence of this right
generates an invalid security descriptor. Also note that you must not mix the old format and the new format within a single
ACL; either all access control entries (ACEs) must grant only the COM_RIGHTS_EXECUTE access right, or they all must grant
COM_RIGHTS_EXECUTE together with a combination of COM_RIGHTS_EXECUTE_LOCAL, COM_RIGHTS_EXECUTE_REMOTE,
COM_RIGHTS_ACTIVATE_LOCAL, and COM_RIGHTS_ACTIVATE_REMOTE.
NOTE
Only users with Administrator rights can modify these settings.
Improper use of these settings can cause applications and Windows components that use DCOM to fail.
In the following table, these abbreviations are used:
LL - Local Launch
LA - Local Activation
RL - Remote Launch
RA - Remote Activation
LC - Local Access Calls
RC - Remote Access Calls
ACL - Access Control List
PREVIOUS DEFAULT
SETTING NAME LOCATION VALUE DEFAULT VALUE POSSIBLE VALUES
PREVIOUS DEFAULT
SETTING NAME LOCATION VALUE DEFAULT VALUE POSSIBLE VALUES
MachineLaunchRest HKEY_LOCAL_MACH Everyone - LL, LA, RL, Administrator: LL, LA, ACL
riction INE\SOFTWARE\ RA RL, RA
Microsoft\Ole Anonymous -
LL, LA, RL, RA
(This is a new registry
key. Based on existing
behavior, these are
the effective values.)
CallFailureLoggingL HKEY_LOCAL_MACH Not applicable. This registry key is 1 - Always log event
evel INE\SOFTWARE\ not present; however, log failures during a
Microsoft\Ole a missing key or value call in the COM
is interpreted as 2. Server process.
This event is not 2 - Never log event
logged by default. If log failures during a
you change this value call in the call server
to 1 to start logging process.
this information to
help you troubleshoot
an issue, be sure to
monitor the size of
your event log,
because this is an
event that can
generate a large
number of entries.
InvalidSecurityDesc HKEY_LOCAL_MACH Not applicable. This registry key is 1 - Always log event
riptorLoggingLevel INE\SOFTWARE\ not present; however, log failures when the
Microsoft\Ole a missing key or value COM infrastructure
is interpreted as 1. finds an invalid
This event is logged security descriptor.
by default. It should 2 - Never log event
rarely occur. log failures when the
COM infrastructure
finds an invalid
security descriptor.
DCOM:Machine (Group Policy object) Not applicable. Not defined Access control list in
Launch Restrictions in Computer SDDL format.
Security Descriptor Configuration Existence of this policy
Definition Language \Windows overrides values in
(SDDL) Syntax Settings\Local Policies MachineLaunchRestric
\Security Options tion, previously.
DCOM:Machine (Group Policy object) Not applicable. Not defined Access control list in
Access Restrictions in Computer SDDL format.
Security Descriptor Configuration Existence of this policy
Definition Language \Windows Settings overrides values in
(SDDL) Syntax \Local Policies MachineAccessRestric
\Security Options tion, previously.
What settings are added or changed in Windows Server 2003 Service
Pack 1?
NOTE
Improper use of these settings can cause applications and Windows components that use DCOM to fail.
PREVIOUS DEFAULT
SETTING NAME LOCATION VALUE DEFAULT VALUE POSSIBLE VALUES
MachineLaunchRest HKEY_LOCAL_MACH Everyone: LL, LA, RL, Administrator: LL, LA, ACL
riction INE\SOFTWARE\ RA RL, RA
Microsoft\Ole Anonymous: LL, LA, Everyone: LL, LA
RL, RA Distributed COM
(This is a new registry users: LL, LA, RL, RA
key. Based on existing
behavior, these would
be the effective
values.)
CallFailureLoggingL HKEY_LOCAL_MACH Not applicable. This registry key is 1 - Always log event
evel INE\SOFTWARE\ not present; however, log failures when the
Microsoft\Ole a missing key or value COM infrastructure
is interpreted as 2. finds an invalid
This event is not security descriptor.
logged by default. If 2 - Never log event
you change this value log failures when the
to 1 to start logging COM infrastructure
this information to finds an invalid
help you troubleshoot security descriptor.
an issue, be sure to
monitor the size of
your event log,
because this is an
event that can
generate a large
number of entries.
InvalidSecurityDesc HKEY_LOCAL_MACH Not applicable. This registry key is 1 - Always log event
riptorLoggingLevel INE\SOFTWARE\ not present; however, log failures when
Microsoft\Ole a missing key or value COM infrastructure
is interpreted as 1. finds an invalid
This event is logged security descriptor.
by default. It should 2 - Never log event
rarely occur. log failures when
COM infrastructure
finds an invalid
security descriptor.
DCOM:Machine (Group Policy object) Not applicable. Not defined. Access control list in
Launch Restrictions in Computer SDDL format.
Security Descriptor Configuration Existence of this policy
Definition Language \Windows Settings overrides values in
(SDDL) Syntax \Local Policies MachineLaunchRestric
\Security Options tion, previously.
DCOM:Machine (Group Policy object) Not applicable. Not defined. Access control list in
Access Restrictions in Computer SDDL format.
Security Descriptor Configuration Existence of this policy
Definition Language \Windows Settings overrides values in
(SDDL) Syntax \Local Policies MachineAccessRestric
\Security Options tion, previously.
Related topics
S
e
c
u
r
i
t
y
i
n
C
O
M
Access Control Lists for COM
1/7/2020 • 2 minutes to read • Edit Online
Windows Server XP Service Pack 2 (SP 2) and Windows Server 2003 Service Pack 1 (SP 1) introduce security
enhancements for the Distributed Component Object Model (DCOM ). One of these enhancements is more specific
access rights for use in access control lists (ACLs). The access rights are:
COM_RIGHTS_EXECUTE 1
COM_RIGHTS_EXECUTE_LOCAL 2
COM_RIGHTS_EXECUTE_REMOTE 4
COM_RIGHTS_ACTIVATE_LOCAL 8
COM_RIGHTS_ACTIVATE_REMOTE 16
To provide backward compatibility, an ACL may exist in the format used before Windows XP SP 2 and Windows
Server 2003 SP 1, which uses only the access right COM_RIGHTS_EXECUTE, or it may exist in the new format
used in Windows XP SP 2 and Windows Server 2003 SP 1, which uses COM_RIGHTS_EXECUTE together with a
combination of COM_RIGHTS_EXECUTE_LOCAL, COM_RIGHTS_EXECUTE_REMOTE,
COM_RIGHTS_ACTIVATE_LOCAL, and COM_RIGHTS_ACTIVATE_REMOTE.
NOTE
COM_RIGHTS_EXECUTE must always be present; the absence of this right generates an invalid security descriptor.
You must not mix the old format and the new format within a single ACL; either all access control entries (ACEs)
must grant only the COM_RIGHTS_EXECUTE access right, or they all must grant COM_RIGHTS_EXECUTE
together with a combination of COM_RIGHTS_EXECUTE_LOCAL, COM_RIGHTS_EXECUTE_REMOTE,
COM_RIGHTS_ACTIVATE_LOCAL, and COM_RIGHTS_ACTIVATE_REMOTE.
The following is an example of an incorrectly formatted ACL:
Revision 1
Sbz1 0
Control 0x8004
SE_DACL_PRESENT
SE_SELF_RELATIVE
Owner: S-1-5-21-1597522630-148096252-1166023319-500 (no name mapped)
Group: S-1-5-21-1597522630-148096252-1166023319-500 (no name mapped)
DACL:
AclRevision 2
Sbz1 0
AclSize 128
AceCount 4
Sbz2 0
Ace[0]
AceType 0: ACCESS_ALLOWED_ACE_TYPE
AceFlags 0
AceSize 36
AccessMask 0x1
S-1-5-21-1597522630-148096252-1166023319-500 (no name mapped)
Ace[1]
AceType 0: ACCESS_ALLOWED_ACE_TYPE
AceFlags 0
AceSize 20
AccessMask 0xb
S-1-5-18 (Well Known Group: NT AUTHORITY\SYSTEM)
Ace[2]
AceType 0: ACCESS_ALLOWED_ACE_TYPE
AceFlags 0
AceSize 20
AccessMask 0x9
S-1-5-11 (Well Known Group: NT AUTHORITY\Authenticated Users)
SACL:
(null)
Note that the first access control entry (ACE ) grants COM_RIGHTS_EXECUTE (0x1) only, while the second ACE
grants COM_RIGHTS_EXECUTE, COM_RIGHTS_EXECUTE_LOCAL, and COM_RIGHTS_ACTIVATE_LOCAL (0xb),
and the third grants COM_RIGHTS_EXECUTE and COM_RIGHTS_ACTIVATE_LOCAL (0x9).
To correct this, the first ACE should be changed to grant COM_RIGHTS_EXECUTE in combination with one of the
other four access rights, or else the second and third ACEs should be changed to grant only
COM_RIGHTS_EXECUTE.
Related topics
D
C
O
M
S
e
c
u
r
i
t
y
E
n
h
a
n
c
e
m
e
n
t
s
i
n
W
i
n
d
o
w
s
X
P
S
e
r
v
i
c
e
P
a
c
k
2
a
n
d
W
i
n
d
o
w
s
S
e
r
v
e
r
2
0
0
3
S
e
r
v
i
c
e
P
a
c
k
1
S
e
c
u
r
i
t
y
i
n
C
O
M
The COM Elevation Moniker
1/7/2020 • 8 minutes to read • Edit Online
The COM elevation moniker allows applications that are running under user account control (UAC ) to activate
COM classes with elevated privileges. For more information, see Focus on Least Privilege.
Requirements
In order to use the elevation moniker to activate a COM class, the class must be configured to run as the launching
user or the 'Activate as Activator' application identity. If the class is configured to run under any other identity, the
activation returns the error CO_E_RUNAS_VALUE_MUST_BE_AAA.
The class must also be annotated with a "friendly" display name that is multilingual user interface (MUI)
compatible. This requires the following registry entry:
HKEY_LOCAL_MACHINE\Software\Classes\CLSID
{CLSID}
LocalizedString = displayName
If this entry is missing, the activation returns the error CO_E_MISSING_DISPLAYNAME. If the MUI file is missing,
the error code from the RegLoadMUIStringW function is returned.
Optionally, to specify an application icon to be displayed by the UAC user interface, add the following registry key:
HKEY_LOCAL_MACHINE\Software\Classes\CLSID
{CLSID}
Elevation
IconReference = applicationIcon
HKEY_LOCAL_MACHINE\Software\Classes\CLSID
{CLSID}
Elevation
Enabled = 1
If this entry is missing, then the activation returns the error CO_E_ELEVATION_DISABLED.
Note that these entries must exist in the HKEY_LOCAL_MACHINE hive, not the HKEY_CURRENT_USER or
HKEY_USERS hive. This prevents users from elevating COM classes that they did not also have the privileges to
register.
Elevation:Administrator!new:{guid}
Elevation:Highest!new:{guid}
The preceding syntax uses the "new" moniker to return an instance of the COM class specified by guid. Note that
the "new" moniker internally uses the IClassFactory interface to obtain a class object and then calls
IClassFactory::CreateInstance on it.
The elevation moniker can also be used to get a class object, which implements IClassFactory. The caller then
calls CreateInstance to get an object instance. The syntax for this is as follows:
Elevation:Administrator!clsid:{guid}
Sample code
The following code example shows how to use the elevation moniker. It assumes that you have already initialized
COM on the current thread.
HRESULT CoCreateInstanceAsAdmin(HWND hwnd, REFCLSID rclsid, REFIID riid, __out void ** ppv)
{
BIND_OPTS3 bo;
WCHAR wszCLSID[50];
WCHAR wszMonikerName[300];
return FALSE;
}
The following code example shows how to call CoInitializeSecurity implicitly with the SD from the previous
code example:
The following code example shows how to call CoInitializeSecurity explicitly with the above SD:
// Absolute SD values
PSECURITY_DESCRIPTOR pAbsSD = NULL;
DWORD AbsSdSize = 0;
PACL pAbsAcl = NULL;
DWORD AbsAclSize = 0;
PACL pAbsSacl = NULL;
DWORD AbsSaclSize = 0;
PSID pAbsOwner = NULL;
DWORD AbsOwnerSize = 0;
PSID pAbsGroup = NULL;
DWORD AbsGroupSize = 0;
MakeAbsoluteSD (
pSD,
pAbsSD,
&AbsSdSize,
pAbsAcl,
&AbsAclSize,
pAbsSacl,
&AbsSaclSize,
pAbsOwner,
&AbsOwnerSize,
pAbsGroup,
&AbsGroupSize
);
if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
{
pAbsSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, AbsSdSize);
pAbsAcl = (PACL)LocalAlloc(LMEM_FIXED, AbsAclSize);
pAbsSacl = (PACL)LocalAlloc(LMEM_FIXED, AbsSaclSize);
pAbsOwner = (PSID)LocalAlloc(LMEM_FIXED, AbsOwnerSize);
pAbsGroup = (PSID)LocalAlloc(LMEM_FIXED, AbsGroupSize);
// Call CoinitilizeSecurity.
COM Permissions and Mandatory Access Labels
Windows Vista introduces the notion of mandatory access labels in security descriptors. The label dictates whether
clients can get execute access to a COM object. The label is specified in the system access control list (SACL )
portion of the security descriptor. In Windows Vista, COM supports the
SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP label. SACLs in the COM permissions are ignored on
operating systems prior to Windows Vista.
As of Windows Vista, dcomcnfg.exe does not support changing the integrity level (IL ) in COM permissions. It must
be set programmatically.
The following code example shows how to create a COM security descriptor with a label that allows
launch/activation requests from all LOW IL clients. Note that the labels are valid for Launch/Activation and Call
permissions. Thus, it is possible to write a COM server that disallows launch, activation or calls from clients with a
certain IL. For more information about integrity levels, see the section "Understanding Windows Vista's Integrity
Mechanism" in Understanding and Working in Protected Mode Internet Explorer.
HKEY_LOCAL_MACHINE\Software\Classes\AppID
{APPID}
ROTFlags
ROTREGFLAGS_ALLOWANYCLIENT 0x1
Related topics
S
e
c
u
r
i
t
y
i
n
C
O
M
U
n
d
e
r
s
t
a
n
d
i
n
g
a
n
d
W
o
r
k
i
n
g
i
n
P
r
o
t
e
c
t
e
d
M
o
d
e
I
n
t
e
r
n
e
t
E
x
p
l
o
r
e
r
Error Handling in COM
1/7/2020 • 2 minutes to read • Edit Online
Almost all COM functions and interface methods return a value of the type HRESULT. The HRESULT (for result
handle) is a way of returning success, warning, and error values. HRESULTs are really not handles to anything;
they are only values with several fields encoded in the value. As per the COM specification, a result of zero
indicates success and a nonzero result indicates failure.
At the source code level, all error values consist of three parts, separated by underscores. The first part is the
prefix that identifies the facility associated with the error, the second part is E for error, and the third part is a string
that describes the actual condition. For example, STG_E_MEDIUMFULL is returned when there is no space left
on a hard disk. The STG prefix indicates the storage facility, the E indicates that the status code represents an error,
and the MEDIUMFULL provides specific information about the error. Many of the values that you might want to
return from an interface method or function are defined in Winerror.h.
For more information about error handling, see the following sections:
Structure of COM Error Codes
Codes in FACILITY_ITF
Using Macros for Error Handling
COM Error Handling in Java and Visual Basic
Error Handling Strategies
Handling Unknown Errors
Related topics
C
O
M
E
r
r
o
r
C
o
d
e
s
Structure of COM Error Codes
1/7/2020 • 2 minutes to read • Edit Online
The following illustration shows the format of an HRESULT (or SCODE ); the numbers indicate bit positions:
The high-order bit in the HRESULT or SCODE indicates whether the return value represents success or failure. If
set to 0, SEVERITY_SUCCESS, the value indicates success. If set to 1, SEVERITY_ERROR, it indicates failure.
The R, C, N, and r bits are reserved.
The facility field indicates the system service responsible for the error. Microsoft allocates new facility codes as they
become necessary. Most SCODEs and HRESULT values set the facility field to FACILITY_ITF, indicating an
interface method error.
Common facility fields are described in the following table.
The code field is a unique number that is assigned to represent the error or warning.
By convention, HRESULT values generally have names in the following format: Facility_Severity_Reason.
Facility is either the facility name or some other distinguishing identifier; Severity is a single letter, S or E, that
indicates whether the function call succeeded (S ) or produced an error (E ); and Reason is an identifier that
describes the meaning of the code. For example, the status code STG_E_FILENOTFOUND indicates a storage-
related error has occurred; specifically, a requested file does not exist. Status codes from FACILITY_NULL omit the
Facility_ prefix.
Error codes are defined within the context of an interface implementation. Once defined, success codes cannot be
changed or new success codes added. However, new failure codes can be written. Microsoft reserves the right to
define new failure codes (but not success codes) for the interfaces described in FACILITY_ITF or in new facilities.
Related topics
E
r
r
o
r
H
a
n
d
l
i
n
g
i
n
C
O
M
W
i
n
d
o
w
s
P
r
o
t
o
c
o
l
s
:
H
R
E
S
U
L
T
Codes in FACILITY_ITF
1/7/2020 • 2 minutes to read • Edit Online
HRESULTs with facilities such as FACILITY_NULL and FACILITY_RPC have universal meaning because they are
defined at a single source: Microsoft. However, HRESULTs in FACILITY_ITF are determined by the function or
interface method from which they are returned. This means that the same 32-bit value in FACILITY_ITF returned
from two different interface methods might have different meanings.
The reason HRESULTs in FACILITY_ITF can have different meanings in different interfaces is that HRESULTs are
kept to an efficient data type size of 32 bits. Unfortunately, 32 bits is not large enough for the development of an
error code allocation system that avoids conflicting codes allocated by different programmers at different times in
different places (unlike the handling of interface identifiers and CLSIDs). As a result, the 32-bit HRESULT is
structured such that Microsoft can define several universal error codes, while allowing other programmers to
define new error codes without fear of conflict. The status code convention is as follows:
Status codes in facilities other than FACILITY_ITF can be defined only by Microsoft.
Status codes in facility FACILITY_ITF are defined solely by the developer of the interface or function that returns
the status code. To avoid conflicting error codes, whoever defines the interface is responsible for coordinating
and publishing the FACILITY_ITF status codes associated with that interface.
All the COM -defined FACILITY_ITF codes have a code value in the range of 0x0000-0x01FF. While it is legal to use
any codes in FACILITY_ITF, it is recommended that only code values in the range of 0x0200-0xFFFF be used. This
recommendation is made as a means of reducing confusion with any COM -defined errors.
It is also recommended that developers define new functions and interfaces to return error codes as defined by
COM and in facilities other than FACILITY_ITF. In particular, interfaces that have any chance of being remoted
using RPC in the future should define the FACILITY_RPC codes as legal. E_UNEXPECTED is a specific error code
that most developers will want to make universally legal.
Related topics
E
r
r
o
r
H
a
n
d
l
i
n
g
i
n
C
O
M
Using Macros for Error Handling
1/7/2020 • 2 minutes to read • Edit Online
COM defines a number of macros that make it easier to work with HRESULT values.
The error handling macros are described in the following table.
MACRO DESCRIPTION
MAKE_HRESULT Returns an HRESULT given the severity bit, facility code, and
error code that comprise the HRESULT.
[!Note]
Calling MAKE_HRESULT for S_OK verification carries a
performance penalty. You should not routinely use
MAKE_HRESULT for successful results.
MAKE_SCODE Returns an SCODE given the severity bit, facility code, and
error code that comprise the SCODE.
Related topics
E
r
r
o
r
H
a
n
d
l
i
n
g
i
n
C
O
M
COM Error Handling in Java and Visual Basic
1/7/2020 • 2 minutes to read • Edit Online
There are three interfaces and three functions that can be used in COM to provide error handling when
programming in Java or Microsoft Visual Basic. In Java and Visual Basic, the method call does not return an
HRESULT as the return value. Instead, these languages use the COM interfaces and functions to obtain HRESULT
values and to handle errors or exceptions. (Exceptions are events beyond the program's control, such as file
problems or invalid parameters.)
The three interfaces that provide support for HRESULTs are listed and described briefly in the following table.
The three functions that provide support for HRESULTs are listed and described briefly in the following table.
GetErrorInfo Obtains the error information pointer set by the previous call
to SetErrorInfo in the current logical thread.
SetErrorInfo Sets the error information object for the current thread of
execution.
Related topics
E
r
r
o
r
H
a
n
d
l
i
n
g
i
n
C
O
M
Returning Error Information
1/7/2020 • 2 minutes to read • Edit Online
Using the COM error-handling interfaces and functions, you can return error information by performing the
following the steps:
1. Implement the ISupportErrorInfo interface.
2. To create an instance of the generic error object, call the CreateErrorInfo function.
3. To set its contents, use the ICreateErrorInfo methods.
4. To associate the error object with the current logical thread, call the SetErrorInfo function.
The error handling interfaces create and manage an error object, which provides information about the error. The
error object is not the same as the object that encountered the error. It is a separate object associated with the
current thread of execution.
Retrieving Error Information
1/29/2020 • 2 minutes to read • Edit Online
Using the COM error-handling interfaces and functions, you can retrieve error information as follows:
1. Check whether the returned value represents an error that the object is prepared to handle.
2. Call QueryInterface to get a pointer to the ISupportErrorInfo interface. Then call
ISupportErrorInfo::InterfaceSupportsErrorInfo to verify that the error was raised by the object that
returned it and that the error object pertains to the current error and not to a previous call.
3. To get a pointer to the error object, call the GetErrorInfo function.
4. To retrieve information from the error object, use the IErrorInfo methods.
If the object is not prepared to handle the error but needs to propagate the error information further down the call
chain, it should simply pass the return value to its caller. Because the GetErrorInfo function clears the error
information and passes ownership of the error object to the caller, the function should be called only by the object
that handles the error.
Error Handling Strategies
1/29/2020 • 2 minutes to read • Edit Online
Because interface methods are virtual, it is not possible for a caller to know the full set of values that may be
returned from any one call. One implementation of a method may return five values; another may return eight.
The documentation lists common values that may be returned for each method; these are the values that you must
check for and handle in your code because they have special meanings. Other values may be returned, but because
they are not meaningful, you do not need to write special code to handle them. A simple check for zero or nonzero
is adequate.
HRESULT Values
The return value of COM functions and methods is an HRESULT. The values of some HRESULTs have been
changed in COM to eliminate all duplication and overlapping with the system error codes. Those that duplicate
system error codes have been changed to FACILITY_WIN32, and those that overlap remain in FACILITY_NULL.
Common HRESULT values and their values are listed in the following table.
Network Errors
If the first four digits of the error code are 8007, this indicates a system or network error. You can use the net
command to decode these types of errors. To decode the error, first convert the last four digits of the hexadecimal
error code to decimal. Then, at the command prompt, type the following, where decimal code is replaced with the
return value you want to decode:
net helpmsg <decimal_code>
The net command returns a description of the error. For example, if COM returns the error 8007054B, convert the
054B to decimal (1355). Then type the following:
net helpmsg 1355
The net command returns the error description: "The specified domain did not exist".
Related topics
E
r
r
o
r
H
a
n
d
l
i
n
g
i
n
C
O
M
Handling Unknown Errors
1/7/2020 • 2 minutes to read • Edit Online
It is legal to return a status code only from the implementation of an interface method sanctioned as legally
returnable. Failure to observe this rule invites the possibility of conflict between returned error-code values and
those sanctioned by the application. Pay particular attention to this potential problem when propagating error
codes from functions that are called internally.
Applications that call interfaces should treat any unknown returned error code (as opposed to a success code) as
synonymous with E_UNEXPECTED. This practice of handling unknown error codes is required by clients of the
COM -defined interfaces and functions. Because typical programming practice is to handle a few specific error
codes in detail and treat the rest generically, this requirement of handling unexpected or unknown error codes is
easily met.
It is important to handle all possible errors when calling an interface method. Failure to do so could cause your
application to crash, to corrupt data, or to become vulnerable to security exploits. The following code sample shows
the recommended way of handling unknown errors:
HRESULT hr;
hr = xxMethod();
switch (GetScode(hr))
{
case NOERROR:
// Method returned success.
break;
case x1:
// Handle error x1 here.
break;
case x2:
// Handle error x2 here.
break;
case E_UNEXPECTED:
default:
// Handle unexpected errors here.
break;
}
The following error check is often used with those routines that do not return anything special (other than S_OK or
some unexpected error):
if (xxMethod() == NOERROR)
{
// Handle success here.
}
else
{
// Handle failure here.
}
Related topics
E
r
r
o
r
H
a
n
d
l
i
n
g
i
n
C
O
M
COM Handlers
1/7/2020 • 2 minutes to read • Edit Online
The purpose of COM handlers is to provide some "smart" code in the client address space that can optimize calls
between a client and server. Handlers can override some interfaces while delegating others directly to the server
(through the proxy).
There are two types of COM handlers:
The OLE handler is a heavyweight DLL that provides important services for linking and embedding. It is usually
created before the server is launched and is initialized so that the server is activated when the embedded object
enters the running state.
The lightweight client-side handler can be created for any purpose, can be very small, and cannot be created
before the server.
The OLE Handler
1/7/2020 • 2 minutes to read • Edit Online
An OLE handler is a DLL containing several interacting components used for linking and embedding. To avoid the
expense of constant interprocess communication between a container and its server, the handler is loaded into the
container's process space to act on behalf of a server as a sort of surrogate process. The OLE handler manages
container requests that do not require the attention of the server application, such as requests for drawing. When a
container requests something that the object handler cannot provide, the handler communicates with the server
application using the COM out-of-process communication mechanism.
The OLE handler components include remoting pieces to manage communication between the handler and its
server, a cache for storing an object's data (along with information on how that data should be formatted and
displayed), and a controlling object that coordinates the activities of the DLL's other components. In addition, if an
object is a link, the DLL also includes a linking component, or linked object, which keeps track of the name and
location of the link source.
OLE provides a default handler that most applications use for linking and embedding. If the default does not
match the requirements of your server, you can either completely replace the default handler or use parts of the
functionality it provides where appropriate. In the latter case, the application handler is implemented as an
aggregate object composed of a new control object and the default handler. Combination application/default
handlers are also known as in-process handlers. The remoting handler is used for objects that are not assigned a
CLSID in the system registry or that have no specified handler. All that is required from a handler for these types
of objects is that they pass information across the process boundary. To create a new instance of the default
handler, call OleCreateDefaultHandler. For some special circumstances, call OleCreateEmbeddingHelper.
When you create an instance of a handler for one class, you cannot use it for another. When used for a compound
document, the OLE handler implements the container-side data structures when objects of a particular class are
accessed remotely.
OLE defined the default handler for clients of compound document local servers. The default handler implemented
a number of interfaces that the typical server did not. When OLE subsequently allowed in-process servers for
compound documents, they had to create an embedding helper that implemented these extra interfaces so that
clients could seamlessly work with them.
Framework designers that define and implement a client-side handler should consider this issue in their design
and should provide an equivalent in-process helper for the same reasons. Even if the designers currently don't
implement interfaces on the handler that the servers don't expose, they may want to define a helper now so that
they can add them in the future. Alternatively, one could implement the extra interfaces on the server object itself.
Related topics
T
h
e
L
i
g
h
t
w
e
i
g
h
t
C
l
i
e
n
t
-
S
i
d
e
H
a
n
d
l
e
r
The Lightweight Client-Side Handler
1/29/2020 • 2 minutes to read • Edit Online
Lightweight client-side handlers allow you to create general client-side handlers of any size, to help you do any
kind of standard task. As handlers, these are usable by more than one client. They differ from OLE handlers in that
they cannot be created before the server is launched, and their lifetime is tied to that of the proxy manager,
preventing a possible race condition in which the handler could otherwise be prematurely released.
The proxy manager is the system-created object that implements the IMarshal interface. If you use standard
marshaling, the system creates it for you when you call CoGetStandardMarshal (or CoGetStdMarshalEx, for
creating an aggregated marshaler for lightweight handlers) and also implements the IClientSecurity and
IMultiQI interfaces on the object. On the server side, there is a corresponding system object that also implements
IMarshal. These objects handle marshaling for you transparently.
There are two general types of these handlers that you may want to implement:
A handler that performs a service that requires no extra data from the server
A handler that uses extra data from the server
Some potential uses of the extra data in the stream supplied by the server are as follows:
Static data from server. Regardless of the particular interface being marshaled, the server writes the same data
into the stream.
Per-interface data from server. Depending on which particular interface is being marshaled, the server may
write different data into the stream.
Per-interface helpers. Per-interface COM components aggregated into the client handler and delegating to the
standard proxy. For example, to improve network performance, a COM component for IStream could do
client-side caching of data, read-ahead, write-behind, op-locking, and so forth.
Network version of an interface. The network version of the interface is different from the interface exposed by
the client and server application code. It is possible, for example, to multiplex exposed interfaces IA and IB over
the same network interface INetAB, the way the embedding server handler does. For example, one could
convert a data transfer interface into a network interface that uses pipes for efficient data transfer.
Down-level clients may not have the capability of unmarshaling interfaces that have custom handlers, for two
reasons: First, they may not understand the CLSID used in the custom marshaled packet when the server handler
is aggregated and the object wants a handler. Second, the handler code may not even run on the client side if it
requires new functionality from COM to create the aggregated standard marshaler and to do remote
QueryInterface calls.
Related topics
T
h
e
O
L
E
H
a
n
d
l
e
r
Implementing and Activating a Handler with No Extra
Server Data
1/7/2020 • 2 minutes to read • Edit Online
To create an instance of your handler, if it is one that gets no extra server data, the server must implement
IStdMarshalInfo but not IMarshal. IStdMarshalInfo has one method, GetClassForHandler, which retrieves the
CLSID of the object handler to be used in the destination process. COM calls this when it calls
CoMarshalInterface for you and activates the handler on the client side.
Next, both the server and handler implementations must call the CoGetStdMarshalEx function. This function
creates a standard marshaler on each side (called a proxy manager on the client side and a stub manager on the
server side).
The server calls CoGetStdMarshalEx, passing in the flag SMEXF_SERVER. This creates a server-side standard
marshaler (stub manager). The server-side structure is shown in the following illustration:
Server-Side Structure
The handler calls CoGetStdMarshalEx, passing in the flag SMEXF_HANDLER. This creates a client-side standard
marshaler (proxy manager) and aggregates it with the handler on the client side. The lifetime of both are managed
by the controlling identity object (implementing IUnknown) that the system implements when the handler calls
CoGetStdMarshalEx. The client-side structure is shown in the following illustration.
Client-Side Structure
As shown in the preceding illustration, the handler is actually sandwiched between the proxy manager and the
identity/controlling unknown. This gives the system control over the lifetime of the object while giving the handler
control over the exposed interfaces. The dashed line between the Identity and Proxy Manager indicates that the two
share tight integration through internal private interfaces.
When COM calls CoUnmarshalInterface for the client, it creates the handler instance, aggregating it with the
Identity. The handler will create the standard marshaler (through the call to CoGetStdMarshalEx, passing in the
controlling unknown it received when it was created). The handler does not implement IMarshal but just returns
IMarshal from the standard marshaler. Even if the handler does implement IMarshal, it will not get called during
an unmarshal.
If two threads simultaneously unmarshal the same object for the first time, it is possible for two handlers to get
created temporarily. One will subsequently be released.
Related topics
T
h
e
L
i
g
h
t
w
e
i
g
h
t
C
l
i
e
n
t
-
S
i
d
e
H
a
n
d
l
e
r
Implementing and Activating a Handler with Extra
Data Supplied by Server
1/7/2020 • 2 minutes to read • Edit Online
If the server wants to include some extra data in the packet for the handler to use, the server must implement both
the IMarshal and the IStdMarshalInfo interfaces. The server must aggregate the standard marshaler and must
delegate the first part of the marshaling to the aggregated standard marshaler, including
IMarshal::GetUnmarshalClass, and must add its own data size to the size returned by the standard marshaler's
IMarshal::GetMarshalSizeMax. The standard marshaler calls IStdMarshalInfo::GetClassForHandler to get the
CLSID of the handler to be created. After the standard marshaler has done its marshaling, the server then writes its
own extra data into the stream. The resulting structures, with extra data in the stream, are shown in the following
illustration:
Handlers that require access to some of the internal interfaces on the proxy manager have to go through the
IInternalUnknown interface. This prevents handlers from blindly delegating and exposing the aggregatee's
internal interfaces outside of the aggregate. These interfaces include IClientSecurity and IMultiQI. If the handler
wants to expose IClientSecurity or IMultiQI, it should implement them itself.
In the case of IClientSecurity, if the client tries to set the security on an interface that the handler has exposed, the
handler should set the security on the underlying network interface proxy.
In the case of IMultiQI, the handler should fill in the interfaces it knows about and then forward the call to the
proxy manager to get the rest of the interfaces filled in.
Related topics
T
h
e
L
i
g
h
t
w
e
i
g
h
t
C
l
i
e
n
t
-
S
i
d
e
H
a
n
d
l
e
r
DLL Surrogates
1/7/2020 • 2 minutes to read • Edit Online
COM makes it possible to create DLL servers that can be loaded into a surrogate EXE process. This combines the
ease of writing DLL servers with the benefits of executable implementation. Development tools like Microsoft
Visual Studio facilitate the writing of DLL servers, but a DLL server in itself has limits. Running the DLL server in
a surrogate process offers several possible benefits:
Fault isolation and the ability to service multiple clients simultaneously.
In a distributed environment, a DLL server implementation could be used to service remote clients.
It could permit clients to help protect themselves from untrusted server code while allowing them access to the
services the DLL server provides.
Running a DLL server in a surrogate provides the DLL with the surrogate's security.
COM provides a default surrogate process, or you can write a custom surrogate if you have special needs.
The following topics provide more information on DLL surrogates:
DLL Server Requirements
Using the System-Supplied Surrogate
Writing a Custom Surrogate
DLL Server Requirements
1/7/2020 • 2 minutes to read • Edit Online
Related topics
D
L
L
S
u
r
r
o
g
a
t
e
s
Surrogate Sharing
1/7/2020 • 2 minutes to read • Edit Online
DLL servers will share a surrogate if they have matching security identities and share the same AppID value.
DLL servers are loaded, by default, into their own surrogate process. To load other DLL servers into an existing
surrogate so that it supports more than one DLL server, there are two requirements:
The DLL servers must have the same AppID value.
The security context of the DLL servers must be the same.
If two DLL servers are to be launched under different security identities, they must be in different surrogates,
whether their AppIDs match.
Following is an example of administering surrogate sharing with AppIDs:
AppID
{12345678-0000-0000-0000-abcdabcdabcd}
@DllSurrogate REG_SZ
CLSID
{12345678-0000-0000-0000-000000000001}
@AppId REG_SZ {12345678-0000-0000-0000-abcdabcdabcd}
InProcServer32
@ REG_SZ c:\myapp\comp1.dll
{12345678-0000-0000-0000-000000000002}
@AppId REG_SZ {12345678-0000-0000-0000-abcdabcdabcd}
InProcServer32
@ REG_SZ c:\myapp\comp2.dll
The two CLSIDs for DLL components comp1.dll and comp2.dll have been configured to share an AppID. The
AppID key specifies that the DLL server can be loaded in a surrogate by specifying the DllSurrogate value. In this
example, the DllSurrogate value is an empty string, indicating that the default system implementation of the DLL
surrogate should be used.
Related topics
D
L
L
S
e
r
v
e
r
R
e
q
u
i
r
e
m
e
n
t
s
R
e
g
i
s
t
e
r
i
n
g
t
h
e
D
L
L
S
e
r
v
e
r
f
o
r
S
u
r
r
o
g
a
t
e
A
c
t
i
v
a
t
i
o
n
Registering the DLL Server for Surrogate Activation
1/7/2020 • 2 minutes to read • Edit Online
A DLL server will be loaded into a surrogate process under the following conditions:
There must be an AppID value specified under the CLSID key in the registry, and a corresponding AppID key.
In an activation call, the CLSCTX_LOCAL_SERVER bit is set and the CLSID key does not specify
LocalServer32, LocalServer, or LocalService. If other CLSCTX bits are set, the processing algorithmfor the in-
process, local, or remote execution flags is followed.
The CLSID key contains the InprocServer32 subkey.
The proxy/stub DLL specified in the InprocServer32 key exists.
The DllSurrogate value exists under the AppID key.
If there is a LocalServer, LocalServer32, or LocalService, indicating the existence of an EXE, the EXE server or
service will always be launched in preference to loading a DLL server into a surrogate process.
The DllSurrogate named-value must be specified for surrogate activation to occur. Activation refers to calls to any
of the following activation functions:
CoGetClassObject
CoCreateInstanceEx
CoGetInstanceFromFile
CoGetInstanceFromIStorage
IMoniker::BindToObject
To launch an instance of the system-supplied surrogate, set the value of DllSurrogate either to an empty string or
to NULL. To specify the launch of a custom surrogate, set the value to the path of the surrogate.
If both RemoteServerName and DllSurrogate are specified for the same AppID, the RemoteServerName value
is ignored and the DllSurrogate value causes an activation on the local computer. For remote surrogate activation,
specify RemoteServerName but not DllSurrogate on the client, and specify DllSurrogate on the server.
A DLL server that is designed to always run alone in its own surrogate process is best configured with an AppID
equal its CLSID. Under AppID, simply specify a DllSurrogate named-value with an empty string value.
It is best to configure a DLL server that is designed to run alone in its own surrogate process and to service
multiple clients across a network with a RunAs value specified under the AppID registry key. Whether the RunAs
specifies "Interactive User" or a specific user identity depends upon the user interface, security, and other server
requirements. When a RunAs value is specified, only one instance of the server is loaded to service all of the
clients, regardless of the identity of the client. On the other hand, do not configure the server with RunAs if the
intention is to have one instance of the DLL server running in surrogate to service each remote client identity.
Related topics
D
L
L
S
e
r
v
e
r
R
e
q
u
i
r
e
m
e
n
t
s
S
u
r
r
o
g
a
t
e
S
h
a
r
i
n
g
Using the System-Supplied Surrogate
1/7/2020 • 2 minutes to read • Edit Online
To use the system-supplied surrogate for your DLL server, register the DLL specifying an empty string or NULL
for the DllSurrogate value in the registry. When an activation request for a DLL server so designated comes to
COM, COM launches the default surrogate process and the requested DLL (by specifying the CLSID on the launch
command line internally) at the same time to avoid a separate call. (For information on running more than one
DLL server in a surrogate process, see Surrogate Sharing.)
The default implementation of the surrogate process is a mixed-threading model style pseudo-COM server. When
multiple DLL servers are loaded into a single surrogate process, this process ensures that each DLL server is
instantiated using the threading model specified in the registry for that server. All loaded free-threaded servers will
live together in the multithreaded apartment, while each apartment-threaded server will reside in a single-
threaded apartment. If a DLL server supports both threading models, COM will choose multithreading.
This surrogate process is written so that COM handles both the unloading of DLL servers and the terminating of
the surrogate process.
The system-provided surrogate will work very well for most developers, as well as being very easy to use.
However, those developers with special considerations may decide that a custom surrogate is necessary. For more
information, see Writing a Custom Surrogate.
Related topics
D
L
L
S
u
r
r
o
g
a
t
e
s
Writing a Custom Surrogate
1/7/2020 • 3 minutes to read • Edit Online
While the system-supplied surrogate will be more than adequate for most situations, there are some cases where
writing a custom surrogate could be worthwhile. Following are some examples:
A custom surrogate could provide some optimizations or semantics not present in the system surrogate.
If an in-process DLL contains code that depends on being in the same process as the client, the DLL server will
not function correctly if it is running in the system surrogate. A custom surrogate could be tailored to a specific
DLL to deal with this.
The system surrogate supports a mixed-threading model so that it can load both free and apartment model
DLLs. A custom surrogate might be tailored to load only apartment DLLs for reasons of efficiency or to accept
a command-line argument for the type of DLL it is allowed to load.
A custom surrogate could take extra command-line parameters that the system surrogate does not.
The system surrogate calls CoInitializeSecurity and tells it to use any existing security settings found under
the AppID key in the registry. A custom surrogate could use another security context.
Interfaces that aren't remotable (such as those for recent OCXs) will not work with the system surrogate. A
custom surrogate could wrap the DLL's interfaces with its own implementation and use proxy/stub DLLs with
a remotable IDL definition that would allow the interface to be remoted.
The main surrogate thread should typically perform the following setup steps:
1. Call CoInitializeEx to initialize the thread and set the threading model.
2. If you want the DLL servers that are to run in the server to be able to use the security settings in the AppID
registry key, call CoInitializeSecurity with the EOAC_APPID capability. Otherwise, legacy security settings
will be used.
3. Call CoRegisterSurrogate to register the surrogate interface to COM.
4. Call ISurrogate::LoadDllServer for the requested CLSID.
5. Put main thread in a loop to call CoFreeUnusedLibraries periodically.
6. When COM calls ISurrogate::FreeSurrogate, revoke all class factories and exit.
A surrogate process must implement the ISurrogate interface. This interface should be registered when a new
surrogate is started and after calling CoInitializeEx. As indicated in the preceding steps, the ISurrogate interface
has two methods that COM calls: LoadDllServer, to dynamically load new DLL servers into existing surrogates;
and FreeSurrogate, to free the surrogate.
The implementation of LoadDllServer, which COM calls with a load request, must first create a class factory
object that supports IUnknown, IClassFactory, and IMarshal, and then call CoRegisterClassObject to register
the object as the class factory for the requested CLSID.
The class factory registered by the surrogate process is not the actual class factory implemented by the DLL
server but is a generic class factory implemented by the surrogate process that supports IClassFactory and
IMarshal. Because it is the surrogate's class factory, rather than that of the DLL server that is being registered, the
surrogate's class factory will need to use the real class factory to create an instance of the object for the registered
CLSID. The surrogate's IClassFactory::CreateInstance should look something like the following example:
STDMETHODIMP CSurrogateFactory::CreateInstance(
IUnknown* pUnkOuter,
REFIID iid,
void** ppv)
{
void* pcf;
HRESULT hr;
The surrogate's class factory must also support IMarshal because a call to CoGetClassObject can request any
interface from the registered class factory, not just IClassFactory. Further, since the generic class factory supports
only IUnknown and IClassFactory, requests for other interfaces must be directed to the real object. Thus, there
should be a MarshalInterface method which should be similar to the following:
STDMETHODIMP CSurrogateFactory::MarshalInterface(
IStream *pStm,
REFIID riid, void *pv,
WORD dwDestContext,
void *pvDestContext,
DWORD mshlflags )
{
void * pCF = NULL;
HRESULT hr;
The surrogate that houses a DLL server must publish the DLL server's class object(s) with a call to
CoRegisterClassObject. All class factories for DLL surrogates should be registered as REGCLS_SURROGATE.
REGCLS_SINGLUSE and REGCLS_MULTIPLEUSE should not be used for DLL servers loaded into surrogates.
Following these guidelines for creating a surrogate process when it is necessary to do so should ensure proper
behavior.
Related topics
D
L
L
S
u
r
r
o
g
a
t
e
s
Monikers
1/7/2020 • 2 minutes to read • Edit Online
A moniker in COM is not only a way to identify an object—a moniker is also implemented as an object. This object
provides services allowing a component to obtain a pointer to the object identified by the moniker. This process is
referred to as binding.
Monikers are objects that implement the IMoniker interface and are generally implemented in DLLs as
component objects. There are two ways of viewing the use of monikers: as a moniker client, a component that uses
a moniker to get a pointer to another object; and as a moniker provider, a component that supplies monikers
identifying its objects to moniker clients.
OLE uses monikers to connect to and activate objects, whether they are in the same machine or across a network.
A very important use is for network connections. They are also used to identify, connect to, and run OLE
compound document link objects. In this case, the link source acts as the moniker provider and the container
holding the link object acts as the moniker client.
For more information, see the following topics:
Moniker Clients
Moniker Providers
OLE Moniker Implementations
Related topics
T
h
e
C
o
m
p
o
n
e
n
t
O
b
j
e
c
t
M
o
d
e
l
Moniker Clients
1/7/2020 • 2 minutes to read • Edit Online
Moniker clients must start by getting a moniker, and there are several ways for a moniker client to get a moniker.
For example, in OLE compound documents, when the end user creates a linked item (either using Insert Object
dialog, the clipboard, or drag-and drop), a moniker is embedded as part of the linked item. In that case, the
programmer has minimal contact with monikers. Programmatically, if you have an interface pointer to an object
that implements the IMoniker interface, you can use that to get a moniker, and there are methods on other
interfaces that are defined to return monikers.
There are different kinds of monikers, which are used to identify different kinds of objects, but to a moniker client,
all monikers look the same. A moniker client simply calls IMoniker::BindToObject on a moniker and gets an
interface pointer to the object that the moniker identifies. Whether the moniker identifies an object as large as an
entire spreadsheet or as small as a single cell within a spreadsheet, calling BindToObject will return a pointer to
that object. If the object is already running, BindToObject will find it in memory. If the object is stored passively
on disk, BindToObject will locate a server for that object, run the server, and have the server bring the object into
the running state. All the details of the binding process are hidden from the moniker client. Thus, for a moniker
client, using the moniker is very simple.
Related topics
M
o
n
i
k
e
r
P
r
o
v
i
d
e
r
s
O
L
E
M
o
n
i
k
e
r
I
m
p
l
e
m
e
n
t
a
t
i
o
n
s
Moniker Providers
1/7/2020 • 2 minutes to read • Edit Online
In general, a component should be a moniker provider when it allows access to one of its objects, while still
controlling the object's storage. If a component is going to hand out monikers that identify its objects, it must be
capable of performing the following tasks:
On request, create a moniker that identifies an object.
Enable the moniker to be bound when a client calls IMoniker::BindToObject on it.
A moniker provider must create a moniker of an appropriate moniker class to identify an object. The moniker class
refers to a specific implementation of the IMoniker interface that defines the type of moniker created. While you
can implement IMoniker to create a new moniker class, it is frequently unnecessary because OLE provides
implementations of several different moniker classes, each with its own CLSID. See OLE Moniker
Implementations for descriptions of moniker classes that OLE provides.
Related topics
M
o
n
i
k
e
r
C
l
i
e
n
t
s
O
L
E
M
o
n
i
k
e
r
I
m
p
l
e
m
e
n
t
a
t
i
o
n
s
OLE Moniker Implementations
1/7/2020 • 2 minutes to read • Edit Online
OLE provides implementations of several monikers for different situations, as described in the following topics:
File Monikers
Composite Monikers
Item Monikers
Anti-Monikers
Pointer Monikers
Class Monikers
Asynchronous Monikers
URL Monikers
The file, composite, and item monikers are the most frequently used monikers, because they can be used to make
nearly any object in any location. Anti-moniker and pointer monikers are primarily used inside OLE but have
some application in implementing custom monikers.
Related topics
M
o
n
i
k
e
r
C
l
i
e
n
t
s
M
o
n
i
k
e
r
P
r
o
v
i
d
e
r
s
File Monikers
1/7/2020 • 2 minutes to read • Edit Online
File monikers are the simplest moniker class. File monikers can be used to identify any object that is stored in its
own file. A file moniker acts as a wrapper for the path name the native file system assigns to the file. Calling
IMoniker::BindToObject for this moniker would cause this object to be activated and then would return an
interface pointer to the object. The source of the object named by the moniker must provide an implementation of
the IPersistFile interface to support binding a file moniker. File monikers can represent either a complete or a
relative path.
For example, the file moniker for a spreadsheet object stored as the file C:\Work\MySheet.xls would contain
information equivalent to that path name. The moniker would not necessarily consist of the same string, however.
The string is just its display name, a representation of the moniker's contents that is meaningful to an end user.
The display name, which is available through the IMoniker::GetDisplayName method, is used only when
displaying a moniker to an end user. This method gets the display name for any of the moniker classes. Internally,
the moniker may store the same information in a format that is more efficient for performing moniker operations
but isn't meaningful to users. Then, when this same object is bound through a call to the BindToObject method,
the object would be activated, probably by loading the file into the spreadsheet.
OLE offers moniker providers the helper function CreateFileMoniker that creates a file moniker object and
returns its pointer to the provider.
Related topics
A
n
t
i
-
M
o
n
i
k
e
r
s
C
l
a
s
s
M
o
n
i
k
e
r
s
C
o
m
p
o
s
i
t
e
M
o
n
i
k
e
r
s
I
t
e
m
M
o
n
i
k
e
r
s
P
o
i
n
t
e
r
M
o
n
i
k
e
r
s
Composite Monikers
1/7/2020 • 2 minutes to read • Edit Online
One of the most useful features of monikers is that you can concatenate or compose monikers together. A
composite moniker is a moniker that is a composition of other monikers and can determine the relation between
the parts. This lets you assemble the complete path to an object given two or more monikers that are the
equivalent of partial paths. You can compose monikers of the same class (such as two file monikers) or of different
classes (such as a file moniker and an item moniker). If you were to write your own moniker class, you could also
compose your monikers with file or item monikers. The basic advantage of a composite is that it gives you one
piece of code to implement every possible moniker that is a combination of simpler monikers. That significantly
reduces the need for specific custom moniker classes.
Because monikers of different classes can be composed with one another, monikers provide the ability to join
multiple namespaces. The file system defines a common namespace for objects stored as files because all
applications understand a file system path name. Similarly, a container object also defines a private namespace for
the objects that it contains because no container understands the names generated by another container.
Monikers allow these namespaces to be joined because file monikers and item monikers can be composed. A
moniker client can search the namespace for all objects using a single mechanism. The client simply calls
IMoniker::BindToObject on the moniker, and the moniker code handles the rest. A call to
IMoniker::GetDisplayName on a composite creates a name using the concatenation of all the individual
monikers' display names.
Furthermore, because you can write your own moniker class, moniker composition allows you to add customized
extensions to the namespace for objects.
Sometimes two monikers of specific classes can be combined in a special way. For example, a file moniker
representing an incomplete path and another file moniker representing a relative path can be combined to form a
single file moniker representing the complete path. For example, the file monikers "c:\work\art" could be
composed with the relative file moniker "..\backup\myfile.doc" to equal "c:\work\backup\myfile.doc". This is an
example of nongeneric composition.
Generic composition, on the other hand, permits the connection of any two monikers, no matter what their classes.
For example, you could compose an item moniker onto a file moniker, although not, of course, the other way
around.
Because a nongeneric composition depends on the class of the monikers involved, its details are defined by the
implementation of a particular moniker class. You can define new types of nongeneric compositions if you write a
new moniker class. By contrast, generic compositions are defined by OLE. Monikers created as a result of generic
composition are called generic composite monikers.
These three classes, file monikers, item monikers, and generic composite monikers, all work together, and they are
the most commonly used classes of monikers.
Moniker clients should call IMoniker::ComposeWith to create a composite on moniker with another. The
moniker it is called on internally decides whether it can do a generic or nongeneric composition. If the moniker
implementation determines that a generic composition is usable, OLE provides the CreateGenericComposite
function to facilitate this.
Related topics
A
n
t
i
-
M
o
n
i
k
e
r
s
C
l
a
s
s
M
o
n
i
k
e
r
s
F
i
l
e
M
o
n
i
k
e
r
s
I
t
e
m
M
o
n
i
k
e
r
s
P
o
i
n
t
e
r
M
o
n
i
k
e
r
s
Item Monikers
1/7/2020 • 2 minutes to read • Edit Online
Another OLE -implemented moniker class is the item moniker, which can be used to identify an object contained
in another object. One type of contained object is an OLE object embedded in a compound document. A
compound document could identify the embedded objects it contains by assigning each one an arbitrary name,
such as "embedobj1," "embedobj2," and so forth. Another type of contained object is a user selection in a
document, such as a range of cells in a spreadsheet or a range of characters in a text document. An object that
consists of a selection is called a pseudo -object because it isn't treated as a distinct object until a user marks the
selection. A spreadsheet might identify a cell range using a name such as "1A:7F," while a word processing
document might identify a range of characters using the name of a bookmark.
An item moniker is useful primarily when concatenated, or composed, with another moniker, one that identifies
the container. An item moniker is usually created and then composed onto (for example) a file moniker to create
the equivalent of a complete path to the object. For example, you can compose the file moniker
"c:\work\report.doc" (which identifies the container object) with the item moniker "embedobj1" (which identifies
an object within the container) to form the moniker "c:\work\report.doc\embedobj1," which uniquely identifies a
particular object within a particular file. You can also concatenate additional item monikers to identify deeply
nested objects. For example, if "embedobj1" is the name of a spreadsheet object, to identify a certain range of cells
in that spreadsheet object you could append another item moniker to create a moniker that would be the
equivalent of "c:\work\report.doc\embedobj1\1A:7F."
When combined with a file moniker, an item moniker forms a complete path. Item monikers thus extend the
notion of path names beyond the file system, defining path names to identify individual objects, not just files.
There is a significant difference between an item moniker and a file moniker. The path contained in a file moniker
is meaningful to anyone who understands the file system, while the partial path contained in an item moniker is
meaningful only to a particular container. Everyone knows what "c:\work\report.doc" refers to, but only one
particular container object knows what "1A:7F" refers to. One container cannot interpret an item moniker created
by another application; the only container that knows which object is referred to by an item moniker is the
container that assigned the item moniker to the object in the first place. For this reason, the source of the object
named by the combination of a file and item moniker must not only implement IPersistFile, to facilitate binding
the file moniker, but also IOleItemContainer to facilitate resolving the name of the item moniker into the
appropriate object, in the context of a file.
The advantage of monikers is that someone using a moniker to locate an object doesn't need to understand the
name contained within the item moniker, as long as the item moniker is part of a composite. Generally, it would
not make sense for an item moniker to exist on its own. Instead, you would compose an item moniker onto a file
moniker. You would then call IMoniker::BindToObject on the composite, which binds the individual monikers
within it, interpreting the names.
To create an item moniker object and return its pointer to the moniker provider, OLE provides the helper function
CreateItemMoniker. This function creates an item moniker object and returns its pointer to the provider.
Related topics
A
n
t
i
-
M
o
n
i
k
e
r
s
C
l
a
s
s
M
o
n
i
k
e
r
s
C
o
m
p
o
s
i
t
e
M
o
n
i
k
e
r
s
F
i
l
e
M
o
n
i
k
e
r
s
P
o
i
n
t
e
r
M
o
n
i
k
e
r
s
Anti-Monikers
1/7/2020 • 2 minutes to read • Edit Online
OLE provides an implementation of a special type of moniker called an anti-moniker. You use this moniker in the
creation of new moniker classes. You use it as the inverse of the moniker that it is composed onto, effectively
canceling that moniker, in much the same way that the ".." operator moves up a directory level in a file system
command.
It is necessary to have an anti-moniker available, because once a composite moniker is created, it is not possible
to delete parts of the moniker if, for example, an object moves. Instead, you use an anti-moniker to remove one or
more entries from a composite moniker.
Anti-monikers are a moniker class explicitly intended for use as an inverse. COM defines the named
CreateAntiMoniker function, which returns an anti-moniker. You generally use this function to implement the
IMoniker::Inverse method.
An anti-moniker is only an inverse for those types of monikers that are implemented to treat anti-monikers as an
inverse. For example, if you want to remove the last piece of a composite moniker, you should not create an anti-
moniker and compose it to the end of the composite. You cannot be sure that the last piece of the composite
considers an anti-moniker to be its inverse. Instead, you should call IMoniker::Enum on the composite moniker,
specifying FALSE as the first parameter. This creates an enumerator that returns the component monikers in
reverse order. Use the enumerator to retrieve the last piece of the composite, and call Inverse on that moniker.
The moniker returned by Inverse is what you need to remove the last piece of the composite.
Related topics
C
l
a
s
s
M
o
n
i
k
e
r
s
C
o
m
p
o
s
i
t
e
M
o
n
i
k
e
r
s
F
i
l
e
M
o
n
i
k
e
r
s
I
t
e
m
M
o
n
i
k
e
r
s
P
o
i
n
t
e
r
M
o
n
i
k
e
r
s
Pointer Monikers
1/29/2020 • 2 minutes to read • Edit Online
A pointer moniker identifies an object that can exist only in the active or running state. This differs from other
classes of monikers, which identify objects that can exist in either the passive or the active state.
Suppose, for example, an application has an object that has no persistent representation. Normally, if a client of
your application needs access to that object, you could simply pass the client a pointer to the object. However,
suppose your client is expecting a moniker. The object cannot be identified with a file moniker, because it isn't
stored in a file, nor with an item moniker, because it isn't contained in another object.
Instead, your application can create a pointer moniker, which is a moniker that simply contains a pointer internally,
and pass that to the client. The client can treat this moniker like any other. However, when the client calls
IMoniker::BindToObject on the pointer moniker, the moniker code does not check the running object table
(ROT) or load anything from storage. Instead, the moniker code simply calls QueryInterface on the pointer
stored inside the moniker.
Pointer monikers allow objects that exist only in the active or running state to participate in moniker operations
and be used by moniker clients. One important difference between pointer monikers and other classes of
monikers is that pointer monikers cannot be saved to persistent storage. If you do, calling the IMoniker::Save
method returns an error. This means that pointer monikers are useful only in specialized situations. You can use
the CreatePointerMoniker function if you need to use a pointer moniker.
Related topics
A
n
t
i
-
M
o
n
i
k
e
r
s
C
l
a
s
s
M
o
n
i
k
e
r
s
C
o
m
p
o
s
i
t
e
M
o
n
i
k
e
r
s
F
i
l
e
M
o
n
i
k
e
r
s
I
t
e
m
M
o
n
i
k
e
r
s
Class Monikers
1/7/2020 • 2 minutes to read • Edit Online
Although classes are typically identified directly with CLSIDs to functions such as CoCreateInstance or
CoGetClassObject, classes may also now be identified with a moniker called a class moniker. Class monikers
bind to the class object of the class for which they are created.
The ability to identify classes with a moniker supports useful operations that are otherwise unwieldy. For
example, file monikers traditionally supported rich binding only to the class associated with the class of file they
referred to; a moniker to an Excel file would bind to an instance of an Excel object, and a moniker to a GIF image
would bind to an instance of the currently registered GIF handler. A class moniker allows you to indicate the class
you want to use to manipulate a file through composition with a file moniker. A class moniker for a 3D charting
class composed with a moniker to an Excel file yields a moniker that binds to an instance of the 3D charting
object and initializes the object with the contents of the Excel file.
Class monikers are therefore most useful in composition with other types of monikers, such as file monikers or
item monikers.
Class monikers may also be composed to the right of monikers supporting binding to the IClassActivator
interface. When composed in this manner, IClassActivator simply gives access to the class object and instances
of the class through IClassActivator::GetClassObject. Class monikers may be identified through
IMoniker::IsSystemMoniker, which returns MKSYS_CLASSMONIKER in pdwMksys.
Programmers typically create class monikers using the CreateClassMoniker function or through
MkParseDisplayName. (See IMoniker::ParseDisplayName for details.)
Related topics
A
n
t
i
-
M
o
n
i
k
e
r
s
C
o
m
p
o
s
i
t
e
M
o
n
i
k
e
r
s
F
i
l
e
M
o
n
i
k
e
r
s
I
t
e
m
M
o
n
i
k
e
r
s
P
o
i
n
t
e
r
M
o
n
i
k
e
r
s
Asynchronous Monikers
1/7/2020 • 2 minutes to read • Edit Online
The OLE moniker architecture provides a consistent, extensible programming model for working with Internet
objects, providing methods for parsing names, representing Universal Resource Locators (URLs) as printable
names, and locating and binding to the objects represented by URL strings. (Also see URL Monikers.) Standard
OLE monikers (notably, item, file, and pointer monikers), however, are inappropriate for the Internet because they
are synchronous, returning a pointer to an object or its storage only at such time as all data is available.
Depending on the amount of data to be downloaded, binding synchronously can tie up the client's user interface
for prolonged periods.
The Internet requires new approaches to application design. Applications should be able to perform all expensive
network operations asynchronously to avoid stalling the user interface. An application should be able to trigger an
operation and receive notification on full or partial completion. At that point, the application should have the
choice either of proceeding with the next step of the operation or providing additional information as needed. As a
download proceeds, an application should also be able to provide users with progress information and the
opportunity to cancel the operation at any time.
Asynchronous monikers provide these capabilities, as well as various levels of asynchronous binding behavior,
while providing backward compatibility for applications that are either unaware of or do not require asynchronous
behavior. Another OLE technology, asynchronous storage, works with asynchronous monikers to provide
asynchronous downloading of an Internet object's persistent state. The asynchronous moniker triggers the bind
operation and sets up the necessary components, including storage and stream objects, byte-array objects, and
notification sinks. Once the components are connected, the moniker gets out of the way and the rest of the bind is
executed mainly between the components implementing the asynchronous storage components and the object.
For more information, see the following topics:
Asynchronous and Synchronous Monikers
Asynchronous and Synchronous Binding
Asynchronous and Synchronous Storage
Data-Pull Model and Data-Push Model
Related topics
U
R
L
M
o
n
i
k
e
r
s
Asynchronous and Synchronous Monikers
1/7/2020 • 2 minutes to read • Edit Online
A client of a standard, synchronous OLE moniker typically creates and holds a reference to the moniker, as well as
the bind-context to be used during binding. The components involved in using traditional monikers are shown in
the following diagram.
Clients typically create standard monikers by calling functions such as CreateFileMoniker, CreateItemMoniker,
or CreatePointerMoniker or, because they are can be saved to persistent storage, through OleSaveToStream
and OleLoadFromStream. Monikers may also be obtained from a container object by calling the
IBindHost::CreateMoniker method. Clients create bind contexts by calling the CreateBindCtx function and then
pass the bind context to the moniker with calls to IMoniker::BindToStorage or IMoniker::BindToObject.
As shown in the following diagram, a client of an asynchronous moniker also creates and holds a reference to the
moniker and bind context to be used during binding.
To get asynchronous behavior, the client implements the IBindStatusCallback interface on a bind-status-callback
object and calls either the RegisterBindStatusCallback function or the CreateAsyncBindCtx function to register
this interface with the bind context. The moniker passes a pointer to its IBinding interface in a call to the
IBindStatusCallback::OnStartBinding method. The client tells the asynchronous moniker how it wants to bind
on return from the moniker's call to IBindStatusCallback::GetBindInfo method.
Related topics
A
s
y
n
c
h
r
o
n
o
u
s
M
o
n
i
k
e
r
s
Asynchronous and Synchronous Binding
1/7/2020 • 2 minutes to read • Edit Online
The client may check to see whether the moniker is asynchronous by calling the IsAsyncMoniker function. If the
client returns the BINDF_ASYNCHRONOUS flag, rather than returning an object pointer or a storage pointer from
subsequent calls to IMoniker::BindToStorage or IMoniker::BindToObject, the moniker returns
MK_S_ASYNCHRONOUS in place of the object pointer and NULL in place of the storage pointer. In response, the
client should wait to receive the requested object or storage during implementation of
IBindStatusCallback::OnDataAvailable and IBindStatusCallBack::OnObjectAvailable.
The callback object also receives progress notification through IBindStatusCallback::OnProgress, data
availability notification through OnDataAvailable, and various other notifications from the moniker about the
status of the binding operation.
If the client does not return the BINDF_ASYNCHRONOUS flag from the moniker's call to
IBindStatusCallback::GetBindInfo, the bind operation will proceed synchronously and the desired object or
storage will be returned from subsequent calls to BindToObject or BindToStorage. Similarly, if the client desires
synchronous operation and does not wish to receive any progress notifications or callbacks, it can request an
asynchronous moniker to behave synchronously by not implementing IBindStatusCallback. In such cases, the
asynchronous moniker will behave like a standard synchronous moniker.
Related topics
A
s
y
n
c
h
r
o
n
o
u
s
M
o
n
i
k
e
r
s
Asynchronous and Synchronous Storage
1/7/2020 • 2 minutes to read • Edit Online
Related topics
A
s
y
n
c
h
r
o
n
o
u
s
M
o
n
i
k
e
r
s
Data-Pull Model and Data-Push Model
1/7/2020 • 2 minutes to read • Edit Online
A client of an asynchronous moniker can choose between a data-pull and data-push model for driving an
asynchronous IMoniker::BindToStorage operation and receiving asynchronous notifications. In the data-pull
model, the client drives the bind operation and the moniker provides data to the client only as it is read. In other
words, after the first call to IBindStatusCallback::OnDataAvailable, the moniker does not provide any data to
the client unless the client has consumed all of the data that is already available.
Because data is downloaded only as it is requested, clients that choose the data-pull model must make sure to read
this data in a timely manner. In the case of Internet downloads with URL monikers, the bind operation may fail if a
client waits too long before requesting more data.
In the data-push model, the moniker drives the asynchronous bind operation and continuously notifies the client
whenever new data is available. The client may choose whether to read the data at any point during the bind
operation, but the moniker will drive the bind operation to completion regardless.
Also, you need to remember to follow the COM rules for memory allocation when using asynchronous monikers,
specifically the following:
Whenever a COM interface or function call returns a buffer (string or other) to its client, the client is responsible
for freeing the memory by calling CoTaskMemFree.
Whenever a COM interface or function requires a buffer from its client, the client must allocate that buffer using
CoTaskMemAlloc and the callee must free it.
Be sure to follow these rules when allocating strings or buffers that are passed to asynchronous monikers, and
remember to free memory returned by asynchronous monikers. See Managing Memory Allocation and related
topics for complete details.
Related topics
A
s
y
n
c
h
r
o
n
o
u
s
M
o
n
i
k
e
r
s
URL Monikers
1/7/2020 • 2 minutes to read • Edit Online
The OLE moniker architecture provides a convenient programming model for working with URLs. The moniker
architecture supports extensible and complete name parsing through the MkParseDisplayName function and
the IParseDisplayName and IMoniker interfaces, as well as printable names through the
IMoniker::GetDisplayName method. The IMoniker interface is the way you actually use URLs you encounter,
and building components that fit into the moniker architecture is the way to actually extend URL namespaces in
practice.
A system-provided moniker class, the URL moniker, provides a framework for building and using certain URLs.
Because URLs frequently see resources across high-latency networks, the URL moniker supports asynchronous
as well as synchronous binding. The URL moniker does not currently support asynchronous storage.
The following diagram shows the components involved in using URL monikers. All these components should be
familiar. (See Asynchronous Monikers.)
Like all moniker clients, a user of URL Monikers typically creates and holds a reference to the moniker as well as
to the bind context to be used during binding (IMoniker::BindToStorage or IMoniker::BindToObject). To
support asynchronous binding, the client can implement a bind-status-callback object, which implements the
IBindStatusCallback interface, and register it with the bind context using the RegisterBindStatusCallback
function. This object will receive the transport's IBinding interface during calls to
IBindStatusCallback::OnStartBinding.
The URL Moniker identifies the protocol being used by parsing the URL prefix and then retrieves the IBinding
interface from the transport layer. The client uses IBinding to support pausing, cancellation, and prioritization of
the binding operation. The callback object also receives progress notification through
IBindStatusCallback::OnProgress, data availability notification through
IBindStatusCallback::OnDataAvailable, and various, other transport-layer notifications about the status of the
binding. The URL moniker or specific transport layers may also request extended information from the client
through IBindStatusCallback::QueryInterface, allowing the client to provide protocol-specific information that
will affect the bind operation.
For more information, see the following topics:
Callback Synchronization
Media-Type Negotiation
URL Moniker Functions
Related topics
A
s
y
n
c
h
r
o
n
o
u
s
M
o
n
i
k
e
r
s
A
b
o
u
t
U
R
L
M
o
n
i
k
e
r
s
Callback Synchronization
1/7/2020 • 2 minutes to read • Edit Online
The asynchronous WinInet API (used for the most common protocols) leaves the synchronization of the callback
mechanism and the calling application as an exercise for the client. This is intentional because it allows the greatest
degree of flexibility. The default protocols and the URL moniker implementation perform this synchronization and
guarantee that single-threaded and apartment-threaded applications never have to deal with free-thread-style
contention. That is, the client's IEnumFORMATETC and IBindStatusCallback interfaces are called only on their
proper threads. This feature is transparent to the user of the URL mMoniker as long each thread that calls
IMoniker::BindToStorage and IMoniker::BindToObject has a message queue.
The asynchronous moniker specification requires more precise control over the prioritization and management of
downloads than is allowed for by either WinSock or WinInet. Accordingly, a URL moniker manages all the
downloads for any given caller's thread, using (as part of its synchronization) a priority scheme based on the
IBinding specification.
Related topics
U
R
L
M
o
n
i
k
e
r
s
Media-Type Negotiation
1/7/2020 • 2 minutes to read • Edit Online
Many application-layer Internet protocols are based on the exchange of messages in a simple, flexible format called
Multipurpose Internet Mail Extensions (MIME ). Although MIME originated as a standard for exchanging electronic
mail messages, it is used today by a wide variety of applications to specify mutually understood data formats as
MIME, or media, types. The process is called media -type negotiation.
Media types are simple strings that denote a type and subtype (such as "text/plain" or "text/HTML"). They are used
to label data or qualify a request. A Web browser, for example, as part of an HTTP request-for-data or request-for-
info, specifies that it is requesting "image/gif" or "image/jpeg" Media Types, to which a web server responds by
returning the appropriate media type and, if the call was a request-for-data, the data itself in the requested format.
Media-type negotiation is often similar to how existing desktop applications negotiate with the system clipboard to
determine which data format to paste when a user chooses Edit/Paste or queries for formats when receiving an
IDataObject pointer during a drag-and-drop operation. The subtle difference in HTTP media-type negotiation is
that the client does not know ahead of time which formats the server has available. Therefore, the client specifies
up-front the media types it supports, in order of greatest fidelity, and the server responds with the best available
format.
URL monikers support media-type negotiation as a way for Internet clients and servers to agree upon formats to
be used when downloading data in BindToStorage operations. To support media-type negotiation, a client
implements the IEnumFORMATETC interface and calls the RegisterFormatEnumerator function to register it
with the bind context. The format enumerator lists the formats the client can accept. A URL moniker translates
these formats into media types when binding to HTTP URLs.
The possible media types requested by the client are represented to URL monikers through FORMATETC
structures available from the IEnumFORMATETC enumerator registered by the caller on the bind context: Each
FORMATETC specifies a clipboard format identifying the media type. For example, the following code fragment
specifies that the media type is PostScript.
FORMATETC fmtetc;
fmtetc.cfFormat = RegisterClipboardFormat(CF_MIME_POSTSCRIPT);
. . .
A client can set the clipboard format to the special media type CF_NULL to indicate that the default media type of
the resource pointed to by the URL should be retrieved. This format is usually the last one in which the client is
interested. When no enumerator is registered with the bind context, a URL moniker works as if an enumerator
containing a single FORMATETC with cfFormat=CF_NULL is available, automatically downloading the default
media-type.
Whatever media type is to be used, the client is notified of the choice by means of the pformatetc argument on its
IBindStatusCallback::OnDataAvailable method. The callback occurs within the context of the client's call to
BindToStorage.
NOTE
If received content is of an unrecognized media-type, the client automatically calls RegisterMediaTypes to register the new
type.
Related topics
U
R
L
M
o
n
i
k
e
r
s
URL Moniker Functions
1/7/2020 • 2 minutes to read • Edit Online
URL moniker functions insulate developers from the complexities of creating, managing, and using URL monikers.
These functions are as follows:
CreateURLMoniker
IsValidURL
RegisterMediaTypes
CreateFormatEnumerator
RegisterFormatEnumerator
RevokeFormatEnumerator
RegisterMediaTypeClass
FindMediaTypeClass
GetClassFileOrMime
UrlMkSetSessionOption
Your familiarity with these functions can be as follows:
Be familiar with CreateURLMoniker and IsValidURL if you will be using URL monikers in stand-alone
applications. If you are authoring an ActiveX control, you should use IBindHost::CreateMoniker instead of
CreateURLMoniker.
Be familiar with RegisterMediaTypes, CreateFormatEnumerator, RegisterFormatEnumerator, and
RevokeFormatEnumerator if you will be performing any MIME negotiation with URL monikers.
Be familiar with RegisterMediaTypeClass, FindMediaTypeClass, GetClassFileOrMime, and
UrlMkSetSessionOption only if you have significant experience both with URL monikers and with COM.
Related topics
U
R
L
M
o
n
i
k
e
r
s
Events in COM and Connectable Objects
1/29/2020 • 2 minutes to read • Edit Online
When a program detects something that has happened, it can notify its clients. For example, if a stock ticker
program detects a change in the price of a stock, it can notify all clients of the change. This notification process is
referred to as firing an event.
With COM, server objects can use COM events to fire events without any information about what objects will be
notified. Objects can also use connectable objects to maintain detailed information about clients who have
requested notifications.
COM connectable objects provide outgoing interfaces to their clients in addition to their incoming interfaces. As a
result, objects and their clients can engage in bidirectional communication. Incoming interfaces are implemented
on an object and receive calls from external clients of an object, while outgoing interfaces are implemented on the
client's sink and receive calls from the object. The object defines an interface it would like to use, and the client
implements it.
An object defines its incoming interfaces and provides implementations of these interfaces. Incoming interfaces
are available to clients through the object's IUnknown::QueryInterface method. Clients call the methods of an
incoming interface on the object, and the object performs desired actions on behalf of the client.
Outgoing interfaces are also defined by an object, but the client provides the implementations of the outgoing
interfaces on a sink object that the client creates. The object then calls methods of the outgoing interface on the
sink object to notify the client of changes in the object, to trigger events in the client, to request something from
the client, or, in fact, for any purpose the object creator comes up with.
An example of an outgoing interface is an IButtonSink interface defined by a push button control to notify its
clients of its events. For example, the button object calls IButtonSink::OnClick on the client's sink object when the
user clicks the button on the screen. The button control defines the outgoing interface. For a client of the button to
handle the event, the client must implement that outgoing interface on a sink object and then connect that sink to
the button control. Then, when events occur in the button, the button will call the sink, at which time the client can
execute whatever action it wishes to assign to that button click.
Connectable objects provide a general mechanism for object-to-client communication. Any object that wishes to
expose events or notifications of any kind can use this technology. In addition to the general connectable object
technology, COM provides many special purpose sink and site interfaces used by objects to notify clients of
specific events of interest to the client. For example, IAdviseSink may be used by objects to notify clients of data
and view changes in the object.
For more information, see the following topics:
Architecture of Connectable Objects
Connectable Object Interfaces
Architecture of Connectable Objects
1/29/2020 • 3 minutes to read • Edit Online
The connectable object is only one piece of the overall architecture of connectable objects. This technology
includes the following elements:
Connectable object. Implements the IConnectionPointContainer interface; creates at least one connection
point object; defines an outgoing interface for the client.
Client. Queries the object for IConnectionPointContainer to determine whether the object is connectable;
creates a sink object to implement the outgoing interface defined by the connectable object.
Sink object. Implements the outgoing interface; used to establish a connection to the connectable object.
Connection point object. Implements the IConnectionPoint interface and manages connection with the
client's sink.
The relationships between client, connectable object, a connection point, and a sink are illustrated in the following
diagram:
Before the connection point object calls methods in the sink interface in step 3 in the preceding diagram, it must
QueryInterface for the specific interface required, even if the pointer was already passed in the step 2 call to the
Advise method.
Two enumerator objects are also involved in this architecture though not shown in the illustration. One is created
by a method in IConnectionPointContainer to enumerate the connection points within the connectable object.
The other is created by a method in IConnectionPoint to enumerate the connections currently established to that
connection point. One connection point can support multiple connected sink interfaces, and it should iterate
through the list of connections each time it makes a method call on that interface. This process is known as
multicasting.
When working with connectable objects, it is important to understand that the connectable object, each connection
point, each sink, and all enumerators are separate objects with separate IUnknown implementations, separate
reference counts, and separate lifetimes. A client using these objects is always responsible for releasing all
reference counts it owns.
NOTE
A connectable object can support more than one client and can support multiple sinks within a client. Likewise, a sink can be
connected to more than one connectable object.
The steps for establishing a connection between a client and a connectable object are as follows:
1. The client queries for IConnectionPointContainer on the object to determine whether the object is
connectable. If this call is successful, the client holds a pointer to the IConnectionPointContainer interface on
the connectable object and the connectable object reference counter has been incremented. Otherwise, the
object is not connectable and does not support outgoing interfaces.
2. If the object is connectable, the client next tries to obtain a pointer to the IConnectionPoint interface on a
connection point within the connectable object. There are two methods for obtaining this pointer, both in
IConnectionPointContainer::FindConnectionPoint and in
IConnectionPointContainer::EnumConnectionPoints. There are a few additional steps needed if
EnumConnectionPoints is used. (See Using IConnectionPointContainer for more information.) If successful,
the connectable object and the client both support the same outgoing interface. The connectable object defines
it and calls it, and the client implements it. The client can then communicate through the connection point
within the connectable object.
3. The client then calls Advise on the connection point to establish a connection between its sink interface and the
object's connection point. After this call, the object's connection point holds a pointer to the outgoing interface
on the sink.
4. The code inside Advise calls QueryInterface on the interface pointer that is passed in, asking for the specific
interface identifier to which it connects.
5. The object calls methods on the sink's interface as needed, using the pointer held by its connection point.
6. The client calls Unadvise to terminate the connection. Then the client calls IConnectionPoint::Release to free
its hold on the connection point and, therefore, the main connectable object also. The client must also call
IConnectionPointContainer::Release to free its hold on the main connectable object.
Related topics
C
o
n
n
e
c
t
a
b
l
e
O
b
j
e
c
t
I
n
t
e
r
f
a
c
e
s
Connectable Object Interfaces
1/7/2020 • 2 minutes to read • Edit Online
Related topics
A
r
c
h
i
t
e
c
t
u
r
e
o
f
C
o
n
n
e
c
t
a
b
l
e
O
b
j
e
c
t
s
Using IConnectionPointContainer
1/29/2020 • 2 minutes to read • Edit Online
Related topics
C
o
n
n
e
c
t
a
b
l
e
O
b
j
e
c
t
I
n
t
e
r
f
a
c
e
s
Using IConnectionPoint
1/7/2020 • 2 minutes to read • Edit Online
When the client has a pointer to a connection point, it can perform the following operations as expressed through
IConnectionPoint:
First, IConnectionPoint::GetConnectionInterface retrieves the outgoing interface IID supported by the
connection point. When used in conjunction with IEnumConnectionPoints, this method allows the client to
examine the IIDs of all outgoing interfaces supported on the connectable object.
Second, a client can navigate from the connection point back to the connectable object's
IConnectionPointContainer interface through the IConnectionPoint::GetConnectionPointContainer
method.
Third, the most interesting methods for the client are IConnectionPoint::Advise and
IConnectionPoint::Unadvise. When a client wishes to connect its own sink object to the connectable object,
the client passes the sink's IUnknown pointer (or any other interface pointer on the same object) to Advise.
The connection point queries the sink for the specific outgoing interface that is expected. If that interface is
available on the sink, the connection point then stores the interface pointer. From this point until Unadvise is
called, the connectable object will make calls to the sink through this interface when events occur. To disconnect
the sink from the connection point, the client passes a key returned from Advise to the Unadvise method.
Unadvise must call Release on the sink interface.
Finally, a client can ask a connection point to enumerate all the connections to it that exist through
IConnectionPoint::EnumConnections. This method creates an enumerator object (with a separate reference
count) returning an IEnumConnections pointer to it. The client must call Release when the enumerator is no
longer needed. Additionally, the enumerator returns a series of CONNECTDATA structures, one for each
connection. Each structure describes one connection using the IUnknown pointer of the sink as well as the
connection key originally returned from Advise. When done with these sink interface pointers, the client must
call Release on each pointer returned in a CONNECTDATA structure.
Related topics
C
o
n
n
e
c
t
a
b
l
e
O
b
j
e
c
t
I
n
t
e
r
f
a
c
e
s
Using IProvideClassInfo
1/7/2020 • 2 minutes to read • Edit Online
A connectable object can offer the IProvideClassInfo and IProvideClassInfo2 interfaces so that its clients can
easily examine its type information. This capability is important when dealing with outgoing interfaces, which, by
definition, are defined by an object but implemented by a client on its own sink object. In some cases, an outgoing
interface is known at compile time to both the connectable object and the sink object; such is the case with
IPropertyNotifySink.
In other cases, however, only the connectable object knows its outgoing interface definitions at compile time. In
these cases, the client must obtain the type information for the outgoing interface so that it can dynamically
provide a sink supporting the right entry points, as follows:
1. The client enumerates the connection points and then, to obtain the IIDs of outgoing interfaces supported by
the connectable object, calls IConnectionPoint::GetConnectionInterface for each connection point.
2. The client queries the connectable object for one of the IProvideClassInfo interfaces.
3. The client calls methods in the IProvideClassInfo interfaces to get the type information for the outgoing
interface.
4. The client creates a sink object supporting the outgoing interface.
5. The process continues, and the client calls IConnectionPoint::Advise to connect its sink to the connection
point.
In the type information, the attribute source marks an interface or dispinterface listed under a coclass as an
outgoing interface. Those listed without this attribute are considered incoming interfaces.
Related topics
C
o
n
n
e
c
t
a
b
l
e
O
b
j
e
c
t
I
n
t
e
r
f
a
c
e
s
P
r
o
v
i
d
i
n
g
C
l
a
s
s
I
n
f
o
r
m
a
t
i
o
n
Component Categories Manager Implementation
1/7/2020 • 2 minutes to read • Edit Online
As the number of available components grows, it becomes increasingly difficult to manage these components. In
terms of the interfaces they expose as well as the tasks they perform, many components offer similar functionality.
It is often necessary to enumerate the components that can be used in a certain context. Examples of this are the
Insert Object dialog box used in OLE compound documents and the Insert Control dialog box used in OLE
controls. These dialog boxes list all components that fulfill (or claim to fulfill) the interface contracts for compound
documents or controls. These existing categories (OLE document, OLE control) do not imply an exact interface
signature. OLE documents have to expose a certain set of core interfaces (for example, IOleObject or
IPersistStorage) but can also expose additional interfaces such as IOleLink.
In the past, components have been tagged by adding a human-readable name ("Insertable", "Control", and so on)
as a subkey to the HKEY_CLASSES_ROOT\CLSID\{...} registry key corresponding to the component. This works
well for a central definition of categories but risks name collisions when many independent parties define new
categories. As in other areas of COM, the solution to providing an extensible namespace lies in the use of globally
unique identifiers (GUIDs). Instead of using a human-readable name, a unique number (CATID ) is assigned to each
category.
Another limitation with the existing categorization is that it is limited to expressing the capabilities of the
component itself. Many components require certain capabilities from the containers. When such a component is
inserted into a container, the insertion can fail or behave unexpectedly, even though the component fulfills the
contracts implied by one of its categories. To enumerate the components that can be used successfully in certain
situations, the capabilities of both the component and the container must be considered.
Because of these considerations, the following changes were made to the existing categorization:
Categories are indicated by using CATIDs that are globally unique identifiers.
Under the Components subkey of the HKEY_CLASSES_ROOT\CLSID registry key, two separate subkeys,
"Implemented Categories" and "Required Categories", were developed. These subkeys contain the lists of
CATIDs that are provided by the component or that the container of the component must provide.
To ease managing the component categories, categories are listed in a central place in the registry:
HKEY_CLASSES_ROOT\Component Categories. This key lists the installed categories both with their CATID
and with localized, human-readable names.
For more information, see the following topics:
Categorizing by Component Capabilities
Categorizing by Container Capabilities
The Component Categories Manager
Default Classes and Associations
Defining Component Categories
Associating Icons with a Category
Categorizing by Component Capabilities
1/7/2020 • 2 minutes to read • Edit Online
Component categories can be used to display a subset of all of the installed components. Each component
category is identified by a GUID, referred to as a Category ID (CATID ). Each CATID has a list of locale-tagged,
human-readable names associated with it. A listing of the CATIDs and the human-readable names is stored in a
well-known location in the registry.
For example, all components that implement the functionality for OLE document embedding can be classified
within a component category. In the past, these objects would have been identified by the "Insertable" key in the
registry. To use component categories instead, the following information would be added to the registry:
HKEY_CLASSES_ROOT\Component Categories\{40FC6ED3-2438-11cf-A3DB-080036F12502}
(Default) = ""
409 = "Embeddable Objects"
Each class that implements the functionality corresponding to a component category lists the category ID for that
category within the CLSID key in the registry. Because a single component can support a wide range of
functionality, components can belong to multiple component categories. For example, a particular OLE control
might support all of the functionality required to participate as OLE document embedding, Microsoft Visual Basic
data binding, and Internet functionality. Such a control would have the following information stored in its CLSID
key in the registry:
With this information, a container can enumerate the controls installed on a system and display only those
controls that support the functionality required by the container. The use of component categories provides a way
to categorize components by the implemented functionality of the component.
Related topics
A
s
s
o
c
i
a
t
i
n
g
I
c
o
n
s
w
i
t
h
a
C
a
t
e
g
o
r
y
C
a
t
e
g
o
r
i
z
i
n
g
b
y
C
o
n
t
a
i
n
e
r
C
a
p
a
b
i
l
i
t
i
e
s
D
e
f
a
u
l
t
C
l
a
s
s
e
s
a
n
d
A
s
s
o
c
i
a
t
i
o
n
s
D
e
f
i
n
i
n
g
C
o
m
p
o
n
e
n
t
C
a
t
e
g
o
r
i
e
s
T
h
e
C
o
m
p
o
n
e
n
t
C
a
t
e
g
o
r
i
e
s
M
a
n
a
g
e
r
Categorizing by Container Capabilities
1/7/2020 • 2 minutes to read • Edit Online
Components often require certain functionality from the container and will not work with a container that does
not provide the support. The user interface should filter out components that require functionality the container
does not support. To accomplish this, components can be categorized by the required container functionality.
An example of components that require functionality from the container and do not work in containers that do not
support that functionality are simple frame OLE controls. Categorizing by container capabilities is accomplished
by an additional registry key within the component's CLSID key:
As shown in this example, a component can belong to component categories that indicate supported functionality
as well as to component categories that indicate required functionality.
In the following example, the button control is a generic OLE control that supports no additional functionality. It
will work in any OLE control container.
HKEY_CLASSES_ROOT\CLSID\{...CLSID_Button...}\Implemented Categories
HKEY_CLASSES_ROOT\CLSID\{...CLSID_Button...}\Implemented Categories\{...CATID_Control...}
Compare the preceding example with the next example in which the MyDBControl can use Visual Basic data
binding if the container supports it. However, it has been defined so that it will work in containers that do not
support Visual Basic data binding (perhaps by a different database API):
HKEY_CLASSES_ROOT\CLSID\{...CLSID_MyDBControl...}\Implemented Categories
HKEY_CLASSES_ROOT\CLSID\{...CLSID_MyDBControl...}\Implemented Categories\{...CATID_Control...}
HKEY_CLASSES_ROOT\CLSID\{...CLSID_MyDBControl...}\Implemented Categories\{...CATID_VBDatabound...}
The GroupBox control is a simple frame control. It relies on the container implementing the ISimpleFrameSite
interface and will work correctly only in such containers:
HKEY_CLASSES_ROOT\CLSID\{...CLSID_GroupBox...}\Implemented Categories
HKEY_CLASSES_ROOT\CLSID\{...CLSID_GroupBox...}\Implemented Categories\{...CATID_Control...}
HKEY_CLASSES_ROOT\CLSID\{...CLSID_GroupBox...}\Implemented Categories\{...CATID_SimpleFrame...}
HKEY_CLASSES_ROOT\CLSID\{...CLSID_GroupBox...}\Required Categories\{...CATID_SimpleFrame...}
A container that supports Visual Basic data bound controls but does not support simple frame controls would
specify CATID_Control and CATID_VBDatabound to the insert control user interface. The list of controls displayed
to the user would contain the CLSID_Button and CLSID_MyDBControl. CLSID_GroupBox would not be
displayed.
Related topics
A
s
s
o
c
i
a
t
i
n
g
I
c
o
n
s
w
i
t
h
a
C
a
t
e
g
o
r
y
C
a
t
e
g
o
r
i
z
i
n
g
b
y
C
o
m
p
o
n
e
n
t
C
a
p
a
b
i
l
i
t
i
e
s
D
e
f
a
u
l
t
C
l
a
s
s
e
s
a
n
d
A
s
s
o
c
i
a
t
i
o
n
s
D
e
f
i
n
i
n
g
C
o
m
p
o
n
e
n
t
C
a
t
e
g
o
r
i
e
s
T
h
e
C
o
m
p
o
n
e
n
t
C
a
t
e
g
o
r
i
e
s
M
a
n
a
g
e
r
The Component Categories Manager
1/7/2020 • 2 minutes to read • Edit Online
To facilitate the handling of component categories and to guarantee consistency of the registry, the system
provides the Component Categories Manager, a COM object with a CLSID of
CLSID_StdComponentCategoriesMgr. This COM object provides the following interfaces:
ICatInformation
ICatRegister
ICatInformation provides methods for obtaining information about the categories implemented or required by
a certain class and provides information about the categories registered on a given machine.
ICatRegister provides methods for registering and unregistering component category information in the
registry. This includes both the human-readable names of categories and the categories implemented or required
by a given component or class.
Related topics
A
s
s
o
c
i
a
t
i
n
g
I
c
o
n
s
w
i
t
h
a
C
a
t
e
g
o
r
y
C
a
t
e
g
o
r
i
z
i
n
g
b
y
C
o
m
p
o
n
e
n
t
C
a
p
a
b
i
l
i
t
i
e
s
C
a
t
e
g
o
r
i
z
i
n
g
b
y
C
o
n
t
a
i
n
e
r
C
a
p
a
b
i
l
i
t
i
e
s
D
e
f
a
u
l
t
C
l
a
s
s
e
s
a
n
d
A
s
s
o
c
i
a
t
i
o
n
s
D
e
f
i
n
i
n
g
C
o
m
p
o
n
e
n
t
C
a
t
e
g
o
r
i
e
s
Default Classes and Associations
1/7/2020 • 2 minutes to read • Edit Online
For certain categories, a single class can be associated as the default class. The default class is selected whenever
that particular category of object is required. While this may not be useful for all component categories,
establishing a default class can be helpful when a particular class must be loaded from a list of possible classes
without user intervention. Administrators define which class can be used by manipulating the registry.
To associate a default class with a category, introduce a CLSID key with the same CLSID as the CATID of the
component category chosen as the default. Then add a TreatAs key to this key, using the value for the CLSID of
the default class for the category. To use the default class for a component category, use CoCreateInstance or
CoGetClassObject, specifying the CATID for the CLSID parameter. This automatically redirects to the CLSID
established as the default for this category. The registry entry is as follows:
HKEY_CLASSES_ROOT\CLSID
{catid}
TreatAs
= default clsid
During installation, a component can check for the existence of any default class keys for its categories and
present the user with options for overriding the current settings.
Related topics
A
s
s
o
c
i
a
t
i
n
g
I
c
o
n
s
w
i
t
h
a
C
a
t
e
g
o
r
y
C
a
t
e
g
o
r
i
z
i
n
g
b
y
C
o
m
p
o
n
e
n
t
C
a
p
a
b
i
l
i
t
i
e
s
C
a
t
e
g
o
r
i
z
i
n
g
b
y
C
o
n
t
a
i
n
e
r
C
a
p
a
b
i
l
i
t
i
e
s
D
e
f
i
n
i
n
g
C
o
m
p
o
n
e
n
t
C
a
t
e
g
o
r
i
e
s
T
h
e
C
o
m
p
o
n
e
n
t
C
a
t
e
g
o
r
i
e
s
M
a
n
a
g
e
r
Defining Component Categories
1/7/2020 • 2 minutes to read • Edit Online
The author of a component category definition creates a unique GUID (the CATID ) that is published along with
the definition. Other parties know the definition of this type and can make use of its supported classes
accordingly. Like the method signature of an interface, a category's semantics should not be modified after being
installed. It is better to maintain backward compatibility of the category by introducing a new category identifier
with revised semantics.
Because interface identifiers (IID ) and component category identifiers (CATID ) exist in different namespaces, it
seems as if it would be possible to use the same GUID for both an IID and a CATID. However, since IIDs are often
used for the CLSID of the interface's proxy/stub server, there is the potential for conflict. Therefore, do not use the
same GUID for an IID and CATID.
Related topics
A
s
s
o
c
i
a
t
i
n
g
I
c
o
n
s
w
i
t
h
a
C
a
t
e
g
o
r
y
C
a
t
e
g
o
r
i
z
i
n
g
b
y
C
o
m
p
o
n
e
n
t
C
a
p
a
b
i
l
i
t
i
e
s
C
a
t
e
g
o
r
i
z
i
n
g
b
y
C
o
n
t
a
i
n
e
r
C
a
p
a
b
i
l
i
t
i
e
s
D
e
f
a
u
l
t
C
l
a
s
s
e
s
a
n
d
A
s
s
o
c
i
a
t
i
o
n
s
T
h
e
C
o
m
p
o
n
e
n
t
C
a
t
e
g
o
r
i
e
s
M
a
n
a
g
e
r
Associating Icons with a Category
1/7/2020 • 2 minutes to read • Edit Online
Building a user interface that allows the user to select component categories within a category requires the ability
to display a meaningful image for a particular category. To associate an icon with a component category, create a
key for the category's CATID and populate that key with a DefaultIcon subkey. The registry entry is as follows:
HKEY_CLASSES_ROOT\CLSID\{...catid...}\DefaultIcon = "c:\hello\icons.dll,1"
The filename referenced by the DefaultIcon key can be either an EXE or a DLL file (resource-only DLL ).
To associate a small 16x16 "toolbox bitmap" with a component category, create a key in
HKEY_CLASSES_ROOT\CLSID for the category's CATID and populate that key with a ToolBoxBitmap32
subkey, as shown in the following example:
HKEY_CLASSES_ROOT\CLSID\{...catid...}\ToolBoxBitmap32 = "c:\goodbye\mycomponent.dll,42"
The filename referenced by the ToolBoxBitmap32 key can also be an EXE or DLL file (resource-only DLL ).
Related topics
C
a
t
e
g
o
r
i
z
i
n
g
b
y
C
o
m
p
o
n
e
n
t
C
a
p
a
b
i
l
i
t
i
e
s
C
a
t
e
g
o
r
i
z
i
n
g
b
y
C
o
n
t
a
i
n
e
r
C
a
p
a
b
i
l
i
t
i
e
s
D
e
f
a
u
l
t
C
l
a
s
s
e
s
a
n
d
A
s
s
o
c
i
a
t
i
o
n
s
D
e
f
i
n
i
n
g
C
o
m
p
o
n
e
n
t
C
a
t
e
g
o
r
i
e
s
I
C
a
t
I
n
f
o
r
m
a
t
i
o
n
I
C
a
t
R
e
g
i
s
t
e
r
T
h
e
C
o
m
p
o
n
e
n
t
C
a
t
e
g
o
r
i
e
s
M
a
n
a
g
e
r
Reference
1/7/2020 • 2 minutes to read • Edit Online
These values indicate whether an entry in the access list describes rights that are allowed or denied.
CONSTANT/VALUE DESCRIPTION
Requirements
Header
Acc
Ctrl.
h
See also
A
C
T
R
L
_
A
C
C
E
S
S
_
E
N
T
R
Y
Authentication Level Constants
1/7/2020 • 2 minutes to read • Edit Online
These values specify an authentication level, which indicates the amount of authentication provided to help protect
the integrity of the data. Each level includes the protection provided by the previous levels.
CONSTANT/VALUE DESCRIPTION
Performs no authentication.
RPC
_C_
AUT
HN_
LEV
EL_
NO
NE
1
Requirements
Header
Rpc
dce.
h
Authentication Service Constants
1/7/2020 • 2 minutes to read • Edit Online
Defines authentication services by identifying the security package that provides the service, such as NTLMSSP,
Kerberos, or Schannel.
CONSTANT/VALUE DESCRIPTION
No authentication.
RPC
_C_
AUT
HN_
NO
NE
0
NTLMSSP
RPC
_C_
AUT
HN_
WI
NN
T
10
Remarks
These constants are used in the SOLE_AUTHENTICATION_SERVICE and the
SOLE_AUTHENTICATION_INFO structures. The SOLE_AUTHENTICATION_SERVICE structure is passed by
the server to the CoInitializeSecurity function and can be retrieved by the CoQueryAuthenticationServices
function. A pointer to a SOLE_AUTHENTICATION_INFO structure is passed by the client to
CoInitializeSecurity. For more information on the security packages identified by these values, such as
NTLMSSP and Kerberos, see COM and Security Packages.
Requirements
Header
Rpc
Dce.
h
See also
C
o
I
n
i
t
i
a
l
i
z
e
S
e
c
u
r
i
t
y
C
o
Q
u
e
r
y
A
u
t
h
e
n
t
i
c
a
t
i
o
n
S
e
r
v
i
c
e
s
I
C
l
i
e
n
t
S
e
c
u
r
i
t
y
S
O
L
E
_
A
U
T
H
E
N
T
I
C
A
T
I
O
N
_
I
N
F
O
S
O
L
E
_
A
U
T
H
E
N
T
I
C
A
T
I
O
N
_
S
E
R
V
I
C
E
Authorization Constants
1/7/2020 • 2 minutes to read • Edit Online
CONSTANT/VALUE DESCRIPTION
Remarks
These constants are used by methods of the IClientSecurity interface. They are used in the
SOLE_AUTHENTICATION_SERVICE structure, which is retrieved by the CoQueryAuthenticationServices
function. They are also used in the SOLE_AUTHENTICATION_INFO structure, which in turn is a member of the
SOLE_AUTHENTICATION_LIST structure. This structure, which is a list of authentication services, the
authorization services they perform, and the authentication information for each service, is passed to the
CoInitializeSecurity function and the IClientSecurity::SetBlanket method.
Requirements
Header
Rpc
Dce.
h
See also
C
o
I
n
i
t
i
a
l
i
z
e
S
e
c
u
r
i
t
y
C
o
Q
u
e
r
y
A
u
t
h
e
n
t
i
c
a
t
i
o
n
S
e
r
v
i
c
e
s
I
C
l
i
e
n
t
S
e
c
u
r
i
t
y
S
O
L
E
_
A
U
T
H
E
N
T
I
C
A
T
I
O
N
_
I
N
F
O
S
O
L
E
_
A
U
T
H
E
N
T
I
C
A
T
I
O
N
_
S
E
R
V
I
C
E
COM Error Codes
1/7/2020 • 2 minutes to read • Edit Online
The following topics provide lists of error codes used by COM -based APIs. These values are defined in the
Winerror.h header file.
COM Error Codes (Generic)
COM Error Codes (XACT, SCHED, OLE )
COM Error Codes (STG, RPC )
COM Error Codes (Security and Setup)
COM Error Codes (COMADMIN, FILTER, GRAPHICS )
COM Error Codes (TPM, PLA, FVE )
COM Error Codes (FWP, WS, NDIS, HyperV )
COM Error Codes (VOLMGR, BCD, VHD, SDIAG)
COM Error Codes (WPN, MBN, P2P, Bluetooth)
COM Error Codes (UI, Audio, DirectX, Codec)
If you are experiencing difficulty with an application you are installing or running, contact customer support for
the software that is displaying the error message. To obtain support for a Microsoft product, go to
https://support.microsoft.com.
COM Error Codes (Generic)
1/7/2020 • 9 minutes to read • Edit Online
The following table provides a list of error codes used by COM -based APIs.
If you are experiencing difficulty with an application you are installing or running, contact customer support for the
software that is displaying the error message. To obtain support for a Microsoft product, go to
https://support.microsoft.com.
CONSTANT/VALUE DESCRIPTION
Catastrophic failure
E_U
NEX
PEC
TED
0x8
000
FFFF
Not implemented
E_N
OTI
MP
L
0x8
000
400
1
Invalid pointer
E_P
OIN
TER
0x8
000
400
3
Invalid handle
E_H
AN
DLE
0x8
007
000
6
Operation aborted
E_A
BO
RT
0x8
000
400
4
Unspecified error
E_F
AIL
0x8
000
400
5
The text associated with this error code could not be found.
RO_
E_E
RR
OR_
STR
ING
_NO
T_F
OU
ND
0x8
000
001
6
Uninitialized object
OLE
_E_B
LAN
K
0x8
004
000
7
Invalid rectangle
OLE
_E_I
NV
ALI
DRE
CT
0x8
004
000
D
Invalid lindex
DV_
E_LI
NDE
X
0x8
004
006
8
Invalid tymed
DV_
E_T
YM
ED
0x8
004
006
9
CONSTANT/VALUE DESCRIPTION
Invalid aspect(s)
DV_
E_D
VAS
PEC
T
0x8
004
006
B
The size of this object exceeds the maximum size set by the
CS_ Administrator.
E_A
DMI
N_LI
MIT
_EX
CEE
DED
0x8
004
016
D
OpenClipboard Failed
CLI
PBR
D_E
_CA
NT_
OPE
N
0x8
004
01D
0
EmptyClipboard Failed
CLI
PBR
D_E
_CA
NT_
EM
PTY
0x8
004
01D
1
CONSTANT/VALUE DESCRIPTION
SetClipboard Failed
CLI
PBR
D_E
_CA
NT_
SET
0x8
004
01D
2
CloseClipboard Failed
CLI
PBR
D_E
_CA
NT_
CLO
SE
0x8
004
01D
4
Operation unavailable
MK_
E_U
NA
VAI
LAB
LE
0x8
004
01E
3
Invalid syntax
MK_
E_S
YNT
AX
0x8
004
01E
4
No common prefix
MK_
E_N
OP
REFI
X
0x8
004
01E
E
CONSTANT/VALUE DESCRIPTION
Header
Win
erro
r.h
See also
C
O
M
E
r
r
o
r
C
o
d
e
s
COM Error Codes (XACT, SCHED, OLE)
1/7/2020 • 12 minutes to read • Edit Online
The following table provides a list of error codes used by COM -based APIs.
If you are experiencing difficulty with an application you are installing or running, contact customer support for the
software that is displaying the error message. To obtain support for a Microsoft product, go to
https://support.microsoft.com.
CONSTANT/VALUE DESCRIPTION
The indicated unit of work does not match the unit of work
XAC expected by the resource manager.
T_E_
WR
ON
GU
OW
0x8
004
D01
2
CONSTANT/VALUE DESCRIPTION
XACT_E_CLERKNOTFOUND
XAC
T_E_
CLE
RK
NO
TFO
UN
D
0x8
004
D08
0
CONSTANT/VALUE DESCRIPTION
XACT_E_CLERKEXISTS
XAC
T_E_
CLE
RKE
XIS
TS
0x8
004
D08
1
XACT_E_RECOVERYINPROGRESS
XAC
T_E_
REC
OVE
RYI
NP
RO
GRE
SS
0x8
004
D08
2
XACT_E_TRANSACTIONCLOSED
XAC
T_E_
TRA
NS
ACT
ION
CLO
SED
0x8
004
D08
3
XACT_E_INVALIDLSN
XAC
T_E_
INV
ALI
DLS
N
0x8
004
D08
4
CONSTANT/VALUE DESCRIPTION
XACT_E_REPLAYREQUEST
XAC
T_E_
REP
LAY
REQ
UES
T
0x8
004
D08
5
XACT_S_DEFECT
XAC
T_S_
DEF
ECT
0x0
004
D00
1
No changes were made during this call, but the sink wants
XAC another chance to look if any other sinks make further
T_S_ changes.
OKI
NF
OR
M
0x0
004
D00
4
Same cache
CAC
HE_
S_S
AM
ECA
CHE
0x0
004
017
1
CONSTANT/VALUE DESCRIPTION
The task will not run at the scheduled times because it has
SCH been disabled.
ED_
S_T
ASK
_DIS
ABL
ED
0x0
004
130
2
The task is registered, but not all specified triggers will start
SCH the task.
ED_
S_S
OM
E_T
RIG
GER
S_F
AILE
D
0x0
004
131
B
The task XML contains too many nodes of the same type.
SCH
ED_
E_T
OO_
MA
NY_
NO
DES
0x8
004
131
D
The task will not run because the user is not logged on.
SCH
ED_
E_U
SER
_NO
T_L
OG
GED
_ON
0x8
004
132
0
CONSTANT/VALUE DESCRIPTION
The Task Scheduler service attempted to run the task, but the
SCH task did not run due to one of the constraints in the task
ED_ definition.
E_T
ASK
_AT
TEM
PTE
D
0x8
004
132
4
CONSTANT/VALUE DESCRIPTION
The task has properties that are not compatible with previous
SCH versions of Windows.
ED_
E_T
ASK
_NO
T_V
1_C
OM
PAT
0x8
004
132
7
Unknown interface.
DIS
P_E_
UN
KN
OW
NIN
TER
FAC
E
0x8
002
000
1
CONSTANT/VALUE DESCRIPTION
Type mismatch.
DIS
P_E_
TYP
EMI
SM
ATC
H
0x8
002
000
5
Unknown name.
DIS
P_E_
UN
KN
OW
NN
AM
E
0x8
002
000
6
CONSTANT/VALUE DESCRIPTION
No named arguments.
DIS
P_E_
NO
NA
ME
DA
RGS
0x8
002
000
7
Exception occurred.
DIS
P_E_
EXC
EPTI
ON
0x8
002
000
9
Invalid index.
DIS
P_E_
BA
DIN
DEX
0x8
002
000
B
CONSTANT/VALUE DESCRIPTION
Unknown language.
DIS
P_E_
UN
KN
OW
NLC
ID
0x8
002
000
C
Memory is locked.
DIS
P_E_
ARR
AYI
SLO
CKE
D
0x8
002
000
D
Invalid callee.
DIS
P_E_
BA
DC
ALL
EE
0x8
002
001
0
Division by zero.
DIS
P_E_
DIV
BYZ
ERO
0x8
002
001
2
Type mismatch.
TYP
E_E_
WR
ON
GTY
PEK
IND
0x8
002
802
A
Ambiguous name.
TYP
E_E_
AM
BIG
UO
US
NA
ME
0x8
002
802
C
CONSTANT/VALUE DESCRIPTION
Unknown LCID.
TYP
E_E_
UN
KN
OW
NLC
ID
0x8
002
802
E
Type mismatch.
TYP
E_E_
TYP
EMI
SM
ATC
H
0x8
002
8CA
0
CONSTANT/VALUE DESCRIPTION
I/O Error.
TYP
E_E_
IOE
RR
OR
0x8
002
8CA
2
Requirements
Header
Win
erro
r.h
See also
C
O
M
E
r
r
o
r
C
o
d
e
s
COM Error Codes (STG, RPC)
1/7/2020 • 8 minutes to read • Edit Online
The following table provides a list of error codes used by COM -based APIs.
If you are experiencing difficulty with an application you are installing or running, contact customer support for the
software that is displaying the error message. To obtain support for a Microsoft product, go to
https://support.microsoft.com.
CONSTANT/VALUE DESCRIPTION
Access Denied.
STG
_E_
ACC
ESS
DEN
IED
0x8
003
000
5
Disk is write-protected.
STG
_E_
DIS
KIS
WRI
TEP
ROT
ECT
ED
0x8
003
001
3
already exists.
STG
_E_F
ILEA
LRE
AD
YEX
ISTS
0x8
003
005
0
Can't save.
STG
_E_C
AN
TSA
VE
0x8
003
010
3
Copy Protection Error - The given sector does not have a valid
STG CSS key.
_E_C
SS_
KEY
_NO
T_P
RES
ENT
0x8
003
030
7
CONSTANT/VALUE DESCRIPTION
The call was not transmitted properly; the message queue was
RPC full and was not emptied after yielding.
_E_C
AN
TTR
AN
SMI
T_C
ALL
0x8
001
000
A
RPC could not call the server or could not return the results of
RPC calling the server.
_E_F
AUL
T
0x8
001
010
4
The object invoked chose not to process the call now. Try
RPC again later.
_E_R
ETR
Y
0x8
001
010
9
Access is denied.
RPC
_E_
ACC
ESS
_DE
NIE
D
0x8
001
011
B
CONSTANT/VALUE DESCRIPTION
Full subject issuer chain SSL principal name expected from the
RPC server.
_E_F
ULL
SIC_
REQ
UIR
ED
0x8
001
012
1
Requirements
Header
Win
erro
r.h
See also
C
O
M
E
r
r
o
r
C
o
d
e
s
COM Error Codes (Security and Setup)
1/7/2020 • 32 minutes to read • Edit Online
The following table provides a list of error codes used by COM -based APIs.
If you are experiencing difficulty with an application you are installing or running, contact customer support for the
software that is displaying the error message. To obtain support for a Microsoft product, go to
https://support.microsoft.com.
CONSTANT/VALUE DESCRIPTION
The computed hash value of the block does not match the
APP one stored in the block map.
X_E_
BLO
CK_
HA
SH_
INV
ALI
D
0x8
008
020
7
Bad UID.
NTE
_BA
D_U
ID
0x8
009
000
1
Bad Hash.
NTE
_BA
D_H
AS
H
0x8
009
000
2
Bad Key.
NTE
_BA
D_K
EY
0x8
009
000
3
Bad Length.
NTE
_BA
D_L
EN
0x8
009
000
4
Bad Data.
NTE
_BA
D_D
ATA
0x8
009
000
5
CONSTANT/VALUE DESCRIPTION
Invalid Signature.
NTE
_BA
D_SI
GN
ATU
RE
0x8
009
000
6
Access denied.
NTE
_PE
RM
0x8
009
001
0
Provider could not perform the action since the context was
NTE acquired as silent.
_SIL
ENT
_CO
NTE
XT
0x8
009
002
2
The security token does not have storage space available for
NTE an additional container.
_TO
KEN
_KE
YSE
T_S
TOR
AGE
_FU
LL
0x8
009
002
3
The key parameters could not be set because the CSP uses
NTE fixed parameters.
_FIX
EDP
AR
AM
ETE
R
0x8
009
002
5
Incorrect password.
NTE
_IN
CO
RRE
CT_
PAS
SW
OR
D
0x8
009
003
3
Encryption failed.
NTE
_EN
CRY
PTI
ON_
FAIL
URE
0x8
009
003
4
CONSTANT/VALUE DESCRIPTION
The client certificate does not contain a valid UPN, or does not
SEC match the client name in the logon request. Please contact
_E_P your administrator.
KINI
T_N
AM
E_M
ISM
ATC
H
0x8
009
033
D
SEC_E_NO_KERB_KEY
SEC
_E_
NO_
KER
B_K
EY
0x8
009
034
8
Since the server was offline, the called function was unable to
CRY complete the usage check.
PT_
E_V
ERIF
Y_U
SAG
E_O
FFLI
NE
0x8
009
202
9
OSS ASN.1 Error: Output buffer is too small, the decoded data
OSS has been truncated.
_M
ORE
_IN
PUT
0x8
009
300
4
The public key does not meet the minimum size required by
CER the specified certificate template.
TSR
V_E_
KEY
_LE
NG
TH
0x8
009
481
1
CONSTANT/VALUE DESCRIPTION
You cannot add the root CA certificate into your local store.
XEN
ROL
L_E_
CA
NN
OT_
AD
D_R
OO
T_C
ERT
0x8
009
500
1
The key archival hash attribute was not found in the response.
XEN
ROL
L_E_
RES
PO
NSE
_KA
_HA
SH_
NO
T_F
OU
ND
0x8
009
500
2
Too many pad bytes between tables or pad bytes are not 0.
MS
SIP
OTF
_E_T
ABL
E_P
AD
BYT
ES
0x8
009
700
A
CONSTANT/VALUE DESCRIPTION
The signature does not have the correct attributes for the
MS policy.
SIP
OTF
_E_F
AILE
D_P
OLI
CY
0x8
009
701
0
CONSTANT/VALUE DESCRIPTION
The files affected by the installation of this file queue have not
SPA been backed up for uninstall.
PI_E
_NO
_BA
CKU
P
0x8
00F
010
3
The INF from which a driver list is to be built does not exist.
SPA
PI_E
_NO
_INF
0x8
00F
020
A
CONSTANT/VALUE DESCRIPTION
The class installer has indicated that the default action should
SPA be performed for this installation request.
PI_E
_DI_
DO_
DEF
AUL
T
0x8
00F
020
E
CONSTANT/VALUE DESCRIPTION
The driver selected for this device does not support this
SPA version of Windows.
PI_E
_NO
N_
WI
ND
OW
S_N
T_D
RIV
ER
0x8
00F
022
D
The driver selected for this device does not support Windows.
SPA
PI_E
_NO
N_
WI
ND
OW
S_D
RIV
ER
0x8
00F
022
E
The hash for the file is not present in the specified catalog file.
SPA The file is likely corrupt or the victim of tampering.
PI_E
_FIL
E_H
AS
H_N
OT_
IN_
CAT
ALO
G
0x8
00F
024
B
The data buffer to receive returned data is too small for the
SCA returned data.
RD_
E_IN
SUF
FICI
ENT
_BU
FFE
R
0x8
010
000
8
There was an error trying to set the smart card file object
SCA pointer.
RD_
E_B
AD_
SEE
K
0x8
010
002
9
The requested key container does not exist on the smart card.
SCA
RD_
E_N
O_K
EY_
CO
NT
AIN
ER
0x8
010
003
0
Power has been removed from the smart card, so that further
SCA communication is not possible.
RD_
W_
UN
PO
WE
RED
_CA
RD
0x8
010
006
7
The requested cache item is too old and was deleted from the
SCA cache.
RD_
W_
CAC
HE_I
TEM
_ST
ALE
0x8
010
007
1
Requirements
Header
Win
erro
r.h
See also
C
O
M
E
r
r
o
r
C
o
d
e
s
COM Error Codes (COMADMIN, FILTER, GRAPHICS)
1/7/2020 • 25 minutes to read • Edit Online
The following table provides a list of error codes used by COM -based APIs.
If you are experiencing difficulty with an application you are installing or running, contact customer support for the
software that is displaying the error message. To obtain support for a Microsoft product, go to
https://support.microsoft.com.
CONSTANT/VALUE DESCRIPTION
The requested device object does not exist for the given
ERR volume.
OR_
FLT_
NO_
DEV
ICE_
OBJ
ECT
0x8
01F
001
9
CONSTANT/VALUE DESCRIPTION
Specified display adapter and all of its state has been reset.
ERR
OR_
GR
AP
HIC
S_A
DA
PTE
R_
WA
S_R
ESE
T
0xC
026
200
3
Specified mode set does not specify preference for one of its
ERR modes.
OR_
GR
AP
HIC
S_N
O_P
REF
ERR
ED_
MO
DE
0x0
026
231
E
Specified mode set is stale. Please reacquire the new mode set.
ERR
OR_
GR
AP
HIC
S_S
TAL
E_M
ODE
SET
0xC
026
232
0
CONSTANT/VALUE DESCRIPTION
No more than one unassigned mode set can exist at any given
ERR time for a given VidPN source/target.
OR_
GR
AP
HIC
S_U
NA
SSI
GNE
D_
MO
DES
ET_
ALR
EAD
Y_E
XIS
TS
0xC
026
235
0
CONSTANT/VALUE DESCRIPTION
The driver trying to start is not the same as the driver for the
ERR POSTed display adapter.
OR_
GR
AP
HIC
S_N
OT_
POS
T_D
EVI
CE_
DRI
VER
0xC
026
243
8
CONSTANT/VALUE DESCRIPTION
The GDI display device passed to this function does not have
ERR any active video outputs.
OR_
GR
AP
HIC
S_O
PM_
NO_
VID
EO_
OU
TPU
TS_
EXIS
T
0xC
026
250
5
CONSTANT/VALUE DESCRIPTION
Either the
ERR IOPMVideoOutput::COPPCompatibleGetInformation,
OR_ IOPMVideoOutput::GetInformation, or
GR IOPMVideoOutput::Configure method failed. This error is
AP returned when the caller tries to use a COPP specific
HIC command while the video output has OPM semantics only.
S_O
PM_
VID
EO_
OU
TPU
T_D
OES
_NO
T_H
AVE
_CO
PP_
SEM
AN
TIC
S
0xC
026
251
C
CONSTANT/VALUE DESCRIPTION
Either the
ERR IOPMVideoOutput::COPPCompatibleGetInformation,
OR_ IOPMVideoOutput::GetInformation, or
GR IOPMVideoOutput::Configure method failed. This error is
AP returned when the caller tries to use an OPM specific
HIC command while the video output has COPP semantics only.
S_O
PM_
VID
EO_
OU
TPU
T_D
OES
_NO
T_H
AVE
_OP
M_S
EM
AN
TIC
S
0xC
026
251
F
The IOPMVideoOutput::COPPCompatibleGetInformation or
ERR IOPMVideoOutput::Configure method failed because the
OR_ display driver does not support the
GR OPM_GET_ACP_AND_CGMSA_SIGNALING and
AP OPM_SET_ACP_AND_CGMSA_SIGNALING GUIDs.
HIC
S_O
PM_
SIG
NAL
ING
_NO
T_S
UPP
ORT
ED
0xC
026
252
0
CONSTANT/VALUE DESCRIPTION
The function failed because the specified GDI device did not
ERR have any monitors associated with it.
OR_
GR
AP
HIC
S_N
O_
MO
NIT
ORS
_CO
RRE
SPO
ND_
TO_
DIS
PLA
Y_D
EVI
CE
0xC
026
25E
5
Requirements
Header
Win
erro
r.h
See also
C
O
M
E
r
r
o
r
C
o
d
e
s
COM Error Codes (TPM, PLA, FVE)
1/7/2020 • 43 minutes to read • Edit Online
The following table provides a list of error codes used by COM -based APIs.
If you are experiencing difficulty with an application you are installing or running, contact customer support for the
software that is displaying the error message. To obtain support for a Microsoft product, go to
https://support.microsoft.com.
CONSTANT/VALUE DESCRIPTION
Authentication failed.
TP
M_E
_AU
THF
AIL
0x8
028
000
1
The clear disable flag is set and all clear operations now
TP require physical access.
M_E
_CL
EAR
_DIS
ABL
ED
0x8
028
000
5
The TPM does not have the space to perform the operation.
TP
M_E
_SIZ
E
0x8
028
001
7
The named PCR value does not match the current PCR value.
TP
M_E
_W
RO
NG
PCR
VAL
0x8
028
001
8
The key is under control of the TPM Owner and can only be
TP evicted by the TPM Owner.
M_E
_KE
Y_O
WN
ER_
CO
NTR
OL
0x8
028
004
4
TPM 2.0: Value is out of range or is not correct for the context.
TP
M_2
0_E_
VAL
UE
0x8
028
008
4
CONSTANT/VALUE DESCRIPTION
TPM 2.0: Hierarchy is not enabled or is not correct for the use.
TP
M_2
0_E_
HIE
RAR
CH
Y
0x8
028
008
5
TPM 2.0: The type of the value is not appropriate for the use.
TP
M_2
0_E_
TYP
E
0x8
028
008
A
CONSTANT/VALUE DESCRIPTION
TPM 2.0: Key fields are not compatible with the selected use.
TP
M_2
0_E_
KEY
0x8
028
008
7
TPM 2.0: The TPM is not in the right mode for upgrade.
TP
M_2
0_E_
UP
GR
ADE
0x8
028
012
D
TPM 2.0: chHash value already set or not correct for use.
TP
M_2
0_E_
CP
HA
SH
0x8
028
015
1
CONSTANT/VALUE DESCRIPTION
TPM 2.0: The sensitive area did not unmarshal correctly after
TP decryption - this code is used in lieu of the other
M_2 unmarshaling errors so that an attacker cannot determine
0_E_ where the unmarshaling error occurred.
SEN
SITI
VE
0x8
028
015
5
CONSTANT/VALUE DESCRIPTION
TPM 2.0: Out of object handles - the handle space for objects
TP is depleted and a reboot is required.
M_2
0_E_
OBJ
ECT
_HA
NDL
ES
0x8
028
090
6
TPM 2.0: The TPM was not able to start the command.
TP
M_2
0_E_
RET
RY
0x8
028
092
2
The TBS service has been started but is not yet running.
TBS
_E_S
ERV
ICE_
STA
RT_
PEN
DIN
G
0x8
028
400
B
The caller does not have the appropriate rights to perform the
TBS requested operation.
_E_
ACC
ESS
_DE
NIE
D
0x8
028
401
2
The caller does not have the appropriate rights to perform the
TP requested operation.
MA
PI_E
_AC
CES
S_D
ENI
ED
0x8
029
010
8
The random number generated did not pass FIPS RNG check.
TP
MA
PI_E
_FIP
S_R
NG_
CHE
CK_
FAIL
ED
0x8
029
011
9
A digest value in a TCG Log entry did not match hashed data.
TP
MA
PI_E
_TC
G_I
NV
ALI
D_D
IGE
ST_
ENT
RY
0x8
029
011
D
The specified list is empty, or the iteration has reached the end
TBS of the list.
IMP
_E_L
IST_
NO_
MO
RE_I
TEM
S
0x8
029
020
D
The TPM does not have enough space to load the requested
TBS resource.
IMP
_E_
NO
T_E
NO
UG
H_S
PAC
E
0x8
029
020
F
CONSTANT/VALUE DESCRIPTION
A new TBS context could not be created because there are too
TBS many open contexts.
IMP
_E_T
OO_
MA
NY_
TBS
_CO
NTE
XTS
0x8
029
021
7
This key has a raw policy so the KSP can't authenticate against
TP it.
M_E
_PC
P_R
AW
_PO
LIC
Y_N
OT_
SUP
PO
RTE
D
0x8
029
042
1
CONSTANT/VALUE DESCRIPTION
The requested salt size for signing with RSAPSS does not
TP match what the TPM uses.
M_E
_PC
P_U
NS
UPP
ORT
ED_
PSS
_SA
LT
0x4
029
042
3
Unable to start Data Collector Set because there are too many
PLA folders.
_E_T
OO_
MA
NY_
FOL
DER
S
0x8
030
004
5
The executable path you have specified does not exist. Verify
PLA that the specified path is correct.
_E_E
XE_
PAT
H_N
OT_
VAL
ID
0x8
030
010
8
The wait for the Data Collector Set start notification has timed
PLA out.
_E_
DCS
_ST
ART
_W
AIT_
TIM
EOU
T
0x8
030
010
A
The wait for the Data Collector to start has timed out.
PLA
_E_
DC_
STA
RT_
WAI
T_TI
ME
OU
T
0x8
030
010
B
The wait for the report generation tool to finish has timed out.
PLA
_E_R
EPO
RT_
WAI
T_TI
ME
OU
T
0x8
030
010
C
CONSTANT/VALUE DESCRIPTION
The BIOS did not correctly communicate with the master boot
FVE record (MBR). Contact the computer manufacturer for BIOS
_E_ upgrade instructions.
NO_
MB
R_M
ETRI
C
0x8
031
000
3
The type of the data obtained from Active Directory was not
FVE expected. The BitLocker recovery information may be missing
_E_ or corrupted.
AD_
INV
ALI
D_D
ATA
TYP
E
0x8
031
000
B
The size of the data obtained from Active Directory was not
FVE expected. The BitLocker recovery information may be missing
_E_ or corrupted.
AD_
INV
ALI
D_D
ATA
SIZE
0x8
031
000
C
The attribute read from Active Directory does not contain any
FVE values. The BitLocker recovery information may be missing or
_E_ corrupted.
AD_
NO_
VAL
UES
0x8
031
000
D
The attribute was not set. Verify that you are logged on with a
FVE domain account that has the ability to write information to
_E_ Active Directory objects.
AD_
ATT
R_N
OT_
SET
0x8
031
000
E
CONSTANT/VALUE DESCRIPTION
The file system size is larger than the partition size in the
FVE partition table. This drive may be corrupt or may have been
_E_B tampered with. To use it with BitLocker, you must reformat
AD_ the partition.
PAR
TITI
ON_
SIZE
0x8
031
001
4
The drive you are attempting to lock does not have any key
FVE protectors available for encryption because BitLocker
_E_R protection is currently suspended. Re-enable BitLocker to lock
ECO this drive.
VER
Y_K
EY_
REQ
UIR
ED
0x8
031
002
2
CONSTANT/VALUE DESCRIPTION
The authorization data for the storage root key (SRK) of the
FVE Trusted Platform Module (TPM) is not zero and is therefore
_E_T incompatible with BitLocker. Please initialize the TPM before
PM_ attempting to use it with BitLocker.
SRK
_AU
TH_
NO
T_Z
ERO
0x8
031
002
5
The specified key protector was not found on the drive. Try
FVE another key protector.
_E_P
ROT
ECT
OR_
NO
T_F
OU
ND
0x8
031
003
3
Requirements
Header
Win
erro
r.h
See also
C
O
M
E
r
r
o
r
C
o
d
e
s
COM Error Codes (FWP, WS, NDIS, HyperV)
1/7/2020 • 16 minutes to read • Edit Online
The following table provides a list of error codes used by COM -based APIs.
If you are experiencing difficulty with an application you are installing or running, contact customer support for the
software that is displaying the error message. To obtain support for a Microsoft product, go to
https://support.microsoft.com.
CONSTANT/VALUE DESCRIPTION
The action type is not one of the allowed action types for a
FW filter.
P_E_
INV
ALI
D_A
CTI
ON_
TYP
E
0x8
032
002
4
The IKEEXT service is not running. This service only runs when
FW there is IPsec policy applied to the machine.
P_E_
IKEE
XT_
NO
T_R
UN
NIN
G
0x8
032
004
4
The input data was not in the expected format or did not have
WS_ the expected value.
E_IN
VAL
ID_F
OR
MA
T
0x8
03D
000
0
A message queue with the same name already exists for the
ERR virtualization infrastructure driver.
OR_
VID
_ME
SSA
GE_
QUE
UE_
ALR
EAD
Y_E
XIS
TS
0xC
037
000
B
Cannot unlock the page array for the guest operating system
ERR memory address because it does not match a previous lock
OR_ request. Restarting the virtual machine may fix the problem. If
VID the problem persists, try restarting the physical computer.
_CH
ILD_
GP
A_P
AGE
_SE
T_C
OR
RUP
TED
0xC
037
000
E
The request exceeded the memory block page limit for the
ERR virtualization infrastructure driver. Restarting the virtual
OR_ machine may fix the problem. If the problem persists, try
VID restarting the physical computer.
_PA
GE_
RA
NGE
_OV
ERF
LO
W
0xC
037
001
3
CONSTANT/VALUE DESCRIPTION
The memory mapped I/O for this page range no longer exists.
ERR Restarting the virtual machine may fix the problem. If the
OR_ problem persists, try restarting the physical computer.
VID
_M
MIO
_RA
NGE
_DE
STR
OYE
D
0xC
037
002
1
Header
Win
erro
r.h
See also
C
O
M
E
r
r
o
r
C
o
d
e
s
COM Error Codes (VOLMGR, BCD, VHD, SDIAG)
1/7/2020 • 10 minutes to read • Edit Online
The following table provides a list of error codes used by COM -based APIs.
If you are experiencing difficulty with an application you are installing or running, contact customer support for the
software that is displaying the error message. To obtain support for a Microsoft product, go to
https://support.microsoft.com.
CONSTANT/VALUE DESCRIPTION
The regeneration operation was not able to copy all data from
ERR the active plexes due to bad sectors.
OR_
VOL
MG
R_I
NC
OM
PLE
TE_
REG
ENE
RAT
ION
0x8
038
000
1
One or more disks were not fully migrated to the target pack.
ERR They may or may not require reimport after fixing the
OR_ hardware problems.
VOL
MG
R_I
NC
OM
PLE
TE_
DIS
K_M
IGR
ATI
ON
0x8
038
000
2
CONSTANT/VALUE DESCRIPTION
The same disk was specified more than once in the migration
ERR list.
OR_
VOL
MG
R_D
ISK_
DU
PLI
CAT
E
0xC
038
000
6
CONSTANT/VALUE DESCRIPTION
The disk layout contains partitions which are samller than the
ERR minimum size.
OR_
VOL
MG
R_D
ISK_
LAY
OU
T_P
ART
ITIO
NS_
TO
O_S
MA
LL
0xC
038
000
E
CONSTANT/VALUE DESCRIPTION
The specified plex is the last active plex in the volume. The plex
ERR cannot be removed or else the volume will go offline.
OR_
VOL
MG
R_P
LEX
_LA
ST_
ACT
IVE
0xC
038
003
B
CONSTANT/VALUE DESCRIPTION
The specified size for the volume is not a multiple of the sector
ERR size.
OR_
VOL
MG
R_V
OLU
ME_
LEN
GT
H_N
OT_
SEC
TOR
_SIZ
E_M
ULT
IPLE
0xC
038
004
8
All disks failed to be updated with the new content of the log.
ERR
OR_
VOL
MG
R_P
ACK
_LO
G_U
PD
ATE
_FAI
LED
0xC
038
005
3
Some BCD entries were not imported correctly from the BCD
ERR store.
OR_
BCD
_NO
T_A
LL_E
NTR
IES_
IMP
ORT
ED
0x8
039
000
1
CONSTANT/VALUE DESCRIPTION
The virtual hard disk is corrupted. The virtual hard disk drive
ERR footer is missing.
OR_
VH
D_D
RIV
E_F
OO
TER
_MI
SSI
NG
0xC
03A
000
1
CONSTANT/VALUE DESCRIPTION
The virtual hard disk is corrupted. The virtual hard disk drive
ERR footer checksum does not match the on-disk checksum.
OR_
VH
D_D
RIV
E_F
OO
TER
_CH
ECK
SU
M_
MIS
MA
TCH
0xC
03A
000
2
The virtual hard disk is corrupted. The virtual hard disk drive
ERR footer in the virtual hard disk is corrupted.
OR_
VH
D_D
RIV
E_F
OO
TER
_CO
RRU
PT
0xC
03A
000
3
The system does not recognize the file format of this virtual
ERR hard disk.
OR_
VH
D_F
OR
MA
T_U
NK
NO
WN
0xC
03A
000
4
CONSTANT/VALUE DESCRIPTION
The version does not support this version of the file format.
ERR
OR_
VH
D_F
OR
MA
T_U
NS
UPP
ORT
ED_
VER
SIO
N
0xC
03A
000
5
The system does not support this version of the virtual hard
ERR disk.This version of the sparse header is not supported.
OR_
VH
D_S
PAR
SE_
HEA
DER
_UN
SUP
PO
RTE
D_V
ERSI
ON
0xC
03A
000
7
The system does not support this version of the virtual hard
ERR disk. The block size is invalid.
OR_
VH
D_I
NV
ALI
D_B
LOC
K_SI
ZE
0xC
03A
000
B
The virtual hard disk is corrupted. The block bitmap does not
ERR match with the block data present in the virtual hard disk.
OR_
VH
D_B
ITM
AP_
MIS
MA
TCH
0xC
03A
000
C
CONSTANT/VALUE DESCRIPTION
A virtual disk support provider for the specified file was not
ERR found.
OR_
VIR
TDI
SK_
PR
OVI
DER
_NO
T_F
OU
ND
0xC
03A
001
4
The sector size of the physical disk on which the virtual disk
ERR resides is not supported.
OR_
VIR
TDI
SK_
UN
SUP
PO
RTE
D_D
ISK_
SEC
TOR
_SIZ
E
0xC
03A
001
D
Change Tracking file for the virtual disk is not in a valid state.
ERR
OR_
CTL
OG_
INC
ON
SIST
AN
T_T
RAC
KIN
G_FI
LE
0xC
03A
002
4
CONSTANT/VALUE DESCRIPTION
There is not enough space in the virtual disk file for the
ERR provided metadata item.
OR_
VH
D_
MET
AD
ATA
_FU
LL
0xC
03A
002
8
Requirements
Header
Win
erro
r.h
See also
C
O
M
E
r
r
o
r
C
o
d
e
s
COM Error Codes (WPN, MBN, P2P, Bluetooth)
1/7/2020 • 6 minutes to read • Edit Online
The following table provides a list of error codes used by COM -based APIs.
If you are experiencing difficulty with an application you are installing or running, contact customer support for the
software that is displaying the error message. To obtain support for a Microsoft product, go to
https://support.microsoft.com.
W
P 0
N x
_ 8
E 0
_ 3
C E
H 0
A 1
N 0
N 0
E T
L h
_ e
C n
L o
O t
S i
E f
D i
c
a
t
i
o
n
c
h
a
n
n
e
l
h
a
s
a
l
r
e
a
d
y
b
e
e
n
c
l
o
s
e
d
.
W
P 0
N x
_ 8
E 0
_ 3
C E
H 0
A 1
N 0
N 1
E T
L h
_ e
R n
E o
Q t
U i
E f
S i
T c
_ a
N t
O i
T o
_ n
C c
O h
M a
P n
L n
E e
T l
E r
e
q
u
e
s
t
d
i
d
n
o
t
c
o
m
p
l
e
t
e
s
u
c
c
e
s
s
f
u
l
l
y
.
W
P 0
N x
_ 8
E 0
_ 3
I E
N 0
V 1
A 0
L 2
I T
D h
_ e
A a
P p
P p
l
i
c
a
t
i
o
n
i
d
e
n
t
i
f
i
e
r
p
r
o
v
i
d
e
d
i
s
i
n
v
a
l
i
d
.
W
P 0
N x
_ 8
E 0
_ 3
O E
U 0
T 1
S 0
T 3
A A
N n
D o
I t
N i
G
_ f
C i
H c
A a
N t
N i
E o
L n
_ c
R h
E a
Q n
U n
E e
S l
T r
e
q
u
e
s
t
f
o
r
t
h
e
p
r
o
v
i
d
e
d
a
p
p
l
i
c
a
t
i
o
n
i
d
e
n
t
i
f
i
e
r
i
s
i
n
p
r
o
g
r
e
s
s
.
W
P 0
N x
_ 8
E 0
_ 3
D E
U 0
P 1
L 0
I 4
C T
A h
T e
E c
_ h
C a
H n
A n
N e
N l
E i
L d
e
n
t
i
f
i
e
r
i
s
a
l
r
e
a
d
y
t
i
e
d
t
o
a
n
o
t
h
e
r
a
p
p
l
i
c
a
t
i
o
n
e
n
d
p
o
i
n
t
.
W
P 0
N x
_ 8
E 0
_ 3
P E
L 0
A 1
T 0
F 5
O
R T
M h
_ e
U n
N o
A t
V i
A f
I i
L c
A a
B t
L i
E o
n
p
l
a
t
f
o
r
m
i
s
u
n
a
v
a
i
l
a
b
l
e
.
W
P 0
N x
_ 8
E 0
_ 3
N E
O 0
T 1
I 0
F 6
I T
C h
A e
T n
I o
O t
N i
_ f
P i
O c
S a
T t
E i
D o
n
h
a
s
a
l
r
e
a
d
y
b
e
e
n
p
o
s
t
e
d
.
W
P 0
N x
_ 8
E 0
_ 3
N E
O 0
T 1
I 0
F 7
I T
C h
A e
T n
I
O o
N t
_ i
H f
I i
D c
D a
E t
N i
o
n
h
a
s
a
l
r
e
a
d
y
b
e
e
n
h
i
d
d
e
n
.
W
P 0
N x
_ 8
E 0
_ 3
N E
O 0
T 1
I 0
F 8
I T
C h
A e
T n
I o
O t
N i
_
N f
O i
T c
_ a
P t
O i
S o
T n
E c
D a
n
n
o
t
b
e
h
i
d
d
e
n
u
n
t
i
l
i
t
h
a
s
b
e
e
n
s
h
o
w
n
.
W
P 0
N x
_ 8
E 0
_ 3
C E
L 0
O 1
U 0
D 9
_
D C
I l
S o
A u
B d
L n
E o
D t
i
f
i
c
a
t
i
o
n
s
h
a
v
e
b
e
e
n
t
u
r
n
e
d
o
f
f.
W
P 0
N x
_ 8
E 0
_ 3
C E
L 0
O 1
U 1
D 0
_ T
I h
N e
C a
A p
P p
A l
B i
L c
E a
t
i
o
n
d
o
e
s
n
o
t
h
a
v
e
t
h
e
c
l
o
u
d
n
o
t
i
f
i
c
a
t
i
o
n
c
a
p
a
b
i
l
i
t
y
.
W
P 0
N x
_ 8
E 0
_ 3
N E
O 0
T 1
I 1
F 1
I S
C e
A t
T t
I i
O n
N g
_ s
D p
I r
S e
A v
B e
L n
E t
D t
h
e
n
o
t
i
f
i
c
a
t
i
o
n
f
r
o
m
b
e
i
n
g
d
e
l
i
v
e
r
e
d
.
W
P 0
N x
_ 8
E 0
_ 3
N E
O 0
T 1
I 1
F 2
I A
C p
A p
T l
I i
O c
N a
_ t
I i
N o
C n
A c
P a
A p
B a
L b
E i
l
i
t
i
e
s
p
r
e
v
e
n
t
t
h
e
n
o
t
i
f
i
c
a
t
i
o
n
f
r
o
m
b
e
i
n
g
d
e
l
i
v
e
r
e
d
.
W
P 0
N x
_ 8
E 0
_ 3
I E
N 0
T 1
E 1
R 3
N T
E h
T
_ e
I a
N p
C p
A l
P i
A c
B a
L t
E i
o
n
d
o
e
s
n
o
t
h
a
v
e
t
h
e
i
n
t
e
r
n
e
t
a
c
c
e
s
s
c
a
p
a
b
i
l
i
t
y
.
W 0
P x
N 8
_ 0
E 3
_ E
N 0
O 1
T 1
I 4
F
I S
C e
A t
T t
I i
O n
N g
_ s
T p
Y r
P e
E v
_ e
D n
I t
S t
A h
B e
L n
E o
D t
i
f
i
c
a
t
i
o
n
t
y
p
e
f
r
o
m
b
e
i
n
g
d
e
l
i
v
e
r
e
d
.
W
P 0
N x
_ 8
E 0
_ 3
N E
O 0
T 1
I 1
F 5
I T
C h
A e
T s
I i
O z
N e
_ o
S f
I t
Z h
E e
n
o
t
i
f
i
c
a
t
i
o
n
c
o
n
t
e
n
t
i
s
t
o
o
l
a
r
g
e
.
W
P 0
N x
_ 8
E 0
_ 3
T E
A 0
G 1
_ 1
S 6
I T
Z h
E e
s
i
z
e
o
f
t
h
e
n
o
t
i
f
i
c
a
t
i
o
n
t
a
g
i
s
t
o
o
l
a
r
g
e
.
W
P 0
N x
_ 8
E 0
_ 3
A E
C 0
C 1
E 1
S 7
S T
_ h
D e
E n
N o
I t
E i
D f
i
c
a
t
i
o
n
p
l
a
t
f
o
r
m
d
o
e
s
n
'
t
h
a
v
e
a
p
p
r
o
p
r
i
a
t
e
p
r
i
v
i
l
e
g
e
o
n
r
e
s
o
u
r
c
e
s
.
W
P 0
N x
_ 8
E 0
_ 3
D E
U 0
P 1
L 1
I 8
C
A T
T h
E e
_ n
R o
E t
G i
I f
S i
T c
R a
A t
T i
I o
O n
N p
l
a
t
f
o
r
m
f
o
u
n
d
a
p
p
l
i
c
a
t
i
o
n
i
s
a
l
r
e
a
d
y
r
e
g
i
s
t
e
r
e
d
.
W
P 0
N x
_ 8
E 0
_ 3
O E
U 0
T 2
_ 0
O 0
F T
_ h
S e
E n
S o
S t
I i
O f
N i
c
a
t
i
o
n
p
l
a
t
f
o
r
m
h
a
s
r
u
n
o
u
t
o
f
p
r
e
s
e
n
t
a
t
i
o
n
l
a
y
e
r
s
e
s
s
i
o
n
s
.
W
P 0
N x
_ 8
E 0
_ 3
P E
O 0
W 2
E 0
R 1
_ T
S h
A e
V n
E o
t
i
f
i
c
a
t
i
o
n
p
l
a
t
f
o
r
m
r
e
j
e
c
t
s
i
m
a
g
e
d
o
w
n
l
o
a
d
r
e
q
u
e
s
t
d
u
e
t
o
s
y
s
t
e
m
i
n
p
o
w
e
r
s
a
v
e
m
o
d
e
.
W
P 0
N x
_ 8
E 0
_ 3
I E
M 0
A 2
G 0
E 2
_ T
N h
O e
T n
_ o
F t
O i
U f
N i
D c
_ a
I t
N i
_ o
C n
A p
C l
H a
E t
f
o
r
m
d
o
e
s
n
'
t
h
a
v
e
t
h
e
r
e
q
u
e
s
t
e
d
i
m
a
g
e
i
n
i
t
s
c
a
c
h
e
.
W
P 0
N x
_ 8
E 0
_ 3
A E
L 0
L 2
_ 0
U 3
R
L T
_ h
N e
O n
T o
_ t
C i
O f
M i
P c
L a
E t
T i
E o
D n
p
l
a
t
f
o
r
m
c
a
n
n
o
t
c
o
m
p
l
e
t
e
a
l
l
o
f
r
e
q
u
e
s
t
e
d
i
m
a
g
e
.
W
P 0
N x
_ 8
E 0
_ 3
I E
N 0
V 2
A 0
L 4
I A
D c
_ l
C o
L u
O d
U i
D m
_ a
I g
M e
A d
G o
E w
n
l
o
a
d
e
d
f
r
o
m
t
h
e
n
o
t
i
f
i
c
a
t
i
o
n
p
l
a
t
f
o
r
m
i
s
i
n
v
a
l
i
d
.
W
P 0
N x
_ 8
E 0
_ 3
N E
O 0
T 2
I 0
F 5
I N
C o
A t
T i
I f
O i
N c
_ a
I t
D i
_ o
M n
A I
T d
C p
H
E r
D o
v
i
d
e
d
a
s
f
i
l
t
e
r
i
s
m
a
t
c
h
e
d
w
i
t
h
w
h
a
t
t
h
e
n
o
t
i
f
i
c
a
t
i
o
n
p
l
a
t
f
o
r
m
m
a
i
n
t
a
i
n
s
.
W
P 0
N x
_ 8
E 0
_ 3
C E
A 0
L 2
L 0
B 6
A N
C o
K t
_ i
A f
L i
R c
E a
A t
D i
Y o
_ n
R c
E a
G l
I l
S b
T a
E c
R k
E i
D n
t
e
r
f
a
c
e
i
s
a
l
r
e
a
d
y
r
e
g
i
s
t
e
r
e
d
.
W
P 0
N x
_ 8
E 0
_ 3
T E
O 0
A 2
S 0
T 7
_ T
N o
O a
T s
I t
F N
I o
C t
A i
T f
I i
O c
N a
_ t
D i
R o
O
P n
P w
E a
D s
d
r
o
p
p
e
d
w
i
t
h
o
u
t
b
e
i
n
g
d
i
s
p
l
a
y
e
d
t
o
t
h
e
u
s
e
r.
W
P 0
N x
_ 8
E 0
_ 3
S E
T 0
O 2
R 0
A 8
G
E T
_ h
L e
O n
C o
K t
E i
D f
i
c
a
t
i
o
n
p
l
a
t
f
o
r
m
d
o
e
s
n
o
t
h
a
v
e
t
h
e
p
r
o
p
e
r
p
r
i
v
i
l
e
g
e
s
t
o
c
o
m
p
l
e
t
e
t
h
e
r
e
q
u
e
s
t
.
E
_ 0
M x
B 8
N 0
_ 5
C 4
O 8
N 2
T 0
E 1
X C
T o
_ n
N t
O e
T x
_ t
A i
C s
T n
I o
V t
A a
T c
E t
D
i
v
a
t
e
d
.
E
_ 0
M x
B 8
N 0
_ 5
B 4
A 8
D 2
_ 0
S 2
I B
M a
d
S
I
M
i
s
i
n
s
e
r
t
e
d
.
E
_ 0
M x
B 8
N 0
_ 5
D 4
A 8
T 2
A 0
_ 3
C R
L e
A q
S u
S e
_ s
N t
O e
T d
_ d
A a
V t
A a
I c
L l
A a
B s
L s
E i
s
n
o
t
a
v
a
i
l
a
b
l
e
.
E
_ 0
M x
B 8
N 0
_ 5
I 4
N 8
V 2
A 0
L 4
I A
D c
_ c
A e
C s
C s
E p
S o
S i
_
S n
T t
R n
I a
N m
G e
(
A
P
N
)
o
r
A
c
c
e
s
s
s
t
r
i
n
g
i
s
i
n
c
o
r
r
e
c
t
.
E
_ 0
M x
B 8
N 0
_ 5
M 4
A 8
X 2
_ 0
A 5
C M
T a
I
V x
A a
T c
E t
D i
_ v
C a
O t
N e
T d
E c
X o
T n
S t
e
x
t
s
h
a
v
e
r
e
a
c
h
e
d
.
E
_ 0
M x
B 8
N 0
_ 5
P 4
A 8
C 2
K 0
E 6
T D
_ e
S v
V i
C c
_ e
D i
E s
T i
A
C n
H p
E a
D c
k
e
t
d
e
t
a
c
h
s
t
a
t
e
.
E
_ 0
M x
B 8
N 0
_ 5
P 4
R 8
O 2
V 0
I 7
D P
E r
R o
_ v
N i
O d
T e
_ r
V i
I s
S n
I o
B t
L v
E i
s
i
b
l
e
.
E
_ 0
M x
B 8
N 0
_ 5
R 4
A 8
D 2
I 0
O 8
_ R
P a
O d
W i
E o
R i
_ s
O p
F o
F w
e
r
e
d
o
f
f.
E
_ 0
M x
B 8
N 0
_ 5
S 4
E 8
R 2
V 0
I 9
C M
E B
_ N
N s
O u
T b
_ s
A c
C r
T i
I p
V t
A i
T o
E n
D i
s
n
o
t
a
c
t
i
v
a
t
e
d
.
E
_ 0
M x
B 8
N 0
_ 5
S 4
I 8
M 2
_ 0
N A
O S
T I
_ M
I i
N s
S n
E o
R t
T i
E n
D s
e
r
t
e
d
.
E 0
_ x
M 8
B 0
N 5
_ 4
V 8
O 2
I 0
C B
E
_ V
C o
A i
L c
L e
_ c
I a
N l
_ l
P i
R n
O p
G r
R o
E g
S r
S e
s
s
.
E
_ 0
M x
B 8
N 0
_ 5
I 4
N 8
V 2
A 0
L C
I V
D i
_ s
C i
A b
C l
H e
E p
r
o
v
i
d
e
r
c
a
c
h
e
i
s
i
n
v
a
l
i
d
.
E
_ 0
M x
B 8
N 0
_ 5
N 4
O 8
T 2
_ 0
R D
E D
G e
I v
S i
T c
E e
R i
E s
D n
o
t
r
e
g
i
s
t
e
r
e
d
.
E
_ 0
M x
B 8
N 0
_ 5
P 4
R 8
O 2
V 0
I E
D P
E r
R o
S v
_ i
N d
O e
T r
_ s
F n
O o
U t
N f
D o
u
n
d
.
E
_ 0
M x
B 8
N 0
_ 5
P 4
I 8
N 2
_ 0
N F
O P
T i
_ n
S i
U s
P n
P o
O t
R s
T u
E p
D p
o
r
t
e
d
.
E
_ 0
M x
B 8
N 0
_ 5
P 4
I 8
N 2
_ 1
R 0
E P
Q i
U n
I i
R s
E r
D e
q
u
i
r
e
d
.
E
_ 0
M x
B 8
N 0
_ 5
P 4
I 8
N 2
_ 1
D 1
I
S P
A I
B N
L i
E s
D d
i
s
a
b
l
e
d
.
E
_ 0
M x
B 8
N 0
_ 5
F 4
A 8
I 2
L 1
U 2
R G
E e
n
e
r
i
c
F
a
i
l
u
r
e
.
E
_ 0
M x
B 8
N 0
_ 5
I 4
8
N 2
V 1
A 8
L
I P
D r
_ o
P f
R i
O l
F e
I i
L s
E i
n
v
a
l
i
d
.
E
_ 0
M x
B 8
N 0
_ 5
D 4
E 8
F 2
A 1
U 9
L D
T e
_ f
P a
R u
O l
F t
I p
L r
E o
_ f
E i
X l
I e
S e
T x
i
s
t
.
E
_ 0
M x
B 8
N 0
_ 5
S 4
M 8
S 2
_ 2
E 0
N S
C M
O S
D e
I n
N c
G o
_ d
N i
O n
T g
_ i
S s
U n
P o
P t
O s
R u
T p
E p
D o
r
t
e
d
.
E
_ 0
M x
B 8
N 0
_ 5
S 4
M 8
S 2
_ 2
F 1
I
L S
T M
E S
R f
_ i
N l
O t
T e
_ r
S i
U s
P n
P o
O t
R s
T u
E p
D p
o
r
t
e
d
.
E
_ 0
M x
B 8
N 0
_ 5
S 4
M 8
S 2
_ 2
I 2
N I
V n
A v
L a
I l
D i
_ d
M S
E M
M S
O m
R e
Y m
_ o
I r
N y
D i
E n
X d
e
x
i
s
u
s
e
d
.
E
_ 0
M x
B 8
N 0
_ 5
S 4
M 8
S 2
_ 2
L 3
A S
N M
G S
_ l
N a
O n
T g
_ u
S a
U g
P e
P i
O s
R n
T o
E t
D s
u
p
p
o
r
t
e
d
.
E
_ 0
M x
B 8
N 0
_ 5
S 4
M 8
S 2
_ 2
M 4
E S
M M
O S
R m
Y e
_ m
F o
A r
I y
L f
U a
R i
E l
u
r
e
o
c
c
u
r
r
e
d
.
E
_ 0
M x
B 8
N 0
_ 5
S 4
M 8
S 2
_ 2
N 5
E S
T M
W S
O n
R e
K t
_ w
T o
I r
M k
E t
O i
U m
T e
o
u
t
h
a
p
p
e
n
e
d
.
E
_ 0
M x
B 8
N 0
_ 5
S 4
M 8
S 2
_ 2
U 6
N U
K n
N k
O n
W o
N w
_ n
S S
M M
S S
C C
_ a
A d
D d
D
R r
E e
S s
S s
i
s
u
s
e
d
.
E
_ 0
M x
B 8
N 0
_ 5
S 4
M 8
S 2
_ 2
F 7
O S
R M
M S
A f
T o
_ r
N m
O a
T t
_ i
S s
U n
P o
P t
O s
R u
T p
E p
D o
r
t
e
d
.
E
_ 0
M x
B 8
N 0
_ 5
S 4
M 8
S 2
_ 2
O 8
P
E S
R M
A S
T o
I p
O e
N r
_ a
N t
O i
T o
_ n
A i
L s
L n
O o
W t
E a
D l
l
o
w
e
d
.
E
_ 0
M x
B 8
N 0
_ 5
S 4
M 8
S 2
_ 2
M 9
E D
M e
O v
R i
Y c
_ e
F S
U M
L S
L m
e
m
o
r
y
i
s
f
u
l
l.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 0
P 0
V 0
6 1
_ T
N h
O e
T I
_ P
I v
N 6
S p
T r
A o
L t
L o
E c
D o
l
i
s
n
o
t
i
n
s
t
a
l
l
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
N 0
O 0
T 0
_ 2
I T
N h
I e
T c
I o
A m
L p
I o
Z n
E e
D n
t
h
a
s
n
o
t
b
e
e
n
i
n
i
t
i
a
l
i
z
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
C 0
A 0
N 0
N 3
O T
T h
_ e
S r
T e
A q
R u
T i
_ r
S e
E d
R s
V e
I r
C v
E i
c
e
c
a
n
o
t
b
e
s
t
a
r
t
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
N 0
O 0
T 0
_ 4
L
I T
C h
E e
N P
S 2
E P
D p
r
o
t
o
c
o
l
i
s
n
o
t
l
i
c
e
n
s
e
d
t
o
r
u
n
o
n
t
h
i
s
O
S
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 0
N 0
V 1
A 0
L
I T
D h
_ e
G g
R r
A a
P p
H h
h
a
n
d
l
e
i
s
i
n
v
a
l
i
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
D 0
B 0
N 1
A 1
M T
E h
_ e
C G
H R
A a
N p
G h
E i
D n
g
d
a
t
a
b
a
s
e
n
a
m
e
h
a
s
c
h
a
n
g
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
D 0
U 0
P 1
L 2
I A
C g
A r
T a
E p
_ h
G w
R i
A t
P h
H t
h
e
s
a
m
e
I
D
a
l
r
e
a
d
y
e
x
i
s
t
s
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
G 0
R 0
A 1
P 3
H T
_ h
N e
O g
T r
_ a
R p
E h
A i
D s
Y n
o
t
r
e
a
d
y
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
G 0
R 0
A 1
P 4
H T
_ h
S e
H g
U r
T a
T p
I h
N i
G s
_ s
D h
O u
W t
N t
i
n
g
d
o
w
n
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
G 0
R 0
A 1
P 5
H T
_ h
I e
N g
_ r
U a
S p
E h
i
s
s
t
i
l
l
i
n
u
s
e
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 0
N 0
V 1
A 6
L T
I h
D e
_ g
D r
A a
T p
A h
B d
A a
S t
E a
b
a
s
e
i
s
c
o
r
r
u
p
t
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
T 0
O 0
O 1
_ 7
M T
A o
N o
Y m
_ a
A n
T y
T a
R t
I t
B r
U i
T b
E u
S t
e
s
h
a
v
e
b
e
e
n
u
s
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
C 0
O 1
N 0
N 3
E
C T
T h
I e
O c
N o
_ n
N n
O e
T c
_ t
F i
O o
U n
N c
D a
n
n
o
t
b
e
f
o
u
n
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
C 0
O 1
N 0
N 6
E T
C h
T e
_ p
S e
E e
L r
F a
t
t
e
m
p
t
e
d
t
o
c
o
n
n
e
c
t
t
o
i
t
s
e
l
f.
P
E 0
E x
R 8
_ 0
E 6
_ 3
A 0
L 1
R 0
E 7
A T
D h
Y e
_ p
L e
I e
S r
T i
E s
N
I a
N l
G r
e
a
d
y
l
i
s
t
e
n
i
n
g
f
o
r
c
o
n
n
e
c
t
i
o
n
s
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
N 0
O 1
D 0
E 8
_ T
N h
O e
T n
_ o
F d
O e
U w
N
D a
s
n
o
t
f
o
u
n
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
C 0
O 1
N 0
N 9
E T
C h
T e
I C
O o
N n
_ n
F e
A c
I t
L i
E o
D n
a
t
t
e
m
p
t
f
a
i
l
e
d
.
P 0
E x
E 8
R 0
_ 6
E 3
_ 0
C 1
O 0
N A
N
E T
C h
T e
I p
O e
N e
_ r
N c
O o
T n
_ n
A e
U c
T t
H i
E o
N n
T c
I o
C u
A l
T d
E n
D o
t
b
e
a
u
t
h
e
n
t
i
c
a
t
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
C 0
O 1
N 0
N B
E T
C h
T e
I c
O o
N n
_ n
R e
E c
F t
U i
S o
E n
D w
a
s
r
e
f
u
s
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
C 0
L 2
A 0
S 1
S T
I h
F e
I p
E e
R e
_ r
T n
O a
O m
_ e
L c
O l
N a
G s
s
i
f
i
e
r
i
s
t
o
o
l
o
n
g
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
T 0
O 2
O 0
_ 2
M T
A h
N e
Y m
_ a
I x
D i
E m
N u
T m
I n
T
I u
E m
S b
e
r
o
f
i
d
e
n
t
i
e
s
h
a
v
e
b
e
e
n
c
r
e
a
t
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
N 0
O 2
_ 0
K 3
E U
Y n
_ a
A b
C l
C e
E t
S o
S
a
c
c
e
s
s
a
k
e
y
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
G 0
R 2
O 0
U 4
P T
S h
_ e
E g
X r
I o
S u
T p
a
l
r
e
a
d
y
e
x
i
s
t
s
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
R 0
E 3
C 0
O 1
R
D T
_ h
N e
O r
T e
_ q
F u
O e
U s
N t
D e
d
r
e
c
o
r
d
c
o
u
l
d
n
o
t
b
e
f
o
u
n
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
D 0
A 3
T 0
A 2
B
A A
S c
E c
_ e
A s
C s
C t
E o
S t
S h
D e
E d
N a
I t
E a
D b
a
s
e
w
a
s
d
e
n
i
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
D 0
B 3
I 0
N 3
I T
T h
I e
A D
L a
I t
Z a
A b
T a
I s
O e
N c
_ o
F u
A l
I d
L n
E o
D t
b
e
i
n
i
t
i
a
l
i
z
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
M 0
A 3
X 0
_ 4
R T
E h
C e
O r
R e
D c
_ o
S r
I d
Z i
E s
_ t
E o
X o
C b
E
E i
D g
E .
D
P
E 0
E x
R 8
_ 0
E 6
_ 3
D 0
A 3
T 0
A 5
B T
A h
S e
E d
_ a
A t
L a
R b
E a
A s
D e
Y a
_ l
P r
R e
E a
S d
E y
N e
T x
i
s
t
s
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
D 0
A 3
0
T 6
A
B T
A h
S e
E d
_ a
N t
O a
T b
_ a
P s
R e
E c
S o
E u
N l
T d
n
o
t
b
e
f
o
u
n
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 0
D 4
E 0
N 1
T T
I h
T e
Y i
_ d
N e
O n
T t
_ i
F t
O y
U c
N o
D u
l
d
n
o
t
b
e
f
o
u
n
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
E 0
V 5
E 0
N 1
T T
_ h
H e
A e
N v
D e
L n
E t
_ h
N a
O n
T d
_ l
F e
O c
U o
N u
D l
d
n
o
t
b
e
f
o
u
n
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 0
N 6
V 0
A 1
L I
I n
D v
_ a
S l
E i
A d
R s
C e
H a
r
c
h
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 0
N 6
V 0
A 2
L T
I h
D e
_ s
A e
T a
T r
R c
I h
B a
U t
T t
E r
S i
b
u
t
e
s
a
r
e
i
n
v
a
l
i
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 0
N 7
V 0
I 1
T T
A h
T e
I i
O n
N v
_ i
N t
O i
T a
_ t
T i
R o
U n
S i
T
E s
D n
o
t
t
r
u
s
t
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
C 0
H 7
A 0
I 3
N T
_ h
T e
O c
O e
_ r
L t
O c
N h
G a
i
n
i
s
t
o
o
l
o
n
g
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 0
N 7
V 0
A 5
L
I T
D h
_ e
T t
I i
M m
E e
_ p
P e
E r
R i
I o
O d
D i
s
i
n
v
a
l
i
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
C 0
I 7
R 0
C 6
U A
L c
A i
R r
_ c
C u
H l
A a
I r
N c
_ e
D r
E t
T c
E h
C a
T i
E n
D w
a
s
d
e
t
e
c
t
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
C 0
E 8
R 0
T 1
_ T
S h
T e
O c
R e
E r
_ t
C s
O t
R o
R r
U e
P i
T s
E c
D o
r
r
u
p
t
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
N 1
O 0
_ 0
C 1
L T
O h
U e
D s
p
e
c
i
f
i
e
d
P
N
R
P
c
l
o
u
d
d
e
o
s
n
o
t
e
x
i
s
t
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
C 1
L 0
O 0
U 5
D T
_ h
N e
A c
M l
E o
_ u
A d
M n
B a
I m
G e
U i
O s
U a
S m
b
i
g
u
o
u
s
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 2
N 0
V 1
A 0
L T
I h
D e
_ r
R e
E c
C o
O r
R d
D i
s
i
n
v
l
a
i
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
N 2
O 0
T 2
_ 0
A N
U o
T t
H a
O u
R t
I h
Z o
E r
D i
z
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
P 2
A 0
S 2
S 1
W
O T
R h
D e
_ p
D a
O s
E s
S w
_ o
N r
O d
T d
_ o
M e
E s
E n
T o
_ t
P m
O e
L e
I t
C p
Y o
l
i
c
y
r
e
q
u
i
r
e
m
e
n
t
s
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
D 2
E 0
F 3
E 0
R
R T
E h
D e
_ r
V e
A c
L o
I r
D d
A v
T a
I l
O i
N d
a
t
i
o
n
h
a
s
b
e
e
n
d
e
f
e
r
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 2
N 0
V 4
A 0
L
I T
D h
_ e
G g
R r
O o
U u
P p
_ p
P r
R o
O p
P e
E r
R i
T e
I s
E a
S r
e
i
n
v
a
l
i
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 2
N 0
V 5
A 0
L T
I h
D e
_ p
P e
E e
E r
R n
_ a
N m
A e
M i
E s
i
n
v
a
l
i
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 2
N 0
V 6
A 0
L T
I h
D e
_ c
C l
L a
A s
S s
S i
I f
F i
I e
E r
R i
s
i
n
v
a
l
i
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 2
N 0
V 7
A 0
L
I T
D h
_ e
F f
R r
I i
E e
N n
D d
L l
Y y
_ n
N a
A m
M e
E i
s
i
n
v
a
l
i
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 2
N 0
V 7
A 1
L I
I n
D v
_ a
R l
O i
L d
E r
_ o
P l
R e
O p
P r
E o
R p
T e
Y r
t
y
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 2
N 0
V 7
A 2
L I
I n
D v
_ a
C l
L i
A d
S c
S l
I a
F s
I s
E i
R f
_ i
P e
R r
O p
P r
E o
R t
T o
Y p
e
r
y
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 2
N 0
V 8
A 0
L I
I n
D v
_ l
R a
E i
C d
O r
R e
D c
_ o
E r
X d
P e
I x
R p
A i
T r
I a
O t
N i
o
n
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 2
N 0
V 8
A 1
L I
I n
D v
_ l
C a
R i
E d
D c
E r
N e
T d
I e
A n
L t
_ i
I a
N l
F i
O n
f
o
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 2
N 0
V 8
A 2
L I
I n
D v
_ a
C l
R i
E d
D c
E r
N e
T d
I e
A n
L t
i
a
l.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 2
N 0
V 8
A 3
L
I I
D n
_ v
R a
E l
C i
O d
R r
D e
_ c
S o
I r
Z d
E s
i
z
e
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
U 2
N 0
S 9
U 0
P U
P n
O s
R u
T p
E p
D o
_ r
V t
E e
R
S d
I v
O e
N r
s
i
o
n
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
G 2
R 0
O 9
U 1
P T
_ h
N e
O g
T r
_ o
R u
E p
A i
D s
Y n
o
t
r
e
a
d
y
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
G 2
R 0
O 9
U 2
P
_ T
I h
N e
_ g
U r
S o
E u
p
i
s
s
t
i
l
l
i
n
u
s
e
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 2
N 0
V 9
A 3
L T
I h
D e
_ g
G r
R o
O u
U p
P i
s
i
n
v
a
l
i
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
N 2
O 0
_ 9
M 4
E N
M o
B m
E e
R m
S b
_ e
F r
O s
U w
N e
D r
e
f
o
u
n
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
N 2
O 0
_ 9
M 5
E T
M h
B e
E r
R e
_ a
C
O r
N e
N n
E o
C m
T e
I m
O b
N e
S r
c
o
n
n
e
c
t
i
o
n
s
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
U 2
N 0
A 9
B 6
L U
E n
_ a
T b
O l
_ e
L t
I o
S l
T i
E s
N t
e
n
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 2
D 0
E A
N 0
T
I T
T h
Y e
_ i
D d
E e
L n
E t
T i
E t
D y
d
o
e
s
n
o
t
e
x
i
s
t
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
S 2
E 0
R A
V 1
I T
C h
E e
_ s
N
O e
T r
_ v
A i
V c
A e
I i
L s
A n
B o
L t
E a
v
a
i
l
i
b
l
e
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
C 6
O 0
N 0
T 1
A T
C h
T e
_ c
N o
O n
T t
_ a
F c
O t
U c
N o
D u
l
d
n
o
t
b
e
f
o
u
n
d
.
P
E 0
E x
R 0
_ 0
S 6
_ 3
G 0
R 0
A 0
P 1
H T
_ h
D e
A g
T r
A a
_ p
C h
R d
E a
A t
T a
E w
D a
s
c
r
e
a
t
e
d
.
P
E 0
E x
R 0
_ 0
S 6
_ 3
N 0
O 0
_ 0
E 2
V
E T
N h
T e
_ r
D e
A i
T s
A n
o
t
m
o
r
e
e
v
e
n
t
d
a
t
a
.
P
E 0
E x
R 0
_ 0
S 6
_ 3
A 2
L 0
R 0
E 0
A T
D h
Y e
_ g
C r
O a
N p
N h
E i
C s
T a
E l
D r
e
a
d
y
c
o
n
n
e
c
t
.
P
E 0
E x
R 0
_ 0
S 6
_ 3
S 6
U 0
B 0
S 0
C T
R h
I e
P s
T u
I b
O s
N c
_ r
E i
X p
I t
S i
T o
S n
a
l
r
e
a
d
y
e
x
i
s
t
s
.
P
E 0
E x
R 0
_ 0
S 6
_ 3
N 0
O 0
_ 0
C 5
O N
N o
N c
E o
C n
T n
I e
V c
I t
T i
Y v
i
t
y
.
P
E 0
E x
R 0
_ 0
S 6
_ 3
A 0
L 0
R 0
E 6
A A
D l
Y r
_ e
A a
_ d
M y
E a
M m
B e
E m
R b
e
r.
P
E 0
E x
R 8
_ 0
E 6
_ 3
C 4
A 0
N 0
N 1
O T
T h
_ e
C p
O e
N e
V r
E n
R a
T m
_ e
P c
E o
E u
R l
_ d
N n
A o
M t
E b
e
c
o
n
v
e
r
t
e
d
t
o
a
D
N
S
p
n
r
p
n
a
m
e
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 4
N 0
V 0
A 2
L I
I n
D v
_ a
P l
E i
E d
R p
_ e
H e
O r
S h
T o
_ s
N t
A n
M a
E m
e
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
N 4
O 0
_ 0
M 3
O
R N
E o
m
o
r
e
d
a
t
a
c
o
u
l
d
b
e
f
o
u
n
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
P 4
N 0
R 0
P 5
_ T
D h
U e
P e
L x
I i
C s
A t
T i
E n
_ g
P p
E e
E e
R r
_ n
N a
A m
M e
E i
s
a
l
r
e
a
d
y
r
e
g
i
s
t
e
r
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 7
N 0
V 0
I 0
T T
E h
_ e
C a
A p
N p
C i
E n
L v
L i
E t
D
e
r
e
q
u
e
s
t
w
a
s
c
a
n
c
e
l
d
b
y
t
h
e
u
s
e
r.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 7
N 0
V 0
I 1
T N
E o
_ r
R e
E s
S p
P o
O s
N e
S o
E t
_ t
N
O h
T e
_ i
A n
V v
A i
I t
L e
A w
B a
L s
E r
e
c
e
i
v
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
N 7
O 0
T 0
_ 3
S U
I s
G e
N r
E i
D s
_ n
I o
N t
s
i
g
e
d
i
n
t
o
s
e
r
v
e
r
l
e
s
s
p
r
e
s
e
n
c
e
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
P 7
R 0
I 0
V 4
A T
C h
Y e
_ u
D s
E e
C r
L d
I e
N c
E l
D i
n
d
e
d
t
h
e
p
r
i
v
a
c
y
p
o
l
i
c
y
p
r
o
m
p
t
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
T 7
I 0
M 0
E 5
O A
U t
T i
m
e
o
u
t
o
c
c
u
r
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
I 7
N 0
V 0
A 7
L
I T
D h
_ e
A a
D d
D d
R r
E e
S s
S s
i
s
i
n
v
a
l
i
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
F 7
W 0
_ 0
E 8
X A
C r
E e
P q
T u
I i
O r
N e
_ d
D f
I i
S r
A e
B w
L a
E l
D l
e
x
c
e
p
t
i
o
n
i
s
d
i
s
a
b
l
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
F 7
W 0
_ 0
B 9
L T
O h
C e
K s
E e
D r
_ v
B i
Y c
_ e
P i
O s
L b
I l
C
Y o
c
k
b
y
a
f
i
r
e
w
a
l
l
p
o
l
i
c
y
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
F 7
W 0
_ 0
B A
L F
O i
C r
K e
E w
D a
_ l
B l
Y e
_ x
S c
H e
I p
E t
L i
D o
S n
_ s
U
P a
r
e
d
i
s
a
b
l
e
d
.
P
E 0
E x
R 8
_ 0
E 6
_ 3
F 7
W 0
_ 0
D B
E T
C h
L e
I u
N s
E e
D r
d
e
c
l
i
n
d
e
d
t
o
e
n
a
b
l
e
t
h
e
f
i
r
e
w
a
l
l
e
x
c
e
p
t
i
o
n
s
.
E
_ 0
B x
L 8
U 0
E 6
T 5
O 0
O 0
T 0
H 1
_ T
A h
T e
T a
_ t
I t
N r
V i
A b
L u
I t
D e
_ h
H a
A n
N d
D l
L e
E g
i
v
e
n
w
a
s
n
o
t
v
a
l
i
d
o
n
t
h
i
s
s
e
r
v
e
r.
E
_ 0
B x
L 8
U 0
E 6
T 5
O 0
O 0
T 0
H 2
_ T
A h
T e
T a
_ t
R t
E r
A i
D b
_ u
N t
O e
T c
_
P a
E n
R n
M o
I t
T b
T e
E r
D e
a
d
.
E
_ 0
B x
L 8
U 0
E 6
T 5
O 0
O 0
T 0
H 3
_ T
A h
T e
T a
_ t
W t
R r
I i
T b
E u
_ t
N e
O c
T a
_ n
P n
E o
R t
M b
I e
T w
T r
E i
D t
t
e
n
.
E
_ 0
B x
L 8
U 0
E 6
T 5
O 0
O 0
T 0
H 4
_ T
A h
T e
T a
_ t
I t
N r
V i
A b
L u
I t
D e
_ P
P D
D U
U w
a
s
i
n
v
a
l
i
d
.
E
_ 0
B x
L 8
U 0
E 6
T 5
O 0
O 0
T 0
H 5
_ T
A h
T e
T a
_ t
I t
N r
S i
U b
F u
F t
I e
C r
I e
E q
N u
T i
_ r
A e
U s
T a
H u
E t
N h
T e
I n
C t
A i
T c
I a
O t
N i
o
n
b
e
f
o
r
e
i
t
c
a
n
b
e
r
e
a
d
o
r
w
r
i
t
t
e
n
.
E
_ 0
B x
L 8
U 0
E 6
T 5
O 0
O 0
T 0
H 6
_ A
A t
T t
T r
_ i
R b
E u
Q t
U e
E s
S e
T r
_ v
N e
O r
T d
_ o
S e
U s
P n
P o
O t
R s
T u
E p
D p
o
r
t
t
h
e
r
e
q
u
e
s
t
r
e
c
e
i
v
e
d
f
r
o
m
t
h
e
c
l
i
e
n
t
.
E
_ 0
B x
L 8
U 0
E 6
T 5
O 0
O 0
T 0
H 7
_ O
A f
T f
T s
_ e
I t
N s
V p
A
L e
I c
D i
_ f
O i
F e
F d
S w
E a
T s
p
a
s
t
t
h
e
e
n
d
o
f
t
h
e
a
t
t
r
i
b
u
t
e
.
E
_ 0
B x
L 8
U 0
E 6
T 5
O 0
O 0
T 0
H 8
_ T
A h
T e
T a
_
I t
N t
S r
U i
F b
F u
I t
C e
I r
E e
N q
T u
_ i
A r
U e
T s
H a
O u
R t
I h
Z o
A r
T i
I z
O a
N t
i
o
n
b
e
f
o
r
e
i
t
c
a
n
b
e
r
e
a
d
o
r
w
r
i
t
t
e
n
.
E
_ 0
B x
L 8
U 0
E 6
T 5
O 0
O 0
T 0
H 9
_ T
A o
T o
T m
_ a
P n
R y
E p
P r
A e
R p
E a
_ r
Q e
U w
E r
U i
E t
_ e
F s
U h
L a
L v
e
b
e
e
n
q
u
e
u
e
d
.
E
_ 0
B x
L 8
U 0
E 6
T 5
O 0
O 0
T 0
H A
_ N
A o
T a
T t
_ t
A r
T i
T b
R u
I t
B e
U f
T o
E u
_ n
N d
O w
T i
_ t
F h
O i
U n
N t
D h
e
g
i
v
e
n
a
t
t
r
i
b
u
t
e
h
a
n
d
l
e
r
a
n
g
e
.
E
_ 0
B x
L 8
U 0
E 6
T 5
O 0
O 0
T 0
H B
_ T
A h
T e
T a
_ t
A t
T r
T i
R b
I u
B t
U e
T c
E a
_ n
N n
O o
T t
_ b
L e
O r
N e
G a
d
o
r
w
r
i
t
t
e
n
u
s
i
n
g
t
h
e
R
e
a
d
B
l
o
b
R
e
q
u
e
s
t
.
E
_ 0
B x
L 8
U 0
E 6
T 5
O 0
O 0
T 0
H C
_ T
A h
T e
T E
_ n
I c
N r
S y
U p
F t
F
I i
C o
I n
E K
N e
T y
_ S
E i
N z
C e
R u
Y s
P e
T d
I f
O o
N r
_ e
K n
E c
Y r
_ y
S p
I t
Z i
E n
g
t
h
i
s
l
i
n
k
i
s
i
n
s
u
f
f
i
c
i
e
n
t
.
E
_ 0
B x
L 8
U 0
E 6
T 5
O 0
O 0
T 0
H D
_
A T
T h
T e
_ a
I t
N t
V r
A i
L b
I u
D t
_ e
A v
T a
T l
R u
I e
B l
U e
T n
E g
_ t
V h
A i
L s
U i
E n
_ v
L a
E l
N i
G d
T f
H o
r
t
h
e
o
p
e
r
a
t
i
o
n
.
E
_ 0
B x
L 8
U 0
E 6
T 5
O 0
O 0
T 0
H E
_ T
A h
T e
T a
_ t
U t
N r
L i
I b
K u
E t
L e
Y r
e
q
u
e
s
t
t
h
a
t
w
a
s
r
e
q
u
e
s
t
e
d
h
a
s
e
n
c
o
u
n
t
e
r
e
d
a
n
e
r
r
o
r
t
h
a
t
w
a
s
u
n
l
i
k
e
l
y
,
a
n
d
t
h
e
r
e
f
o
r
e
c
o
u
l
d
n
o
t
b
e
c
o
m
p
l
e
t
e
d
a
s
r
e
q
u
e
s
t
e
d
.
E
_ 0
B x
L 8
U 0
E 6
T 5
O 0
O 0
T 0
H F
_ T
A h
T e
T a
_ t
I t
N r
S i
U
F b
F u
I t
C e
I r
E e
N q
T u
_ i
E r
N e
C s
R e
Y n
P c
T r
I y
O p
N t
i
o
n
b
e
f
o
r
e
i
t
c
a
n
b
e
r
e
a
d
o
r
w
r
i
t
t
e
n
.
E
_ 0
B x
L 8
U 0
E 6
T 5
O 0
O 0
T 1
H 0
_
A T
T h
T e
_ a
U t
N t
S r
U i
P b
P u
O t
R e
T t
E y
D p
_ e
G i
R s
O n
U o
P t
_ a
T s
Y u
P p
E p
o
r
t
e
d
g
r
o
u
p
i
n
g
a
t
t
r
i
b
u
t
e
a
s
d
e
f
i
n
e
d
b
y
a
h
i
g
h
e
r
l
a
y
e
r
s
p
e
c
i
f
i
c
a
t
i
o
n
.
E
_ 0
B x
L 8
U 0
E 6
T 5
O 0
O 0
T 1
H 1
_
A I
T n
T s
_ u
I f
N f
S i
U c
F i
F e
I n
C t
I R
E e
N s
T o
_ u
R r
E c
S e
O s
U t
R o
C c
E o
S m
p
l
e
t
e
t
h
e
r
e
q
u
e
s
t
.
E
_ 0
B x
L 8
U 0
E 6
T 5
O 1
O 0
T 0
H 0
_
A A
T n
T e
_ r
U r
N o
K r
N t
O h
W a
N t
_ l
E i
R e
R s
O i
R n
t
h
e
r
e
s
e
r
v
e
d
r
a
n
g
e
h
a
s
b
e
e
n
r
e
c
e
i
v
e
d
.
Requirements
Header
Win
erro
r.h
See also
C
O
M
E
r
r
o
r
C
o
d
e
s
COM Error Codes (UI, Audio, DirectX, Codec)
1/7/2020 • 11 minutes to read • Edit Online
The following table provides a list of error codes used by COM -based APIs.
If you are experiencing difficulty with an application you are installing or running, contact customer support for the
software that is displaying the error message. To obtain support for a Microsoft product, go to
https://support.microsoft.com.
U
I 0
_ x
E 8
_ 0
C 2
R A
E 0
A 0
T 0
E 1
_ T
F h
A e
I o
L b
E j
D e
c
t
c
o
u
l
d
n
o
t
b
e
c
r
e
a
t
e
d
.
U 0
I x
_ 8
E 0
_ 2
S A
H 0
U 0
T 0
D 2
O
W S
N h
_ u
C t
A d
L o
L w
E n
D w
a
s
a
l
r
e
a
d
y
c
a
l
l
e
d
o
n
t
h
i
s
o
b
j
e
c
t
o
r
t
h
e
o
b
j
e
c
t
t
h
a
t
o
w
n
s
i
t
.
U
I 0
_ x
E 8
_ 0
I 2
L A
L 0
E 0
G 0
A 3
L T
_ h
R i
E s
E m
N e
T t
R h
A o
N d
C c
Y a
n
n
o
t
b
e
c
a
l
l
e
d
d
u
r
i
n
g
t
h
i
s
t
y
p
e
o
f
c
a
l
l
b
a
c
k
.
U
I 0
_ x
E 8
_ 0
O 2
B A
J 0
E 0
C 0
T 4
_ T
S h
E i
A s
L o
E b
D j
e
c
t
h
a
s
b
e
e
n
s
e
a
l
e
d
,
s
o
t
h
i
s
c
h
a
n
g
e
i
s
n
o
l
o
n
g
e
r
a
l
l
o
w
e
d
.
U
I 0
_ x
E 8
_ 0
V 2
A A
L 0
U 0
E 0
_ 5
N
O T
T h
_ e
S r
E e
T q
u
e
s
t
e
d
v
a
l
u
e
w
a
s
n
e
v
e
r
s
e
t
.
U
I 0
_ x
E 8
_ 0
V 2
A A
L 0
U 0
E 0
_ 6
N T
O h
T e
_ r
D e
E q
T u
E e
R s
M t
I e
N d
E v
D a
l
u
e
c
a
n
n
o
t
b
e
d
e
t
e
r
m
i
n
e
d
.
U
I 0
_ x
E 8
_ 0
I 2
N A
V 0
A 0
L 0
I 7
D A
_ c
O a
U l
T l
P b
U a
T c
k
r
e
t
u
r
n
e
d
a
n
i
n
v
a
l
i
d
o
u
t
p
u
t
p
a
r
a
m
e
t
e
r.
U
I 0
_ x
E 8
_ 0
B 2
O A
O 0
L 0
E 0
A 8
N A
_ c
E a
X l
P l
E b
C a
T c
E k
D
r
e
t
u
r
n
e
d
a
s
u
c
c
e
s
s
c
o
d
e
o
t
h
e
r
t
h
a
n
S
_
O
K
o
r
S
_
F
A
L
S
E
.
U
I 0
_ x
E 8
_ 0
D 2
I A
F 0
F 0
E 0
R 9
E
N A
T p
_ a
O r
W a
N m
E e
R t
e
r
t
h
a
t
s
h
o
u
l
d
b
e
o
w
n
e
d
b
y
t
h
i
s
o
b
j
e
c
t
i
s
o
w
n
e
d
b
y
a
d
i
f
f
e
r
e
n
t
o
b
j
e
c
t
.
U
I 0
_ x
E 8
_ 0
A 2
M A
B 0
I 0
G 0
U A
O M
U o
S r
_ e
M t
A h
T a
C n
H o
n
e
i
t
e
m
m
a
t
c
h
e
d
t
h
e
s
e
a
r
c
h
c
r
i
t
e
r
i
a
.
U
I 0
_ x
E 8
_ 0
F 2
P A
_ 0
O 0
V 0
E B
R A
F f
L l
O o
W a
t
i
n
g
-
p
o
i
n
t
o
v
e
r
f
l
o
w
o
c
c
u
r
r
e
d
.
U
I 0
_ x
E 8
_ 0
W 2
R A
O 0
N 0
G 0
_ C
T T
H h
R i
E s
A m
D e
t
h
o
d
c
a
n
o
n
l
y
b
e
c
a
l
l
e
d
f
r
o
m
t
h
e
t
h
r
e
a
d
t
h
a
t
c
r
e
a
t
e
d
t
h
e
o
b
j
e
c
t
.
U
I 0
_ x
E 8
_ 0
S 2
T A
O 0
R 1
Y 0
B 1
O T
A h
R e
D s
_ t
A o
C r
T y
I
V b
E o
a
r
d
i
s
c
u
r
r
e
n
t
l
y
i
n
t
h
e
s
c
h
e
d
u
l
e
.
U
I 0
_ x
E 8
_ 0
S 2
T A
O 0
R 1
Y 0
B 2
O T
A h
R e
D s
_ t
N o
O r
T y
_ b
P
L o
A a
Y r
I d
N i
G s
n
o
t
p
l
a
y
i
n
g
.
U
I 0
_ x
E 8
_ 0
S 2
T A
A 0
R 1
T 0
_ 3
K T
E h
Y e
F s
R t
A a
M r
E t
_ k
A e
F y
T f
E r
R a
_ m
E e
N m
D i
g
h
t
o
c
c
u
r
a
f
t
e
r
t
h
e
e
n
d
k
e
y
f
r
a
m
e
.
U
I 0
_ x
E 8
_ 0
E 2
N A
D 0
_ 1
K 0
E 4
Y I
F t
R m
A i
M g
E h
_ t
N n
O o
T t
_ b
D e
E p
T o
E s
R
M s
I i
N b
E l
D e
t
o
d
e
t
e
r
m
i
n
e
t
h
e
e
n
d
k
e
y
f
r
a
m
e
t
i
m
e
w
h
e
n
t
h
e
s
t
a
r
t
k
e
y
f
r
a
m
e
i
s
r
e
a
c
h
e
d
.
U
I 0
_ x
E 8
_ 0
L 2
O A
O 0
P 1
S 0
_ 5
O T
V w
E o
R r
L e
A p
P e
a
t
e
d
p
o
r
t
i
o
n
s
o
f
a
s
t
o
r
y
b
o
a
r
d
m
i
g
h
t
o
v
e
r
l
a
p
.
U
I 0
_ x
E 8
_ 0
T 2
R A
A 0
N 1
S 0
I 6
T T
I h
O e
N t
_ r
A a
L n
R s
E i
A t
D i
Y o
_ n
U h
S a
E s
D a
l
r
e
a
d
y
b
e
e
n
a
d
d
e
d
t
o
a
s
t
o
r
y
b
o
a
r
d
.
U
I 0
_ x
E 8
_ 0
T 2
R A
A 0
N 1
S 0
I 7
T T
I h
O e
N t
_ r
N a
O n
T s
_ i
I t
N i
_ o
S n
T h
O
R a
Y s
B n
O o
A t
R b
D e
e
n
a
d
d
e
d
t
o
a
s
t
o
r
y
b
o
a
r
d
.
U
I 0
_ x
E 8
_ 0
T 2
R A
A 0
N 1
S 0
I 8
T T
I h
O e
N t
_ r
E a
C n
L s
I i
P t
S i
E
D o
n
m
i
g
h
t
e
c
l
i
p
s
e
t
h
e
b
e
g
i
n
n
i
n
g
o
f
a
n
o
t
h
e
r
t
r
a
n
s
i
t
i
o
n
i
n
t
h
e
s
t
o
r
y
b
o
a
r
d
.
U
I 0
_ x
E 8
_ 0
T 2
I A
M 0
E 1
_ 0
B 9
E T
F h
O e
R g
E i
_ v
L e
A n
S t
T i
_ m
U e
P i
D s
A e
T a
E r
l
i
e
r
t
h
a
n
t
h
e
t
i
m
e
p
a
s
s
e
d
t
o
t
h
e
l
a
s
t
u
p
d
a
t
e
.
U
I 0
_ x
E 8
_ 0
T 2
I A
M 0
E 1
R 0
_ A
C T
L h
I i
E s
N c
T l
_ i
A e
L n
R t
E i
A s
D a
Y l
_ r
C
O e
N a
N d
E y
C c
T o
E n
D n
e
c
t
e
d
t
o
a
t
i
m
e
r.
U
I 0
_ x
E 8
_ 0
I 2
N A
V 0
A 1
L 0
I B
D T
_ h
D e
I p
M a
E s
N s
S e
I d
O d
N i
m
e
n
s
i
o
n
i
s
i
n
v
a
l
i
d
o
r
d
o
e
s
n
o
t
m
a
t
c
h
t
h
e
o
b
j
e
c
t
'
s
d
i
m
e
n
s
i
o
n
.
U
I 0
_ x
E 8
_ 0
P 2
R A
I 0
M 1
I 0
T C
I
V T
E h
_ e
O a
U d
T d
_ e
O d
F p
_ r
B i
O m
U i
N t
D i
S v
e
b
e
g
i
n
s
a
t
o
r
b
e
y
o
n
d
t
h
e
d
u
r
a
t
i
o
n
o
f
t
h
e
i
n
t
e
r
p
o
l
a
t
o
r.
U
I 0
_ x
E 8
_ 0
W 2
I A
N 0
D 2
O 0
W 1
_ T
C h
L e
O o
S p
E e
D r
a
t
i
o
n
c
a
n
n
o
t
b
e
c
o
m
p
l
e
t
e
d
b
e
c
a
u
s
e
t
h
e
w
i
n
d
o
w
i
s
b
e
i
n
g
c
l
o
s
e
d
.
E
_ 0
A x
U 8
D 0
I 6
O 6
_ 0
E 0
N 0
G 1
I P
N o
E r
_ t
N C
O
D l
E s
_ c
N o
O u
T l
_ d
F n
O o
U t
N f
D i
n
d
a
n
a
u
d
i
o
e
n
g
i
n
e
n
o
d
e
e
x
p
o
s
e
d
b
y
a
m
i
n
i
p
o
r
t
d
r
i
v
e
r
c
l
a
i
m
i
n
g
s
u
p
p
o
r
t
f
o
r
I
M
i
n
i
p
o
r
t
A
u
d
i
o
E
n
g
i
n
e
N
o
d
e
.
D
X 0
G x
I 0
_ 8
S 7
T A
A 0
T 0
U 0
S 1
_
O T
C h
C e
L P
U r
D e
E s
D e
n
t
o
p
e
r
a
t
i
o
n
w
a
s
i
n
v
i
s
i
b
l
e
t
o
t
h
e
u
s
e
r.
D
X 0
G x
I 0
_ 8
S 7
T A
A 0
T 0
U 0
S 2
_
C T
L h
I e
P P
P r
E e
D s
e
n
t
o
p
e
r
a
t
i
o
n
w
a
s
p
a
r
t
i
a
l
l
y
i
n
v
i
s
i
b
l
e
t
o
t
h
e
u
s
e
r.
D
X 0
G x
I 0
_ 8
S 7
T A
A 0
T 0
U 0
S 4
_ T
N h
O e
_ d
R r
E i
D v
I e
R r
E i
C s
T r
I e
O q
N u
e
s
t
i
n
g
t
h
a
t
t
h
e
D
X
G
I
r
u
n
t
i
m
e
n
o
t
u
s
e
s
h
a
r
e
d
r
e
s
o
u
r
c
e
s
t
o
c
o
m
m
u
n
i
c
a
t
e
w
i
t
h
t
h
e
D
e
s
k
t
o
p
W
i
n
d
o
w
M
a
n
a
g
e
r.
D
X 0
G x
I 0
_ 8
S 7
T A
A 0
T 0
U 0
S 5
_ T
N h
O e
_ P
D r
E e
S s
K e
T n
O t
P o
_ p
A e
C r
C a
E t
S i
S o
n
w
a
s
n
o
t
v
i
s
i
b
l
e
b
e
c
a
u
s
e
t
h
e
W
i
n
d
o
w
s
s
e
s
s
i
o
n
h
a
s
s
w
i
t
c
h
e
d
t
o
a
n
o
t
h
e
r
d
e
s
k
t
o
p
(
f
o
r
e
x
a
m
p
l
e
,
c
t
r
l
-
a
l
t
-
d
e
l
)
.
D
X 0
G x
I 0
_ 8
S 7
T A
A 0
T 0
U 0
S 6
_ T
G h
R e
A P
P r
H e
I s
C
S e
_ n
V t
I o
D p
P e
N r
_ a
S t
O i
U o
R n
C w
E a
_ s
I n
N o
_ t
U v
S i
E s
i
b
l
e
b
e
c
a
u
s
e
t
h
e
t
a
r
g
e
t
m
o
n
i
t
o
r
w
a
s
b
e
i
n
g
u
s
e
d
f
o
r
s
o
m
e
o
t
h
e
r
p
u
r
p
o
s
e
.
D
X 0
G x
I 0
_ 8
S 7
T A
A 0
T 0
U 0
S 7
_ T
M h
O e
D P
E r
_ e
C s
H e
A n
N t
G o
E
D p
e
r
a
t
i
o
n
w
a
s
n
o
t
v
i
s
i
b
l
e
b
e
c
a
u
s
e
t
h
e
d
i
s
p
l
a
y
m
o
d
e
c
h
a
n
g
e
d
.
D
X
G
I
w
i
l
l
h
a
v
e
r
e
-
a
t
t
e
m
p
t
e
d
t
h
e
p
r
e
s
e
n
t
a
t
i
o
n
.
D
X 0
G x
I 0
_ 8
S 7
T A
A 0
T 0
U 0
S 8
_ T
M
O h
D e
E P
_ r
C e
H s
A e
N n
G t
E o
_ p
I e
N r
_ a
P t
R i
O o
G n
R w
E a
S s
S n
o
t
v
i
s
i
b
l
e
b
e
c
a
u
s
e
a
n
o
t
h
e
r
D
i
r
e
c
t
3
D
d
e
v
i
c
e
w
a
s
a
t
t
e
m
p
t
i
n
g
t
o
t
a
k
e
f
u
l
l
s
c
r
e
e
n
m
o
d
e
a
t
t
h
e
t
i
m
e
.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 0
_ 1
I
N T
V h
A e
L a
I p
D p
_ l
C i
A c
L a
L t
i
o
n
m
a
d
e
a
c
a
l
l
t
h
a
t
i
s
i
n
v
a
l
i
d
.
E
i
t
h
e
r
t
h
e
p
a
r
a
m
e
t
e
r
s
o
f
t
h
e
c
a
l
l
o
r
t
h
e
s
t
a
t
e
o
f
s
o
m
e
o
b
j
e
c
t
w
a
s
i
n
c
o
r
r
e
c
t
.
E
n
a
b
l
e
t
h
e
D
3
D
d
e
b
u
g
l
a
y
e
r
i
n
o
r
d
e
r
t
o
s
e
e
d
e
t
a
i
l
s
v
i
a
d
e
b
u
g
m
e
s
s
a
g
e
s
.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 0
_ 2
N T
O h
T e
_ o
F b
O j
U e
N c
D t
w
a
s
n
o
t
f
o
u
n
d
.
I
f
c
a
l
l
i
n
g
I
D
X
G
I
F
a
c
t
o
r
y
::
E
n
u
m
A
d
a
p
t
e
s
,
t
h
e
r
e
i
s
n
o
a
d
a
p
t
e
r
w
i
t
h
t
h
e
s
p
e
c
i
f
i
e
d
o
r
d
i
n
a
l.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 0
_ 3
M T
O h
R e
E c
_ a
D l
A l
T e
A r
d
i
d
n
o
t
s
u
p
p
l
y
a
s
u
f
f
i
c
i
e
n
t
l
y
l
a
r
g
e
b
u
f
f
e
r.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 0
_ 4
U T
N h
S e
U s
P p
P e
O c
R i
T f
E i
D e
d
d
e
v
i
c
e
i
n
t
e
r
f
a
c
e
o
r
f
e
a
t
u
r
e
l
e
v
e
l
i
s
n
o
t
s
u
p
p
o
r
t
e
d
o
n
t
h
i
s
s
y
s
t
e
m
.
D 0
X x
G 8
I 8
_ 7
E A
R 0
R 0
O 0
R 5
_
D T
E h
V e
I G
C P
E U
_ d
R e
E v
M i
O c
V e
E i
D n
s
t
a
n
c
e
h
a
s
b
e
e
n
s
u
s
p
e
n
d
e
d
.
U
s
e
G
e
t
D
e
v
i
c
e
R
e
m
o
v
e
d
R
e
a
s
o
n
t
o
d
e
t
e
r
m
i
n
e
t
h
e
a
p
p
r
o
p
r
i
a
t
e
a
c
t
i
o
n
.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 0
_ 6
D T
E h
V e
I G
C P
E U
_ w
H i
U l
N l
G n
o
t
r
e
s
p
o
n
d
t
o
m
o
r
e
c
o
m
m
a
n
d
s
,
m
o
s
t
l
i
k
e
l
y
b
e
c
a
u
s
e
o
f
a
n
i
n
v
a
l
i
d
c
o
m
m
a
n
d
p
a
s
s
e
d
b
y
t
h
e
c
a
l
l
i
n
g
a
p
p
l
i
c
a
t
i
o
n
.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 0
_ 7
D T
E h
V e
I G
C P
E U
_ w
R i
E l
S l
E n
T o
t
r
e
s
p
o
n
d
t
o
m
o
r
e
c
o
m
m
a
n
d
s
,
m
o
s
t
l
i
k
e
l
y
b
e
c
a
u
s
e
s
o
m
e
o
t
h
e
r
a
p
p
l
i
c
a
t
i
o
n
s
u
b
m
i
t
t
e
d
i
n
v
a
l
i
d
c
o
m
m
a
n
d
s
.
T
h
e
c
a
l
l
i
n
g
a
p
p
l
i
c
a
t
i
o
n
s
h
o
u
l
d
r
e
-
c
r
e
a
t
e
t
h
e
d
e
v
i
c
e
a
n
d
c
o
n
t
i
n
u
e
.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 0
_ A
W T
A h
S e
_ G
S P
T U
I w
L a
L s
_ b
D u
R s
A y
W a
I t
N t
G h
e
m
o
m
e
n
t
w
h
e
n
t
h
e
c
a
l
l
w
a
s
m
a
d
e
,
a
n
d
t
h
e
c
a
l
l
w
a
s
n
e
i
t
h
e
r
e
x
e
c
u
t
e
d
n
o
r
s
c
h
e
d
u
l
e
d
.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 0
_ B
F A
R n
A e
M v
E e
_ n
S t
T (
A s
T u
I c
S h
T a
I s
C p
S o
_ w
D e
I r
S c
J y
O c
I l
N e
T )
i
n
t
e
r
r
u
p
t
e
d
t
h
e
g
a
t
h
e
r
i
n
g
o
f
p
r
e
s
e
n
t
a
t
i
o
n
s
t
a
t
i
s
t
i
c
s
.
A
n
y
p
r
e
v
i
o
u
s
s
t
a
t
i
s
t
i
c
s
s
h
o
u
l
d
b
e
c
o
n
s
i
d
e
r
e
d
i
n
v
a
l
i
d
.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 0
_ C
G
R F
A u
P l
H l
I s
C c
S r
_ e
V e
I n
D m
P o
N d
_ e
S c
O o
U u
R l
C d
E n
_ o
I t
N b
_ e
U a
S c
E h
i
e
v
e
d
b
e
c
a
u
s
e
t
h
e
s
p
e
c
i
f
i
e
d
o
u
t
p
u
t
w
a
s
a
l
r
e
a
d
y
i
n
u
s
e
.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 2
_ 0
D A
R n
I i
V n
E t
R e
_ r
I n
N a
T l
E i
R s
N s
A u
L
_ e
E p
R r
R e
O v
R e
n
t
e
d
t
h
e
d
r
i
v
e
r
f
r
o
m
c
a
r
r
y
i
n
g
o
u
t
t
h
e
s
p
e
c
i
f
i
e
d
o
p
e
r
a
t
i
o
n
.
T
h
e
d
r
i
v
e
r
'
s
s
t
a
t
e
i
s
p
r
o
b
a
b
l
y
s
u
s
p
e
c
t
,
a
n
d
t
h
e
a
p
p
l
i
c
a
t
i
o
n
s
h
o
u
l
d
n
o
t
c
o
n
t
i
n
u
e
.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 2
_ 1
N A
O g
N l
E o
X b
C a
L l
U c
S o
I u
V n
E t
e
r
r
e
s
o
u
r
c
e
w
a
s
i
n
u
s
e
,
a
n
d
t
h
e
s
p
e
c
i
f
i
e
d
c
o
u
n
t
e
r
c
a
n
n
o
t
b
e
u
s
e
d
b
y
t
h
i
s
D
i
r
e
c
t
3
D
d
e
v
i
c
e
a
t
t
h
i
s
t
i
m
e
.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 2
_ 2
N A
O r
T e
_ s
C o
U u
R r
R c
E e
N i
T s
L n
Y o
_
A t
V a
A v
I a
L i
A l
B a
L b
E l
e
a
t
t
h
e
t
i
m
e
o
f
t
h
e
c
a
l
l,
b
u
t
m
a
y
b
e
c
o
m
e
a
v
a
i
l
a
b
l
e
l
a
t
e
r.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 2
_ 3
R T
E h
M e
O a
T p
E p
_ l
C i
L c
I a
E t
N i
T o
_ n
D '
I s
S r
C e
O m
N o
N t
E e
C d
T e
E v
D i
c
e
h
a
s
b
e
e
n
r
e
m
o
v
e
d
d
u
e
t
o
s
e
s
s
i
o
n
d
i
s
c
o
n
n
e
c
t
o
r
n
e
t
w
o
r
k
d
i
s
c
o
n
n
e
c
t
.
T
h
e
a
p
p
l
i
c
a
t
i
o
n
s
h
o
u
l
d
c
a
l
l
I
D
X
G
I
F
a
c
t
o
r
y
1
::
I
s
C
u
r
r
e
n
t
t
o
f
i
n
d
o
u
t
w
h
e
n
t
h
e
r
e
m
o
t
e
d
e
v
i
c
e
b
e
c
o
m
e
s
a
v
a
i
l
a
b
l
e
a
g
a
i
n
.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 2
_ 4
R T
E h
M e
O d
T e
E v
_ i
O c
U e
T h
O a
F s
M b
E e
M e
O n
R r
Y e
m
o
v
e
d
d
u
r
i
n
g
a
r
e
m
o
t
e
s
e
s
s
i
o
n
b
e
c
a
u
s
e
t
h
e
r
e
m
o
t
e
c
o
m
p
u
t
e
r
r
a
n
o
u
t
o
f
m
e
m
o
r
y
.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 2
_ 6
A T
C h
C e
E k
S e
S y
_ e
L d
O m
S
T u
t
e
x
w
a
s
a
b
a
n
d
o
n
e
d
.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 2
_ 7
W T
A h
I e
T t
_ i
T m
I e
M o
E u
O t
U v
T a
l
u
e
h
a
s
e
l
a
p
s
e
d
a
n
d
t
h
e
r
e
s
o
u
r
c
e
i
s
n
o
t
y
e
t
a
v
a
i
l
a
b
l
e
.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 2
_ 8
S T
E h
S e
S o
I
O u
N t
_ p
D u
I t
S d
C u
O p
N l
N i
E c
C a
T t
E i
D o
n
h
a
s
b
e
e
n
t
u
r
n
e
d
o
f
f
b
e
c
a
u
s
e
t
h
e
W
i
n
d
o
w
s
s
e
s
s
i
o
n
e
n
d
e
d
o
r
w
a
s
d
i
s
c
o
n
n
e
c
t
e
d
.
T
h
i
s
h
a
p
p
e
n
s
w
h
e
n
a
r
e
m
o
t
e
u
s
e
r
d
i
s
c
o
n
n
e
c
t
s
,
o
r
w
h
e
n
"
s
w
i
t
c
h
u
s
e
r
"
i
s
u
s
e
d
l
o
c
a
l
l
y
.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 2
_ 9
R
E T
S h
T e
R D
I X
C G
T I
_ o
T u
O t
_ u
O p
U u
T t
P (
U m
T o
_ n
S i
T t
A o
L r
E )
t
o
w
h
i
c
h
t
h
e
s
w
a
p
c
h
a
i
n
c
o
n
t
e
n
t
w
a
s
r
e
s
t
r
i
c
t
e
d
,
h
a
s
b
e
e
n
d
i
s
c
o
n
n
e
c
t
e
d
o
r
c
h
a
n
g
e
d
.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 2
_ A
C
A D
N X
N G
O I
T i
_ s
P u
R n
O a
T b
E l
C e
T t
_ o
C p
O r
N o
T v
E i
N d
T e
c
o
n
t
e
n
t
p
r
o
t
e
c
t
i
o
n
o
n
t
h
e
s
w
a
p
c
h
a
i
n
.
T
h
i
s
i
s
t
y
p
i
c
a
l
l
y
c
a
u
s
e
d
b
y
a
n
o
l
d
e
r
d
r
i
v
e
r,
o
r
b
y
t
h
e
a
p
p
l
i
c
a
t
i
o
n
u
s
i
n
g
a
s
w
a
p
c
h
a
i
n
t
h
a
t
i
s
i
n
c
o
m
p
a
t
i
b
l
e
w
i
t
h
c
o
n
t
e
n
t
p
r
o
t
e
c
t
i
o
n
.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 2
_ B
A T
C h
C e
E a
S p
S p
_ l
D i
E c
N a
I t
E i
D o
n
i
s
t
r
y
i
n
g
t
o
u
s
e
a
r
e
s
o
u
r
c
e
t
o
w
h
i
c
h
i
t
d
o
e
s
n
o
t
h
a
v
e
t
h
e
r
e
q
u
i
r
e
d
a
c
c
e
s
s
p
r
i
v
i
l
e
g
e
s
.
T
h
i
s
i
s
m
o
s
t
c
o
m
m
o
n
l
y
c
a
u
s
e
d
b
y
w
r
i
t
i
n
g
t
o
a
s
h
a
r
e
d
r
e
s
o
u
r
c
e
w
i
t
h
r
e
a
d
-
o
n
l
y
a
c
c
e
s
s
.
D
X 0
G x
I 0
_ 8
S 7
T A
A 0
T 0
U 0
S 9
_ T
U h
N e
O s
C w
C a
L p
U c
D h
E a
D i
n
h
a
s
b
e
c
o
m
e
u
n
o
c
c
l
u
d
e
d
.
D
X 0
G x
I 0
_ 8
S 7
T A
A 0
T 0
U 0
S A
_ T
D h
D e
A a
_ d
W a
A p
S t
_ e
S r
T d
I i
L d
L n
_ o
D t
R h
A a
W v
I e
N a
G c
c
e
s
s
t
o
t
h
e
r
e
q
u
i
r
e
d
r
e
s
o
u
r
c
e
s
t
o
c
o
m
p
l
e
t
e
t
h
e
D
e
s
k
t
o
p
D
u
p
l
i
c
a
t
i
o
n
P
r
e
s
e
n
t
(
)
c
a
l
l,
t
h
e
P
r
e
s
e
n
t
(
)
c
a
l
l
n
e
e
d
s
t
o
b
e
m
a
d
e
a
g
a
i
n
.
D
X 0
G x
I 8
_ 8
E 7
R A
R 0
O 0
R 2
_ 5
M A
O n
D o
E n
_ -
C g
H o
A i
N n
G g
E m
_ o
I d
N e
_ c
P h
R a
O n
G g
R e
E p
S r
S e
v
e
n
t
e
d
c
o
m
p
l
e
t
i
o
n
o
f
t
h
e
c
a
l
l.
T
h
e
c
a
l
l
m
a
y
s
u
c
c
e
e
d
i
f
a
t
t
e
m
p
t
e
d
l
a
t
e
r.
D
X 0
G x
I 8
_ 8
D 7
D B
I 0
_ 0
E 0
R 1
R
_ T
W h
A e
S G
S P
T U
I w
L a
L s
D b
R u
A s
W y
I w
N h
G e
n
t
h
e
o
p
e
r
a
t
i
o
n
w
a
s
r
e
q
u
e
s
t
e
d
.
D
X 0
G x
I 8
_ 8
D 7
D B
I 0
_ 0
E 0
R 2
R
_ T
U h
N e
S d
U r
P i
P v
O e
R r
T h
E a
D s
r
e
j
e
c
t
e
d
t
h
e
c
r
e
a
t
i
o
n
o
f
t
h
i
s
r
e
s
o
u
r
c
e
.
D
X 0
G x
I 8
_ 8
D 7
D B
I 0
_ 0
E 0
R 3
R T
_ h
N e
O G
N P
E U
X c
C o
L u
U n
S t
I e
V r
E w
a
s
i
n
u
s
e
b
y
a
n
o
t
h
e
r
p
r
o
c
e
s
s
o
r
d
3
d
d
e
v
i
c
e
w
h
e
n
a
p
p
l
i
c
a
t
i
o
n
r
e
q
u
e
s
t
e
d
a
c
c
e
s
s
t
o
i
t
.
D
3 0
D x
1 8
0 8
_ 7
E 9
R 0
R 0
O 0
R 1
_
T T
O h
O e
_ a
M p
A p
N l
Y i
_ c
U a
N t
I i
Q o
U n
E h
_ a
S s
T e
A x
T c
E e
_ e
O d
B e
J d
E t
C h
T e
S m
a
x
i
m
u
m
n
u
m
b
e
r
o
f
u
n
i
q
u
e
s
t
a
t
e
o
b
j
e
c
t
s
p
e
r
D
i
r
e
c
t
3
D
d
e
v
i
c
e
.
T
h
e
l
i
m
i
t
i
s
4
0
9
6
f
o
r
f
e
a
t
u
r
e
l
e
v
e
l
s
u
p
t
o
1
1
.
1
.
D
3 0
D x
1 8
0 8
_ 7
E 9
R 0
R 0
O 0
R 2
_ T
F h
I e
L s
E p
_ e
N c
O i
T f
_ i
F e
O d
U f
N i
D l
e
w
a
s
n
o
t
f
o
u
n
d
.
D
3 0
D x
1 8
1 8
_ 7
E C
R 0
R 0
O 0
R 1
_ T
T h
O e
O a
_ p
M p
A l
N i
Y c
_ a
U t
N i
I o
Q n
U h
E a
_ s
S e
T x
A c
T e
E e
_ d
O e
B d
J t
E h
C e
T m
S a
x
i
m
u
m
n
u
m
b
e
r
o
f
u
n
i
q
u
e
s
t
a
t
e
o
b
j
e
c
t
s
p
e
r
D
i
r
e
c
t
3
D
d
e
v
i
c
e
.
T
h
e
l
i
m
i
t
i
s
4
0
9
6
f
o
r
f
e
a
t
u
r
e
l
e
v
e
l
s
u
p
t
o
1
1
.
1
.
D
3 0
D x
1 8
1 8
_ 7
E C
R 0
R 0
O 0
R 2
_ T
F h
I e
L
E s
_ p
N e
O c
T i
_ f
F i
O e
U d
N f
D i
l
e
w
a
s
n
o
t
f
o
u
n
d
.
D
3 0
D x
1 8
1 8
_ 7
E C
R 0
R 0
O 0
R 3
_ T
T h
O e
O a
_ p
M p
A l
N i
Y c
_ a
U t
N i
I o
Q n
U
E h
_ a
V s
I e
E x
W c
_ e
O e
B d
J e
E d
C t
T h
S e
m
a
x
i
m
u
m
n
u
m
b
e
r
o
f
u
n
i
q
u
e
v
i
e
w
o
b
j
e
c
t
s
p
e
r
D
i
r
e
c
t
3
D
d
e
v
i
c
e
.
T
h
e
l
i
m
i
t
i
s
2
^
2
0
f
o
r
f
e
a
t
u
r
e
l
e
v
e
l
s
u
p
t
o
1
1
.
1
.
D 0
3 x
D 8
1 8
1 7
_ C
E 0
R 0
R 0
O 4
R
_ T
D h
E e
F a
E p
R p
R l
E i
D c
_ a
C t
O i
N o
T n
E '
X s
T f
_ i
M r
A s
P t
_ c
W a
I l
T l
H p
O e
U r
T c
_ o
I m
N m
I a
T n
I d
A l
L i
_ s
D t
I t
S o
C M
A a
R p
D o
n
a
d
e
f
e
r
r
e
d
c
o
n
t
e
x
t
d
i
d
n
o
t
u
s
e
D
3
D
1
1
_
M
A
P
_
W
R
I
T
E
_
D
I
S
C
A
R
D
.
D
2 0
D x
E 8
R 8
R 9
_ 9
W 0
R 0
O 0
N 1
G T
_ h
S e
T o
A b
T j
E e
c
t
w
a
s
n
o
t
i
n
t
h
e
c
o
r
r
e
c
t
s
t
a
t
e
t
o
p
r
o
c
e
s
s
t
h
e
m
e
t
h
o
d
.
D
2 0
D x
E 8
R 8
R 9
_ 9
N 0
O 0
T 0
_ 2
I T
N h
I e
T o
I b
A j
L e
I c
Z t
E h
D a
s
n
o
t
y
e
t
b
e
e
n
i
n
i
t
i
a
l
i
z
e
d
.
D
2 0
D x
E 8
R 8
R 9
_ 9
U 0
N 0
S 0
U 3
P T
P h
O e
R r
T e
E q
D u
_ e
O s
P t
E e
R d
A o
T p
I e
O r
N a
t
i
o
n
i
s
n
o
t
s
u
p
p
o
r
t
e
d
.
D
2 0
D x
E 8
R 8
R 9
_ 9
S 0
C 0
A 0
N 4
N T
E h
R e
_ g
F e
A o
I m
L e
E t
D r
y
s
c
a
n
n
e
r
f
a
i
l
e
d
t
o
p
r
o
c
e
s
s
t
h
e
d
a
t
a
.
D
2 0
D x
E 8
R 8
R 9
_ 9
S 0
C 0
R 0
E 5
E D
N i
_ r
A e
C c
C t
E 2
S D
S c
_ o
D u
E l
N d
I n
E o
D t
a
c
c
e
s
s
t
h
e
s
c
r
e
e
n
.
D
2 0
D x
E 8
R 8
R 9
_ 9
D 0
I 0
S 0
P 6
L A
A v
Y a
_ l
S i
T d
A d
T i
E s
_ p
I l
N a
V y
A s
L t
I a
D t
e
c
o
u
l
d
n
o
t
b
e
d
e
t
e
r
m
i
n
e
d
.
D
2 0
D x
E 8
R 8
R 9
_ 9
Z 0
E 0
R 0
O 7
_ T
V h
E e
C s
T u
O p
R p
l
i
e
d
v
e
c
t
o
r
i
s
z
e
r
o
.
D
2 0
D x
E 8
R 8
R 9
_ 9
I 0
N 0
T 0
E 8
R A
N n
A i
L n
_ t
E e
R r
R n
O a
R l
e
r
r
o
r
(
D
i
r
e
c
t
2
D
b
u
g
)
o
c
c
u
r
r
e
d
.
O
n
c
h
e
c
k
e
d
b
u
i
l
d
s
,
w
e
w
o
u
l
d
a
s
s
e
r
t
.
T
h
e
a
p
p
l
i
c
a
t
i
o
n
s
h
o
u
l
d
c
l
o
s
e
t
h
i
s
i
n
s
t
a
n
c
e
o
f
D
i
r
e
c
t
2
D
a
n
d
s
h
o
u
l
d
c
o
n
s
i
d
e
r
r
e
s
t
a
r
t
i
n
g
i
t
s
p
r
o
c
e
s
s
.
D
2 0
D x
E 8
R 8
R 9
_ 9
D 0
I 0
S 0
P 9
L
A T
Y h
_ e
F d
O i
R s
M p
A l
T a
_ y
N f
O o
T r
_ m
S a
U t
P D
P i
O r
R e
T c
E t
D 2
D
n
e
e
d
s
t
o
r
e
n
d
e
r
i
s
n
o
t
s
u
p
p
o
r
t
e
d
b
y
t
h
e
h
a
r
d
w
a
r
e
d
e
v
i
c
e
.
D
2 0
D x
E 8
R 8
R 9
_ 9
I 0
N 0
V 0
A A
L A
I c
D a
_ l
C l
A t
L o
L t
h
i
s
m
e
t
h
o
d
i
s
i
n
v
a
l
i
d
.
D
2 0
D x
E 8
R 8
R 9
_ 9
N 0
O 0
_ 0
H B
A N
R o
D h
W a
A r
R d
E w
_ a
D r
E e
V r
I e
C n
E d
e
r
i
n
g
d
e
v
i
c
e
i
s
a
v
a
i
l
a
b
l
e
f
o
r
t
h
i
s
o
p
e
r
a
t
i
o
n
.
D
2 0
D x
E 8
R 8
R 9
_ 9
R 0
E 0
C 0
R C
E T
A h
T e
E r
_ e
T h
A a
R s
G b
E e
T e
n
a
p
r
e
s
e
n
t
a
t
i
o
n
e
r
r
o
r
t
h
a
t
m
a
y
b
e
r
e
c
o
v
e
r
a
b
l
e
.
T
h
e
c
a
l
l
e
r
n
e
e
d
s
t
o
r
e
c
r
e
a
t
e
,
r
e
r
e
n
d
e
r
t
h
e
e
n
t
i
r
e
f
r
a
m
e
,
a
n
d
r
e
a
t
t
e
m
p
t
p
r
e
s
e
n
t
.
D
2 0
D x
E 8
R 8
R 9
_ 9
T 0
O 0
O 0
_ D
M S
A h
N a
Y d
_ e
S r
H c
A o
D n
E s
R t
_ r
E u
L c
E t
M i
E o
N n
T f
S a
i
l
e
d
b
e
c
a
u
s
e
i
t
w
a
s
t
o
o
c
o
m
p
l
e
x
.
D
2 0
D x
E 8
R 8
R 9
_ 9
S 0
H 0
A 0
D E
E S
R h
_ a
C d
O e
M r
P c
I o
L m
E p
_ i
F l
A a
I t
L i
E o
D n
f
a
i
l
e
d
.
D
2 0
D x
E 8
R 8
R 9
_ 9
M 0
A 0
X 0
_ F
T
E R
X e
T q
U u
R e
E s
_ t
S e
I d
Z D
E i
_ r
E e
X c
C t
E X
E s
D u
E r
D f
a
c
e
s
i
z
e
e
x
c
e
e
d
e
d
m
a
x
i
m
u
m
t
e
x
t
u
r
e
s
i
z
e
.
D
2 0
D x
E 8
R 8
R 9
_ 9
U 0
N 0
S 1
U 0
P T
P h
O e
R r
T e
E q
D u
_ e
V s
E t
R e
S d
I D
O i
N r
e
c
t
2
D
v
e
r
s
i
o
n
i
s
n
o
t
s
u
p
p
o
r
t
e
d
.
D
2 0
D x
E 8
R 8
R 9
_ 9
B 0
A 0
D 1
_ 1
N I
U n
M v
B a
E l
R i
d
n
u
m
b
e
r.
D
2 0
D x
E 8
R 8
R 9
_ 9
W 0
R 0
O 1
N 2
G
_ O
F b
A j
C e
T c
O t
R s
Y u
s
e
d
t
o
g
e
t
h
e
r
m
u
s
t
b
e
c
r
e
a
t
e
d
f
r
o
m
t
h
e
s
a
m
e
f
a
c
t
o
r
y
i
n
s
t
a
n
c
e
.
D
2 0
D x
E 8
R 8
R 9
_ 9
L 0
A 0
Y 1
E 3
R A
_ l
A a
L y
R e
E r
A r
D e
Y s
_ o
I u
N r
_ c
U e
S c
E a
n
o
n
l
y
b
e
i
n
u
s
e
o
n
c
e
a
t
a
n
y
p
o
i
n
t
i
n
t
i
m
e
.
D
2 0
D x
E 8
R 8
R 9
_ 9
P 0
O 0
P 1
_ 4
C T
A h
L e
L p
_ o
D p
I c
D a
_ l
N l
O d
T i
_ d
M n
A o
T t
C m
H a
_ t
P c
U
S h
H t
h
e
c
o
r
r
e
s
p
o
n
d
i
n
g
p
u
s
h
c
a
l
l.
D
2 0
D x
E 8
R 8
R 9
_ 9
W 0
R 0
O 1
N 5
G T
_ h
R e
E r
S e
O s
U o
R u
C r
E c
_ e
D w
O a
M s
A
I r
N e
a
l
i
z
e
d
o
n
t
h
e
w
r
o
n
g
r
e
n
d
e
r
t
a
r
g
e
t
.
D
2 0
D x
E 8
R 8
R 9
_ 9
P 0
U 0
S 1
H 6
_ T
P h
O e
P p
_ u
U s
N h
B a
A
L n
A d
N p
C o
E p
D c
a
l
l
s
w
e
r
e
u
n
b
a
l
a
n
c
e
d
.
D
2 0
D x
E 8
R 8
R 9
_ 9
R 0
E 0
N 1
D 7
E A
R t
_ t
T e
A m
R p
G t
E t
T o
_ c
H o
A p
S y
_ f
L
A r
Y o
E m
R a
_ r
O e
R n
_ d
C e
L r
I t
P a
R r
E g
C e
T t
w
h
i
l
e
a
l
a
y
e
r
o
r
c
l
i
p
r
e
c
t
i
s
a
p
p
l
i
e
d
.
D
2 0
D x
E 8
R 8
R 9
_ 9
I 0
N 0
C 1
O 8
M
P T
A h
T e
I b
B r
L u
E s
_ h
B t
R y
U p
S e
H s
_ a
T r
Y e
P i
E n
S c
o
m
p
a
t
i
b
l
e
f
o
r
t
h
e
c
a
l
l.
D
2 0
D x
E 8
R 8
R 9
_ 9
W 0
I 0
N 1
3 9
2
_ A
E n
R u
R n
O k
R n
o
w
n
w
i
n
3
2
f
a
i
l
u
r
e
o
c
c
u
r
r
e
d
.
D
2 0
D x
E 8
R 8
R 9
_ 9
T 0
A 0
R 1
G A
E T
T h
_ e
N r
O e
T n
_ d
G e
D r
I t
_ a
C r
O g
M e
P t
A i
T s
I n
B o
L t
E c
o
m
p
a
t
i
b
l
e
w
i
t
h
G
D
I
.
D
2 0
D x
E 8
R 8
R 9
_ 9
T 0
E 0
X 1
T B
_ A
E t
F e
F x
E
C t
T c
_ l
I i
S e
_ n
W t
R d
O r
N a
G w
_ i
T n
Y g
P e
E f
f
e
c
t
o
b
j
e
c
t
i
s
o
f
t
h
e
w
r
o
n
g
t
y
p
e
.
D
2 0
D x
E 8
R 8
R 9
_ 9
T 0
E 0
X 1
T C
_
R T
E h
N e
D a
E p
R p
E l
R i
_ c
N a
O t
T i
_ o
R n
E i
L s
E h
A o
S l
E d
D i
n
g
a
r
e
f
e
r
e
n
c
e
t
o
t
h
e
I
D
W
r
i
t
e
T
e
x
t
R
e
n
d
e
r
e
r
i
n
t
e
r
f
a
c
e
a
f
t
e
r
t
h
e
c
o
r
r
e
s
p
o
n
d
i
n
g
D
r
a
w
T
e
x
t
o
r
D
r
a
w
T
e
x
t
L
a
y
o
u
t
c
a
l
l
h
a
s
r
e
t
u
r
n
e
d
.
T
h
e
I
D
W
r
i
t
e
T
e
x
t
R
e
n
d
e
r
e
r
i
n
s
t
a
n
c
e
w
i
l
l
b
e
i
n
v
a
l
i
d
.
D
2 0
D x
E 8
R 8
R 9
_ 9
E 0
X 0
C 1
E D
E T
D h
S e
_ r
M e
A q
X u
_ e
B s
I t
T e
M d
A s
P i
_ z
S e
I i
Z s
E l
a
r
g
e
r
t
h
a
n
t
h
e
g
u
a
r
a
n
t
e
e
d
s
u
p
p
o
r
t
e
d
t
e
x
t
u
r
e
s
i
z
e
a
t
t
h
e
D
i
r
e
c
t
3
D
d
e
v
i
c
e
'
s
c
u
r
r
e
n
t
f
e
a
t
u
r
e
l
e
v
e
l.
D
2 0
D x
E 8
R 8
R 9
_ 9
I 0
N 0
V 1
A E
L T
I h
D e
_ r
G e
R w
A a
P s
H a
_ c
C
O o
N n
F f
I i
G g
U u
R r
A a
T t
I i
O o
N n
e
r
r
o
r
i
n
t
h
e
g
r
a
p
h
.
D
2 0
D x
E 8
R 8
R 9
_ 9
I 0
N 0
V 1
A F
L T
I h
D e
_ r
I e
N w
T a
E s
R a
N i
A n
L
_ t
G e
R r
A n
P a
H l
_ c
C o
O n
N f
F i
I g
G u
U r
R a
A t
T i
I o
O n
N e
r
r
o
r
i
n
t
h
e
g
r
a
p
h
.
D
2 0
D x
E 8
R 8
R 9
_ 9
C 0
Y 0
C 2
L 0
I T
C h
_ e
G r
R
A e
P w
H a
s
a
c
y
c
l
e
i
n
t
h
e
g
r
a
p
h
.
D
2 0
D x
E 8
R 8
R 9
_ 9
B 0
I 0
T 2
M 1
A C
P a
_ n
C n
A o
N t
N d
O r
T a
_ w
D w
R i
A t
W h
a
b
i
t
m
a
p
t
h
a
t
h
a
s
t
h
e
D
2
D
1
_
B
I
T
M
A
P
_
O
P
T
I
O
N
S
_
C
A
N
N
O
T
_
D
R
A
W
o
p
t
i
o
n
.
D 0
2 x
D 8
E 8
R 9
R 9
_ 0
O 0
U 2
T 2
S
T T
A h
N e
D o
I p
N e
G r
_ a
B t
I i
T o
M n
A c
P a
_ n
R n
E o
F t
E c
R o
E m
N p
C l
E e
S t
e
w
h
i
l
e
t
h
e
r
e
a
r
e
o
u
t
s
t
a
n
d
i
n
g
r
e
f
e
r
e
n
c
e
s
t
o
t
h
e
t
a
r
g
e
t
b
i
t
m
a
p
.
D
2 0
D x
E 8
R 8
R 9
_ 9
O 0
R 0
I 2
G 3
I T
N h
A
L e
_ o
T p
A e
R r
G a
E t
T i
_ o
N n
O f
T a
_ i
B l
O e
U d
N b
D e
c
a
u
s
e
t
h
e
o
r
i
g
i
n
a
l
t
a
r
g
e
t
i
s
n
o
t
c
u
r
r
e
n
t
l
y
b
o
u
n
d
a
s
a
t
a
r
g
e
t
.
D
2 0
D x
E 8
R 8
R 9
_ 9
I 0
N 0
V 2
A 4
L C
I a
D n
_ n
T o
A t
R s
G e
E t
T t
h
e
i
m
a
g
e
a
s
a
t
a
r
g
e
t
b
e
c
a
u
s
e
i
t
i
s
e
i
t
h
e
r
a
n
e
f
f
e
c
t
o
r
i
s
a
b
i
t
m
a
p
t
h
a
t
d
o
e
s
n
o
t
h
a
v
e
t
h
e
D
2
D
1
_
B
I
T
M
A
P
_
O
P
T
I
O
N
S
_
T
A
R
G
E
T
f
l
a
g
s
e
t
.
D
2 0
D x
E 8
R 8
R 9
_ 9
B 0
I 0
T 2
M 5
A C
P a
_ n
B n
O o
U t
N d
D r
_ a
A w
S w
_ i
T t
A h
R a
G b
E i
T t
m
a
p
t
h
a
t
i
s
c
u
r
r
e
n
t
l
y
b
o
u
n
d
a
s
t
h
e
t
a
r
g
e
t
b
i
t
m
a
p
.
D
2 0
D x
E 8
R 8
R 9
_ 9
I 0
N 0
S 2
U 6
F D
F 3
I D
C D
I e
E v
N i
T c
_ e
D d
E o
V e
I s
C n
E o
_ t
C h
A a
P v
A e
B s
I u
L f
I f
T i
I c
E i
S e
n
t
c
a
p
a
b
i
l
i
t
i
e
s
t
o
p
e
r
f
o
r
m
t
h
e
r
e
q
u
e
s
t
e
d
a
c
t
i
o
n
.
D
2 0
D x
E 8
R 8
R 9
_ 9
I 0
N 0
T 2
E 7
R T
M
E h
D e
I g
A r
T a
E p
_ h
T c
O o
O u
_ l
L d
A n
R o
G t
E b
e
r
e
n
d
e
r
e
d
w
i
t
h
t
h
e
c
o
n
t
e
x
t
'
s
c
u
r
r
e
n
t
t
i
l
i
n
g
s
e
t
t
i
n
g
s
.
D
2 0
D x
E 8
R 8
R 9
_ 9
E 0
F 0
F 2
E 8
C T
T h
_ e
I C
S L
_ S
N I
O D
T p
_ r
R o
E v
G i
I d
S e
T d
E t
R o
E U
D n
r
e
g
i
s
t
e
r
d
i
d
n
o
t
c
o
r
r
e
s
p
o
n
d
t
o
a
r
e
g
i
s
t
e
r
e
d
e
f
f
e
c
t
.
D
2 0
D x
E 8
R 8
R 9
_ 9
I 0
N 0
V 2
A 9
L T
I h
D e
_
P s
R p
O e
P c
E i
R f
T i
Y e
d
p
r
o
p
e
r
t
y
d
o
e
s
n
o
t
e
x
i
s
t
.
D
2 0
D x
E 8
R 8
R 9
_ 9
N 0
O 0
_ 2
S A
U T
B h
P e
R s
O p
P e
E c
R i
T f
I
E i
S e
d
s
u
b
-
p
r
o
p
e
r
t
y
d
o
e
s
n
o
t
e
x
i
s
t
.
D
2 0
D x
E 8
R 8
R 9
_ 9
P 0
R 0
I 2
N B
T A
_ d
J d
O P
B a
_ g
C e
L o
O r
S C
E l
D
o
s
e
c
a
l
l
e
d
a
f
t
e
r
p
r
i
n
t
j
o
b
i
s
a
l
r
e
a
d
y
c
l
o
s
e
d
.
D
2 0
D x
E 8
R 8
R 9
_ 9
P 0
R 0
I 2
N C
T E
_
F r
O r
R o
M r
A d
T u
_ r
N i
O n
T g
_ p
S r
U i
P n
P t
O c
R o
T n
E t
D r
o
l
c
r
e
a
t
i
o
n
.
I
n
d
i
c
a
t
e
s
t
h
a
t
n
o
n
e
o
f
t
h
e
p
a
c
k
a
g
e
t
a
r
g
e
t
t
y
p
e
s
(
r
e
p
r
e
s
e
n
t
i
n
g
p
r
i
n
t
e
r
f
o
r
m
a
t
s
)
a
r
e
s
u
p
p
o
r
t
e
d
b
y
D
i
r
e
c
t
2
D
p
r
i
n
t
c
o
n
t
r
o
l.
D
2 0
D x
E 8
R 8
R 9
_ 9
T 0
O 0
O 2
_ D
M A
A n
N e
Y f
_ f
T e
R c
A t
N a
S t
F
O t
R e
M m
_ p
I t
N e
P d
U t
T o
S u
s
e
a
t
r
a
n
s
f
o
r
m
w
i
t
h
t
o
o
m
a
n
y
i
n
p
u
t
s
.
D
W 0
R x
I 8
T 8
E 9
_ 8
E 5
_ 0
F 0
I 0
L I
E n
F d
O i
R c
M a
A t
T e
s
a
n
e
r
r
o
r
i
n
a
n
i
n
p
u
t
f
i
l
e
s
u
c
h
a
s
a
f
o
n
t
f
i
l
e
.
D
W 0
R x
I 8
T 8
9
E 8
_ 5
E 0
_ 0
U 1
N
E I
X n
P d
E i
C c
T a
E t
D e
s
a
n
e
r
r
o
r
o
r
i
g
i
n
a
t
i
n
g
i
n
D
i
r
e
c
t
W
r
i
t
e
c
o
d
e
,
w
h
i
c
h
i
s
n
o
t
e
x
p
e
c
t
e
d
t
o
o
c
c
u
r
b
u
t
i
s
s
a
f
e
t
o
r
e
c
o
v
e
r
f
r
o
m
.
D
W 0
R x
I 8
T 8
E 9
_ 8
E 5
_ 0
N 0
O 2
F
O I
N n
T d
i
c
a
t
e
s
t
h
e
s
p
e
c
i
f
i
e
d
f
o
n
t
d
o
e
s
n
o
t
e
x
i
s
t
.
D
W 0
R x
I 8
T 8
E 9
_ 8
E 5
_ 0
F 0
I 3
L
E A
N f
O o
T n
F t
O f
U i
N l
D e
c
o
u
l
d
n
o
t
b
e
o
p
e
n
e
d
b
e
c
a
u
s
e
t
h
e
f
i
l
e
,
d
i
r
e
c
t
o
r
y
,
n
e
t
w
o
r
k
l
o
c
a
t
i
o
n
,
d
r
i
v
e
,
o
r
o
t
h
e
r
s
t
o
r
a
g
e
l
o
c
a
t
i
o
n
d
o
e
s
n
o
t
e
x
i
s
t
o
r
i
s
u
n
a
v
a
i
l
a
b
l
e
.
D
W 0
R x
I 8
T 8
E 9
_ 8
E 5
_ 0
F 0
I 4
L A
E f
A o
C n
C t
E f
S i
S l
e
e
x
i
s
t
s
b
u
t
c
o
u
l
d
n
o
t
b
e
o
p
e
n
e
d
d
u
e
t
o
a
c
c
e
s
s
d
e
n
i
e
d
,
s
h
a
r
i
n
g
v
i
o
l
a
t
i
o
n
,
o
r
s
i
m
i
l
a
r
e
r
r
o
r.
D
W 0
R x
I 8
T 8
E 9
_ 8
E 5
_ 0
F 0
O 5
N A
T f
C o
O n
L t
L c
E o
C l
T l
I e
O c
N t
O i
B o
S n
O i
L s
E o
T b
E s
o
l
e
t
e
d
u
e
t
o
c
h
a
n
g
e
s
i
n
t
h
e
s
y
s
t
e
m
.
D
W 0
R x
I 8
T 8
E 9
_ 8
E 5
_ 0
A 0
L 6
R T
E h
A e
D g
Y i
R v
E e
G n
I i
S n
T t
E e
R
E r
D f
a
c
e
i
s
a
l
r
e
a
d
y
r
e
g
i
s
t
e
r
e
d
.
D
W 0
R x
I 8
T 8
E 9
_ 8
E 5
_ 0
C 0
A 7
C T
H h
E e
F f
O o
R n
M t
A c
T a
c
h
e
c
o
n
t
a
i
n
s
i
n
v
a
l
i
d
d
a
t
a
.
D
W 0
R x
I 8
T 8
E 9
_ 8
E 5
_ 0
C 0
A 8
C A
H f
E o
V n
E t
R c
S a
I c
O h
N e
f
i
l
e
c
o
r
r
e
s
p
o
n
d
s
t
o
a
d
i
f
f
e
r
e
n
t
v
e
r
s
i
o
n
o
f
D
i
r
e
c
t
W
r
i
t
e
.
D
W 0
R x
I 8
T 8
E 9
_ 8
E 5
_ 0
U 0
N 9
S T
U h
P
P e
O o
R p
T e
E r
D a
O t
P i
E o
R n
A i
T s
I n
O o
N t
s
u
p
p
o
r
t
e
d
f
o
r
t
h
i
s
t
y
p
e
o
f
f
o
n
t
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 0
R 4
R
_ T
W h
R e
O c
N o
G d
S e
T c
A i
T s
E i
n
t
h
e
w
r
o
n
g
s
t
a
t
e
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 0
R 5
R T
_ h
V e
A v
L a
U l
E u
O e
U i
T s
O o
F u
R t
A o
N f
G r
E a
n
g
e
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 0
R 7
R T
_ h
U e
N i
K m
N a
O g
W e
N f
I o
M r
A m
G a
E t
F i
O s
R u
M n
A k
T n
o
w
n
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 0
R B
R
_ T
U h
N e
S S
U D
P K
P v
O e
R r
T s
E i
D o
V n
E i
R s
S u
I n
O s
N u
p
p
o
r
t
e
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 0
R C
R T
_ h
N e
O c
T o
I m
N p
I o
T n
I e
A n
L t
I i
Z s
E n
D o
t
i
n
i
t
i
a
l
i
z
e
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 0
R D
R T
_ h
A e
L r
R e
E i
A s
D a
Y l
L r
O e
C a
K d
E y
D a
n
o
u
t
s
t
a
n
d
i
n
g
r
e
a
d
o
r
w
r
i
t
e
l
o
c
k
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 4
R 0
R T
_ h
P e
R s
O p
P e
E c
R i
T f
Y i
N e
O
T d
F b
O i
U t
N m
D a
p
p
r
o
p
e
r
t
y
c
a
n
n
o
t
b
e
f
o
u
n
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 4
R 1
R T
_ h
P e
R b
O i
P t
E m
R a
T p
Y c
N
O o
T d
S e
U c
P d
P o
O e
R s
T n
E o
D t
s
u
p
p
o
r
t
t
h
e
b
i
t
m
a
p
p
r
o
p
e
r
t
y
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 4
R 2
R T
_ h
P e
R
O b
P i
E t
R m
T a
Y p
S p
I r
Z o
E p
e
r
t
y
s
i
z
e
i
s
i
n
v
a
l
i
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 4
R 3
R A
_ n
C u
O n
D k
E n
C o
P w
R n
E e
S r
E
N r
T o
r
h
a
s
o
c
c
u
r
r
e
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 4
R 4
R T
_ h
C e
O b
D i
E t
C m
N a
O p
T c
H o
U d
M e
B c
N d
A o
I e
L s
n
o
t
s
u
p
p
o
r
t
a
t
h
u
m
b
n
a
i
l.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 4
R 5
R T
_ h
P e
A b
L i
E t
T m
T a
E p
U p
N a
A l
V e
A t
I t
L e
A i
B s
L u
E n
a
v
a
i
l
a
b
l
e
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 4
R 6
R T
_ o
C o
O m
D a
E n
C y
T s
O c
O a
M n
A l
N i
Y n
S e
C s
A w
N e
L r
I e
N r
E e
S q
u
e
s
t
e
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 4
R 8
R
_ A
I n
N i
T n
E t
R e
N r
A n
L a
E l
R e
R r
O r
R o
r
o
c
c
u
r
r
e
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 4
R 9
R T
_ h
S e
O b
U i
R t
C m
E a
R p
E b
C o
T u
D n
O d
E s
S d
N o
O n
T o
M t
A m
T a
C t
H c
D h
I t
M h
E e
N b
S i
I t
O m
N a
S p
d
i
m
e
n
s
i
o
n
s
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 5
R 0
R T
_
C h
O e
M c
P o
O m
N p
E o
N n
T e
N n
O t
T c
F a
O n
U n
N o
D t
b
e
f
o
u
n
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 5
R 1
R T
_ h
I e
M b
A i
G t
E m
S a
I p
Z s
E i
O z
U e
T i
O
F s
R o
A u
N t
G s
E i
d
e
t
h
e
v
a
l
i
d
r
a
n
g
e
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 5
R 2
R T
_ h
T e
O r
O e
M i
U s
C t
H o
M o
E m
T u
A c
D h
A m
T e
A t
a
d
a
t
a
t
o
b
e
w
r
i
t
t
e
n
t
o
t
h
e
b
i
t
m
a
p
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 6
R 0
R T
_ h
B e
A i
D m
I a
M g
A e
G i
E s
u
n
r
e
c
o
g
n
i
z
e
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 6
R 1
R T
_ h
B e
A i
D m
H a
E g
A e
D h
E e
R a
d
e
r
i
s
u
n
r
e
c
o
g
n
i
z
e
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 6
R 2
R T
_ h
F e
R b
A i
M t
E m
M a
I p
S f
S r
I a
N m
G e
i
s
m
i
s
s
i
n
g
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 6
R 3
R T
_ h
B e
A i
D m
M a
E g
T e
A m
D e
A t
T a
A d
H a
E t
A a
D h
E e
R a
d
e
r
i
s
u
n
r
e
c
o
g
n
i
z
e
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 7
R 0
R T
_ h
B e
A
D s
S t
T r
R e
E a
A m
M d
D a
A t
T a
A i
s
u
n
r
e
c
o
g
n
i
z
e
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 7
R 1
R F
_ a
S i
T l
R e
E d
A t
M o
W w
R r
I i
T t
E e
t
o
t
h
e
s
t
r
e
a
m
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 7
R 2
R F
_ a
S i
T l
R e
E d
A t
M o
R r
E e
A a
D d
f
r
o
m
t
h
e
s
t
r
e
a
m
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 7
R 3
R
_ T
S h
T e
R s
E t
A r
M e
N a
O m
T i
A s
V n
A o
I t
L a
A v
B a
L i
E l
a
b
l
e
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 8
R 0
R T
_ h
U e
N b
S
U i
P t
P m
O a
R p
T p
E i
D x
P e
I l
X f
E o
L r
F m
O a
R t
M i
A s
T u
n
s
u
p
p
o
r
t
e
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 8
R 1
R T
_ h
U e
N o
S p
U e
P r
P a
O t
R
T i
E o
D n
O i
P s
E u
R n
A s
T u
I p
O p
N o
r
t
e
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 8
R A
R T
_ h
I e
N c
V o
A m
L p
I o
D n
R e
E n
G t
I r
S e
T g
R i
A s
T t
I r
O a
N t
i
o
n
i
s
i
n
v
a
l
i
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 8
R B
R T
_ h
C e
O c
M o
P m
O p
N o
E n
N e
T n
I t
N i
I n
T i
I t
A i
L a
I l
Z i
E z
F a
A t
I i
L o
U n
R h
E
a
s
f
a
i
l
e
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 8
R C
R T
_ h
I e
N b
S u
U f
F f
F e
I r
C a
I l
E l
N o
T c
B a
U t
F e
F d
E i
R s
i
n
s
u
f
f
i
c
i
e
n
t
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 8
R D
R D
_ u
D p
U l
P i
L c
I a
C t
A e
T m
E e
M t
E a
T d
A a
D t
A a
T i
A s
P p
R r
E e
S s
E e
N n
T t
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 8
R E
R
_ T
P h
R e
O b
P i
E t
R m
T a
Y p
U p
N r
E o
X p
P e
E r
C t
T y
E t
D y
T p
Y e
P i
E s
u
n
e
x
p
e
c
t
e
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 8
R F
R T
_ h
U e
N s
E i
X z
P e
E i
C s
T u
E n
D e
S x
I p
Z e
E c
t
e
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 9
R 0
R T
_ h
I e
N p
V r
A o
L p
I e
D r
Q t
U y
E q
R u
Y e
R r
E y
Q i
U s
E i
S n
T v
a
l
i
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 9
R 1
R T
_ h
U e
N m
E e
X t
P a
E d
C a
T t
E a
D t
M y
E p
T e
A i
D s
A u
T n
A e
T x
Y p
P e
E c
t
e
d
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 9
R 2
R
_ T
R h
E e
Q s
U p
E e
S c
T i
O f
N i
L e
Y d
V b
A i
L t
I m
D a
A p
T p
M r
E o
T p
A e
D r
A t
T y
A i
R s
O o
O n
T l
y
v
a
l
i
d
a
t
r
o
o
t
l
e
v
e
l.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 9
R 3
R T
_ h
I e
N q
V u
A e
L r
I y
D s
Q t
U r
E i
R n
Y g
C c
H o
A n
R t
A a
C i
T n
E s
R a
n
i
n
v
a
l
i
d
c
h
a
r
a
c
t
e
r.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 9
R 4
R W
_ i
W n
I d
N o
3 w
2 s
E C
R o
R d
O e
R c
s
r
e
c
e
i
v
e
d
a
n
e
r
r
o
r
f
r
o
m
t
h
e
W
i
n
3
2
s
y
s
t
e
m
.
W
I 0
N x
C 8
O 8
D 9
E 8
C 2
_ F
E 9
R 5
R T
_ h
I e
N r
V e
A q
L u
I e
D s
P t
R e
O d
G l
R e
E v
S e
S l
I o
V f
E d
L e
E t
V a
E i
L l
i
s
n
o
t
p
r
e
s
e
n
t
.
Requirements
Header
Win
erro
r.h
See also
C
O
M
E
r
r
o
r
C
o
d
e
s
Impersonation Level Constants
1/7/2020 • 2 minutes to read • Edit Online
Specifies an impersonation level, which indicates the amount of authority given to the server when it is
impersonating the client.
CONSTANT/VALUE DESCRIPTION
The server can obtain the client's identity. The server can
RPC impersonate the client for ACL checking, but it cannot access
_C_I system objects as the client.
MP_
LEV
EL_I
DEN
TIFY
2
Remarks
GetUserName will fail while impersonating at identify level. The workaround is to impersonate, call
OpenThreadToken, revert, call GetTokenInformation, and finally, call LookupAccountSid. Using
CoSetProxyBlanket, the client sets the impersonation level
Using CoSetProxyBlanket, the client sets the impersonation level and proxy identity that will be available when a
server calls CoImpersonateClient. The identity the server will see when impersonating takes place is described in
Cloaking. Note that when making a call while impersonating, the callee will normally receive the caller's process
token, not the caller's impersonation token. To receive the caller's impersonation token, the caller must enable
cloaking.
Requirements
Header
Rpc
Dce.
h
See also
C
l
o
a
k
i
n
g
Enumerations
1/7/2020 • 2 minutes to read • Edit Online
INTERFACE DESCRIPTION
IClientSecurity Gives the client control over the security settings for each
individual interface proxy of an object.
IOleItemContainer Used by item monikers when they are bound to the objects
they identify.
IPersistStream Enables the saving and loading of objects that use a simple
serial stream for their storage needs.
IPipeLong Transfers data of the long integer type (which is 32 bits wide).
IRpcChannelBuffer Marshals data between a COM client proxy and a COM server
stub.
IRpcProxyBuffer Controls the RPC proxy used to marshal data between COM
components.
IRpcStubBuffer Controls the RPC stub used to marshal data between COM
components.
Syntax
HRESULT GetAvailableSize(
[in] HMONITOR hMonitor,
[out] UINT *puMaxHeight,
[out] UINT *puFixedWidth
);
Parameters
h Specifies the monitor for which the available docking size will be retrieved.
M
o
n
i
t
o
r
[
i
n
]
p On success, set to the maximum height available for docking on the specified hMonitor, in pixels.
u
On failure, set to zero.
M
a
x
H
e
i
g
h
t
[
o
u
t
]
p
u
F
i
x
e
d
W
i
d
t
h
[
o
u
t
]
On success, set to the fixed width available for docking on the specified hMonitor, in pixels. Any window
docked to this hMonitor will be sized to this width.
On failure, set to zero.
Return value
RETURN CODE DESCRIPTION
Success.
S_O
K
Remarks
Accessibility windows can only be docked to a monitor that has at least 768 vertical screen pixels. This API will not
allow such windows to be docked with a height that would cause Windows Store apps to have less than 768
vertical screen pixels.
Examples
IAccessibilityDockingService *pDockingService;
HRESULT hr = CoCreateInstance(CLSID_AccessibilityDockingService, CLSCTX_INPROV_SERVER, nullptr,
IID_PPV_ARGS(&pDockingService));
if (SUCCEEDED(hr))
{
UINT uMaxHeight;
UINT uFixedWidth;
See also
I
A
c
c
e
s
s
i
b
i
l
i
t
y
D
o
c
k
i
n
g
S
e
r
v
i
c
e
IOrpcDebugNotify interface
1/7/2020 • 2 minutes to read • Edit Online
When to implement
Implement this interface to enable remote debugging over RPC.
When to use
This interface should be used for in-process remote debugging when software exceptions should not be used
for the COM debugger notifications. It enables in-process debuggers to be notified by direct calls using these
methods.
Members
The IOrpcDebugNotify interface inherits from the IUnknown interface. IOrpcDebugNotify also has these
types of members:
Methods
Methods
The IOrpcDebugNotify interface has these methods.
METHOD DESCRIPTION
ClientFillBuffer Sends data from the client debugger to the server debugger.
ClientGetBufferSize Retrieves the RPC buffer size from the client-side debugger.
ServerFillBuffer Sends data from the server debugger to the client debugger.
ServerGetBufferSize Retrieves the RPC buffer size from the server-side debugger.
Remarks
An import library containing the IOrpcDebugNotify interface is not included in the Microsoft Windows
Software Development Kit (SDK). An application can use the GetProcAddress and GetModuleHandle
functions to retrieve a function pointer to DllDebugObjectRPCHook from oleaut.dll and provide these
methods via the IOrpcDebugNotify interface.
Requirements
Minimum supported client Windows 2000 Professional [desktop apps only]
Header
N/A
IDL
N/A
See also
I
U
n
k
n
o
w
n
O
R
P
C
_
D
B
G
_
A
L
L
O
R
P
C
_
D
B
G
_
B
U
F
F
E
R
O
R
P
C
_
I
N
I
T
_
A
R
G
S
D
l
l
D
e
b
u
g
O
b
j
e
c
t
R
P
C
H
o
o
k
IOrpcDebugNotify::ClientGetBufferSize method
1/7/2020 • 2 minutes to read • Edit Online
NOTE
An import library containing the ClientGetBufferSize function is not included in the Microsoft Windows Software
Development Kit (SDK). An application can use the GetProcAddress and GetModuleHandle functions to retrieve a
function pointer to DllDebugObjectRPCHook from oleaut.dll and provide this function via the IOrpcDebugNotify
interface.
Syntax
void ClientGetBufferSize(
ORPC_DBG_ALL *lpOrpcDebugAll
);
Parameters
l
p
O
r
p
c
D
e
b
u
g
A
l
l
A pointer to a ORPC_DBG_ALL structure that contains notification specific information the COM RPC
system passes to the debugger.
Return value
This method does not return a value.
Requirements
Header
N/A
IDL
N/A
See also
O
R
P
C
_
I
N
I
T
_
A
R
G
S
D
l
l
D
e
b
u
g
O
b
j
e
c
t
R
P
C
H
o
o
k
I
O
r
p
c
D
e
b
u
g
N
o
t
i
f
y
IOrpcDebugNotify::ClientFillBuffer method
1/7/2020 • 2 minutes to read • Edit Online
NOTE
An import library containing the ClientFillBuffer function is not included in the Microsoft Windows Software Development
Kit (SDK). An application can use the GetProcAddress and GetModuleHandle functions to retrieve a function pointer to
DllDebugObjectRPCHook from oleaut.dll and provide this function via the IOrpcDebugNotify interface.
Syntax
void ClientFillBuffer(
ORPC_DBG_ALL *lpOrpcDebugAll
);
Parameters
l
p
O
r
p
c
D
e
b
u
g
A
l
l
A pointer to a ORPC_DBG_ALL structure that contains notification specific information the COM RPC
system passes to the debugger.
Return value
This method does not return a value.
Requirements
Header
N/A
IDL
N/A
See also
D
l
l
D
e
b
u
g
O
b
j
e
c
t
R
P
C
H
o
o
k
I
O
r
p
c
D
e
b
u
g
N
o
t
i
f
y
IOrpcDebugNotify::ClientNotify method
1/7/2020 • 2 minutes to read • Edit Online
NOTE
An import library containing the ClientNotify function is not included in the Microsoft Windows Software Development Kit
(SDK). An application can use the GetProcAddress and GetModuleHandle functions to retrieve a function pointer to
DllDebugObjectRPCHook from oleaut.dll and provide this function via the IOrpcDebugNotify interface.
Syntax
void ClientNotify(
ORPC_DBG_ALL *lpOrpcDebugAll
);
Parameters
l
p
O
r
p
c
D
e
b
u
g
A
l
l
A pointer to a ORPC_DBG_ALL structure that contains notification specific information the COM RPC
system passes to the debugger.
Return value
This method does not return a value.
Requirements
Header
N/A
IDL
N/A
See also
O
R
P
C
_
I
N
I
T
_
A
R
G
S
D
l
l
D
e
b
u
g
O
b
j
e
c
t
R
P
C
H
o
o
k
I
O
r
p
c
D
e
b
u
g
N
o
t
i
f
y
IOrpcDebugNotify::ServerNotify method
1/7/2020 • 2 minutes to read • Edit Online
NOTE
An import library containing the ServerNotify function is not included in the Microsoft Windows Software Development
Kit (SDK). An application can use the GetProcAddress and GetModuleHandle functions to retrieve a function pointer to
DllDebugObjectRPCHook from oleaut.dll and provide this function via the IOrpcDebugNotify interface.
Syntax
void ServerNotify(
ORPC_DBG_ALL *lpOrpcDebugAll
);
Parameters
l
p
O
r
p
c
D
e
b
u
g
A
l
l
A pointer to a ORPC_DBG_ALL structure that contains notification specific information the COM RPC
system passes to the debugger.
Return value
This method does not return a value.
Requirements
Header
N/A
IDL
N/A
See also
O
R
P
C
_
I
N
I
T
_
A
R
G
S
D
l
l
D
e
b
u
g
O
b
j
e
c
t
R
P
C
H
o
o
k
I
O
r
p
c
D
e
b
u
g
N
o
t
i
f
y
IOrpcDebugNotify::ServerGetBufferSize method
1/7/2020 • 2 minutes to read • Edit Online
NOTE
An import library containing the ServerGetBufferSize function is not included in the Microsoft Windows Software
Development Kit (SDK). An application can use the GetProcAddress and GetModuleHandle functions to retrieve a
function pointer to DllDebugObjectRPCHook from oleaut.dll and provide this function via the IOrpcDebugNotify
interface.
Syntax
void ServerGetBufferSize(
ORPC_DBG_ALL *lpOrpcDebugAll
);
Parameters
l
p
O
r
p
c
D
e
b
u
g
A
l
l
A pointer to a ORPC_DBG_ALL structure that contains notification specific information the COM RPC
system passes to the debugger.
Return value
This method does not return a value.
Requirements
Header
N/A
IDL
N/A
See also
O
R
P
C
_
I
N
I
T
_
A
R
G
S
D
l
l
D
e
b
u
g
O
b
j
e
c
t
R
P
C
H
o
o
k
I
O
r
p
c
D
e
b
u
g
N
o
t
i
f
y
IOrpcDebugNotify::ServerFillBuffer method
1/7/2020 • 2 minutes to read • Edit Online
NOTE
An import library containing the ServerFillBuffer function is not included in the Microsoft Windows Software Development
Kit (SDK). An application can use the GetProcAddress and GetModuleHandle functions to retrieve a function pointer to
DllDebugObjectRPCHook from oleaut.dll and provide this function via the IOrpcDebugNotify interface.
Syntax
void ServerFillBuffer(
ORPC_DBG_ALL *lpOrpcDebugAll
);
Parameters
l
p
O
r
p
c
D
e
b
u
g
A
l
l
A pointer to a ORPC_DBG_ALL structure that contains notification specific information the COM RPC
system passes to the debugger.
Return value
This method does not return a value.
Requirements
Header
N/A
IDL
N/A
See also
O
R
P
C
_
I
N
I
T
_
A
R
G
S
D
l
l
D
e
b
u
g
O
b
j
e
c
t
R
P
C
H
o
o
k
I
O
r
p
c
D
e
b
u
g
N
o
t
i
f
y
Macros
1/7/2020 • 2 minutes to read • Edit Online
Registry values in the following registry keys control aspects of the functionality of COM:
HKEY_LOCAL_MACHINE\SOFTWARE\Classes
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
As of Windows Server 2003, COM uses only the current process token to decide which registry hive to access, not
the thread token. If COM is not able to access the user profile registry hive, it will access the
HKEY_LOCAL_MACHINE\System hive.
Related topics
R
e
g
i
s
t
r
y
HKEY_LOCAL_MACHINE\SOFTWARE\Classes
1/7/2020 • 2 minutes to read • Edit Online
The subkeys and registry values associated with the HKEY_LOCAL_MACHINE\SOFTWARE\Classes key
contain information about an application that is needed to support COM functionality. This information includes
such topics as supported data formats, compatibility information, programmatic identifiers, DCOM, and controls.
SUBKEY DESCRIPTION
Groups the configuration options for one or more DCOM objects into one centralized location in the registry.
DCOM objects hosted by the same executable are grouped into one AppID to simplify the management of
common security and configuration settings.
Registry Key
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID\{AppID_GUID }
AccessPermission Describes the Access Control List (ACL) of the principals that
can access instances of this class. This ACL is used only by
applications that do not call CoInitializeSecurity.
AuthenticationLevel Sets the authentication level for applications that do not call
CoInitializeSecurity or for applications that call
CoInitializeSecurity and specify an AppID.
LaunchPermission Describes the Access Control List (ACL) of the principals that
can start new servers for this class.
LoadUserSettings Determines whether COM will load the user profile for COM
servers running as the launching user application identity.
SRPTrustLevel Sets the software restriction policy (SRP) trust level for
applications.
Remarks
AppIDs are mapped to executables and classes using two different mechanisms:
Using a 128-bit Globally Unique Identifier (GUID ) that identifies the AppID key. A class indicates its
corresponding AppID under the CLSID key in a named value "AppID". This mapping is used during
activation.
Using a named value that indicates an executable name (such as "MYOLDAPP.EXE"). This named value is of
type REG_SZ and contains the string representation of the AppID associated with the executable. This
mapping is used to obtain the default access permissions and authentication level.
The HKEY_LOCAL_MACHINE\SOFTWARE\Classes key corresponds to the HKEY_CLASSES_ROOT key,
which was retained for compatibility with earlier versions of COM.
For COM servers, the mapping is usually generated and written to the registry during the registration process
or when running dcomcnfg.exe. However, COM clients that want to set security using the AppID key must
create appropriate registry keys and specify the required mapping by calling the registry functions or using
Regedit.exe. Then values such as AccessPermission or AuthenticationLevel can be set for the client. For
example, suppose the name of your executable for your client process is "YourClient.exe" and you want to set
the authentication level to "None". You would use Guidgen.exe or Uuidgen.exe to create the GUID that is the
AppID for your executable. Then you would set values in the registry as shown in the following example, where
00000001 represents an authentication level of "None":
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID
{MyGuid}
AuthenticationLevel = 00000001
MyClient.exe
AppID = {MyGUID}
AccessPermission
1/7/2020 • 2 minutes to read • Edit Online
Describes the Access Control List (ACL ) of the principals that can access instances of this class. This ACL is used
only by applications that do not call CoInitializeSecurity.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID
{AppID_GUID}
AccessPermission = ACL
Remarks
This is a REG_BINARY value. It contains data describing the Access Control List (ACL ) of the principals that can
access instances of this class. Upon receiving a request to connect to an existing object of this class, the ACL is
checked by the application being called while impersonating the caller. If the access-check fails, the connection is
disallowed. If this named value does not exist, the DefaultAccessPermission ACL is tested to determine whether
the connection is to be allowed.
For applications that do not call CoInitializeSecurity or do not use the IGlobalOptions interface to specify the
AppID, the executable of the application's binary must be mapped to the AppID of the application as described in
AppID. This is required so that COM can locate the AppID of the application.
Related topics
C
o
I
n
i
t
i
a
l
i
z
e
S
e
c
u
r
i
t
y
D
e
f
a
u
l
t
A
c
c
e
s
s
P
e
r
m
i
s
s
i
o
n
S
e
c
u
r
i
t
y
i
n
C
O
M
ActivateAtStorage
1/7/2020 • 2 minutes to read • Edit Online
Configures the client to instantiate objects on the same computer as the persistent state they are using or from
which they are initialized.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID
{AppID_GUID}
ActivateAtStorage = value
Remarks
This is a REG_SZ value. Any value that begins with 'Y' or 'y' indicates that ActivateAtStorage should be used.
The ActivateAtStorage capability provides a transparent way to allow clients to locate running objects on the
same computer as the data that they use. This reduces network traffic because the object performs local file-system
calls instead of calls across the network.
When a value is set for ActivateAtStorage, this becomes the default behavior in calls to the
CoGetInstanceFromFile and CoGetInstanceFromIStorage functions, as well as to the file moniker
implementation of IMoniker::BindToObject. In all of these calls, specifying a COSERVERINFO structure
overrides the setting of ActivateAtStorage for the duration of the function call. The caller can pass
COSERVERINFO information to IMoniker::BindToObject through the BIND_OPTS2 structure.
The value set for ActivateAtStorage is also the default behavior when CLSCTX_REMOTE_SERVER is specified if
no registry information for the class is installed on the client's computer. Client applications written to take
advantage of ActivateAtStorage may therefore require less administration.
Related topics
C
L
S
C
T
X
C
o
G
e
t
I
n
s
t
a
n
c
e
F
r
o
m
F
i
l
e
C
o
G
e
t
I
n
s
t
a
n
c
e
F
r
o
m
I
S
t
o
r
a
g
e
C
O
S
E
R
V
E
R
I
N
F
O
I
M
o
n
i
k
e
r
:
:
B
i
n
d
T
o
O
b
j
e
c
t
R
e
g
i
s
t
e
r
i
n
g
C
O
M
S
e
r
v
e
r
s
AppID
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID
<Executable_name>
AppID = {AppID_GUID}
Remarks
This is a REG_SZ value.
Related topics
A
p
p
I
D
K
e
y
AppIDFlags
1/7/2020 • 4 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID
{AppID_GUID}
AppIDFlags = flags
Remarks
This is a REG_DWORD value.
0x1 APPIDREGFLAGS_ACTIVATE_IUSERVER_INDESKTOP
0x2 APPIDREGFLAGS_SECURE_SERVER_PROCESS_SD_AND_BIND
0x4 APPIDREGFLAGS_ISSUE_ACTIVATION_RPC_AT_IDENTIFY
APPIDREGFLAGS_ACTIVATE_IUSERVER_INDESKTOP Description
If the APPIDREGFLAGS_ACTIVATE_IUSERVER_INDESKTOP flag is cleared in AppIDFlags or if AppIDFlags
is not present, the client in a terminal server session making an activation request for an Interactive User COM
server, will either bind to, or launch and bind to, the COM server in the "default" desktop of the "winsta0" window
station of the session in the activation request. For example, if the client is running "winsta0\desktop1" of session 3,
the activation request for session 3 will either bind to, or launch and bind to, the COM server in "winsta0\default"
of session 3, even if an instance of the COM server is already running in "winsta0\desktop1" of session 3.
If the APPIDREGFLAGS_ACTIVATE_IUSERVER_INDESKTOP flag is set in the AppIDFlags value, COM will
either bind to, or launch and bind to, the server process running in the client's desktop and the session in the
activation request. For example, if the client is running "winsta0\desktop1" in session 3, the activation request for
session 3 will either bind to, or launch and bind to, the COM server in "winsta0\desktop1" in session 3, even if an
instance of the COM server is already running in "winsta0\default" in session 3.
The client can use the session moniker to specify a session different than the client's session when it makes the
activation request.
The APPIDREGFLAGS_ACTIVATE_IUSERVER_INDESKTOP flag applies only to COM servers that are
configured to RunAs "Interactive User".
APPIDREGFLAGS_SECURE_SERVER_PROCESS_SD_AND_BIND Description
If the APPIDREGFLAGS_SECURE_SERVER_PROCESS_SD_AND_BIND flag is set in AppIDFlags, COM
servers that are configured to RunAs "Activator" will be launched with a process security descriptor that allows
PROCESS_ALL_ACCESS to the LogonID SID of the process token. In addition, the owner of the security descriptor
will be set to the LogonID SID of the process token.
If the APPIDREGFLAGS_SECURE_SERVER_PROCESS_SD_AND_BIND flag is set in AppIDFlags, COM
servers that are configured to RunAs "This User" will be launched with a process security descriptor that allows
PROCESS_ALL_ACCESS in the LogonID SID of the process token. In addition, the owner of the security descriptor
will be set to the LogonID SID of the process token. Further, the COM Service Control Manager (SCM ) modifies
the token of the COM server process as follows:
It adds an APPID SID to the token. It grants the APPID SID full access in the token default discretionary access
control list (DACL ). In Windows Vista and later versions of Windows, it grants the OwnerRights SID
READ_CONTROL permission in the token default DACL. In pre-Windows Vista versions of Windows, it sets the
token owner to the APPID SID.
The following security considerations must be taken into account when using the
APPIDREGFLAGS_SECURE_SERVER_PROCESS_SD_AND_BIND flag:
The APPIDREGFLAGS_SECURE_SERVER_PROCESS_SD_AND_BIND flag is meant to be set by COM
servers that are launched under one of the built-in service security contexts; either the NetworkService or the
LocalService accounts. If the servers impersonate privileged clients and if the
APPIDREGFLAGS_SECURE_SERVER_PROCESS_SD_AND_BIND flag is not set, malicious code running in
other processes with the same security context can elevate privilege by hijacking the impersonation tokens of
the privileged clients from the COM server process.
When the APPIDREGFLAGS_SECURE_SERVER_PROCESS_SD_AND_BIND flag is set, COM hardens the
security descriptor of the process object in the case of RunAs "Activator" COM servers. For such servers, the
COM client is expected to harden the token that it uses for the COM activation.
When the APPIDREGFLAGS_SECURE_SERVER_PROCESS_SD_AND_BIND flag is set, COM hardens the
security descriptor of the process object in the case of RunAs "This User" COM servers. It also hardens the
process token of the COM server since the COM SCM is the entity that creates the token.
The APPIDREGFLAGS_SECURE_SERVER_PROCESS_SD_AND_BIND flag is supported in Windows XP,
Windows Server 2003, Windows Vista, and Windows Server 2008 only when the MSRC8322 patch (security
bulletin MS09-012) is applied. It is natively supported in Windows 7 and later versions of Windows.
The APPIDREGFLAGS_SECURE_SERVER_PROCESS_SD_AND_BIND flag applies only to COM servers that
are configured to RunAs "Activator" or "This User". It does not apply to COM servers that are NT services.
APPIDREGFLAGS_ISSUE_ACTIVATION_RPC_AT_IDENTIFY Description
If the APPIDREGFLAGS_ISSUE_ACTIVATION_RPC_AT_IDENTIFY flag is set in AppIDFlags, the COM SCM
will issue object activation requests to the COM server process using an impersonation level of
RPC_C_IMP_LEVEL_IDENTIFY.
If the APPIDREGFLAGS_ISSUE_ACTIVATION_RPC_AT_IDENTIFY flag is not set, the COM SCM will issue
object activation requests to the COM server processes using an impersonation level of
RPC_C_IMP_LEVEL_IMPERSONATE.
The following security considerations must be taken into account when using the
APPIDREGFLAGS_ISSUE_ACTIVATION_RPC_AT_IDENTIFY flag:
The APPIDREGFLAGS_ISSUE_ACTIVATION_RPC_AT_IDENTIFY flag is meant to be used by COM servers
that do not perform work on behalf of clients in object activation requests. For such servers, having the COM
SCM issue object activation requests at RPC_C_IMP_LEVEL_IDENTIFY minimizes the chances of privileged
tokens with SE_IMPERSONATE_NAME level appearing in the process.
The APPIDREGFLAGS_ISSUE_ACTIVATION_RPC_AT_IDENTIFY flag is supported in Windows 7 and later
versions of Windows.
Related topics
D
e
s
k
t
o
p
s
I
m
p
e
r
s
o
n
a
t
i
o
n
L
e
v
e
l
s
I
n
t
e
r
a
c
t
i
v
e
U
s
e
r
S
e
s
s
i
o
n
M
o
n
i
k
e
r
s
W
i
n
d
o
w
S
t
a
t
i
o
n
s
AuthenticationLevel
1/7/2020 • 2 minutes to read • Edit Online
Sets the authentication level for applications that do not call CoInitializeSecurity or for applications that call
CoInitializeSecurity and specify an AppID.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID
{AppID_GUID}
AuthenticationLevel = value
Remarks
This is a REG_DWORD value that is equivalent to the RPC_C_AUTHN_LEVEL constants.
VALUE CONSTANT
1 RPC_C_AUTHN_LEVEL_NONE
2 RPC_C_AUTHN_LEVEL_CONNECT
3 RPC_C_AUTHN_LEVEL_CALL
4 RPC_C_AUTHN_LEVEL_PKT
5 RPC_C_AUTHN_LEVEL_PKT_INTEGRITY
6 RPC_C_AUTHN_LEVEL_PKT_PRIVACY
Related topics
A
u
t
h
e
n
t
i
c
a
t
i
o
n
L
e
v
e
l
C
o
n
s
t
a
n
t
s
L
e
g
a
c
y
A
u
t
h
e
n
t
i
c
a
t
i
o
n
L
e
v
e
l
R
e
g
i
s
t
e
r
i
n
g
C
O
M
S
e
r
v
e
r
s
S
e
c
u
r
i
t
y
i
n
C
O
M
DllSurrogate
1/7/2020 • 2 minutes to read • Edit Online
Enables DLL servers to run in a surrogate process. If an empty string is specified, the system-supplied surrogate
is used; otherwise, the value specifies the path of the surrogate to be used.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID
{AppID_GUID}
DllSurrogate = path
Remarks
This is a REG_SZ value that specifies that the class is a DLL that is to be activated in a surrogate process, and the
surrogate process to be used. To use the system-supplied generic surrogate process, set path to an empty string
or NULL. To specify another surrogate process, set path to the path of the surrogate. As in the specification of the
path of a server under the LocalServer32 key, a full path specification is not necessary. The surrogate must be
written to properly communicate with the DCOM service as described in Writing a Custom Surrogate.
The DllSurrogate value must be present for a DLL server to be activated in a surrogate. Activation refers to a call
to CoGetClassObject, CoCreateInstanceEx, CoCreateInstanceEx, CoGetInstanceFromFile,
CoGetInstanceFromIStorage, or IMoniker::BindToObject. Running DLLs in a surrogate process provides the
benefits of an executable implementation, including fault isolation, the ability to serve multiple clients
simultaneously, and allowing the server to provide services to remote clients in a distributed environment.
Related topics
C
o
R
e
g
i
s
t
e
r
S
u
r
r
o
g
a
t
e
D
L
L
S
u
r
r
o
g
a
t
e
s
D
l
l
S
u
r
r
o
g
a
t
e
E
x
e
c
u
t
a
b
l
e
I
S
u
r
r
o
g
a
t
e
DllSurrogateExecutable
1/7/2020 • 2 minutes to read • Edit Online
Enables DLL servers to run in a custom surrogate process, in conjunction with the DllSurrogate registry value. If
DllSurrogateExecutable is not specified, COM passes NULL as the value for the first parameter of the
CreateProcess function.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID
{AppID_GUID}
DllSurrogateExecutable = file
Remarks
This value is of type REG_SZ. It works in conjunction with the DllSurrogate value to prevent any ambiguity when
using the CreateProcess function. DllSurrogate indicates whether a custom surrogate needs to be used, and this
information is passed as the first parameter for CreateProcess. Depending on the implementation of
CreateProcess, this information might be ambiguous. If DllSurrogateExecutable is specified, COM passes the
value as the first parameter of CreateProcess. If DllSurrogateExecutable is not specified, COM passes NULL as
the value for the first parameter of CreateProcess.
Related topics
C
o
R
e
g
i
s
t
e
r
S
u
r
r
o
g
a
t
e
D
L
L
S
u
r
r
o
g
a
t
e
s
D
l
l
S
u
r
r
o
g
a
t
e
I
S
u
r
r
o
g
a
t
e
Endpoints
1/7/2020 • 2 minutes to read • Edit Online
Configures a COM application to use a specified TCP port number for DCOM communications.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID
{AppID_GUID}
Endpoints = ncacn_ip_tcp,0,port
Remarks
This is a REG_MULTI_SZ value.
The port value is a number between 1024 and 65535 that specifies the TCP port number that your COM
application will use for DCOM communications. If you do not specify this registry key, port numbers for DCOM
communications are dynamically assigned. In most scenarios, you might prefer to leave this registry key undefined
and allow DCOM to dynamically assign port numbers.
LaunchPermission
1/7/2020 • 2 minutes to read • Edit Online
Describes the Access Control List (ACL ) of the principals that can start new servers for this class. This value may
be added under any AppID key to limit activation by remote clients of specific classes.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID
{AppID_GUID}
LaunchPermission = ACL
Remarks
This is a REG_BINARY value. Upon receiving a local or remote request to launch the server of this class, the ACL
described by this value is checked while impersonating the client, and its success either allows or disallows the
launching of the server. If this value does not exist, the DefaultLaunchPermission value is checked in the same
way to determine whether the class code can be launched.
Related topics
C
o
I
n
i
t
i
a
l
i
z
e
S
e
c
u
r
i
t
y
D
e
f
a
u
l
t
L
a
u
n
c
h
P
e
r
m
i
s
s
i
o
n
S
e
c
u
r
i
t
y
i
n
C
O
M
LoadUserSettings
1/7/2020 • 2 minutes to read • Edit Online
Determines whether COM will load the user profile for COM servers running as the launching user application
identity.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID
{AppID_GUID}
LoadUserSettings = value
Remarks
This is a REG_DWORD value. If value is nonzero, COM loads the profile of the user account with which it launches
the COM server. If value is zero or not present, COM will not load the profile of the user account with which it
launches the COM server.
This setting is ignored if a RunAs entry is present.
LocalService
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID
{AppID_GUID}
LocalService = name
Remarks
In addition to running as a local server executable (EXE ), a COM object may also choose to package itself to run
as a service application when activated by a local or remote client. Services support numerous useful and UI-
integrated administrative features, including local and remote starting, stopping, pausing, and restarting, as well
as the ability to establish the server to run under a specific user account and window station.
An object written as a service is installed for use by COM by establishing a LocalService value and performing a
standard service installation. The LocalService value must be set to the service name, as configured in
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services, as the default REG_SZ value.
When LocalService is set, any string assigned to ServiceParameters is passed as a command-line argument to
the service as it is being launched.
The service configuration is preferred in many situations where the capabilities of the local and remote service
management APIs and user interface might be useful for the services that the object provides. For example,
leveraging the existing administrative framework of the service architecture should be an obvious choice if the
object is long-lived or readily supports concepts such as starting, stopping, resetting, or pausing.
Services can be dynamically configured and can be configured to run automatically when the machine boots, or to
be launched when requested by a client application.
If you are implementing classes as services, you should be aware of the following points:
This value is used in preference to the LocalServer32 key for local and remote activation requests—if
LocalService exists and refers to a valid service, the LocalServer32 key is ignored.
Currently, only a single instance of a service application may be running at a given time on a computer. COM
services must therefore register their class objects on launch using REGCLS_MULTIPLEUSE to support
multiple clients.
To launch and initialize properly, COM services configured to run automatically when a machine boots must
include RPCSS in their list of dependent services.
Related topics
R
e
g
i
s
t
e
r
i
n
g
C
O
M
S
e
r
v
e
r
s
S
e
r
v
i
c
e
P
a
r
a
m
e
t
e
r
s
S
e
r
v
i
c
e
s
PreferredServerBitness
1/7/2020 • 2 minutes to read • Edit Online
Sets the preferred architecture, 32-bit or 64-bit, for this COM server.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID
{AppID_GUID}
PreferredServerBitness = value
Remarks
This is a REG_DWORD value that is available only on 64-bit versions of Windows.
VALUE DESCRIPTION
2 Use a 32-bit version of the server. If one does not exist, the
client's activation request will fail.
3 Use a 64-bit version of the server. If one does not exist, the
client's activation request will fail.
Related topics
C
L
S
C
T
X
RemoteServerName
1/7/2020 • 2 minutes to read • Edit Online
Configures the client to request the object be run at a particular computer whenever an activation function is
called for which a COSERVERINFO structure is not specified.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID
{AppID_GUID}
RemoteServerName = name
Remarks
RemoteServerName allows simple configuration management of client applications; they may be written
without hard-coded server names and can be configured by modifying the RemoteServerName registry values
of the classes of objects they use.
As described in the documentation for the CLSCTX enumeration and the COSERVERINFO structure, one of the
parameters of the distributed COM activation is a pointer to a COSERVERINFO structure. When this value is not
NULL, the information in the COSERVERINFO structure overrides the setting of the RemoteServerName key
for the function call.
Related topics
R
e
g
i
s
t
e
r
i
n
g
C
O
M
S
e
r
v
e
r
s
ROTFlags
1/7/2020 • 2 minutes to read • Edit Online
Controls the registration of a COM server in the running object table (ROT).
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID
{AppID_GUID}
ROTFlags = flags
Remarks
This is a REG_DWORD value.
0x1 ROTREGFLAGS_ALLOWANYCLIENT
ROTREGFLAGS_ALLOWANYCLIENT Description
If a COM server wants to register in the ROT and allow any client to access the registration, it must use the
ROTFLAGS_ALLOWANYCLIENT flag. An "Activate As Activator" COM server cannot specify
ROTFLAGS_ALLOWANYCLIENT because the DCOM service control manager (DCOMSCM ) enforces a spoof
check against this flag. Therefore, in Windows Vista and later, COM adds support for the ROTFlags registry entry
that allows the server to stipulate that its ROT registrations be made available to any client.
The entry must exist in the HKEY_LOCAL_MACHINE hive. This entry provides an "Activate As Activator" server
with the same functionality that ROTFLAGS_ALLOWANYCLIENT provides for a RunAs server.
Related topics
A
p
p
I
D
K
e
y
R
e
g
i
s
t
e
r
i
n
g
C
O
M
S
e
r
v
e
r
s
S
e
c
u
r
i
t
y
i
n
C
O
M
RunAs
1/7/2020 • 2 minutes to read • Edit Online
Configures a class to run under a specific user account when activated by a remote client without being written as
a service application.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID
{AppID_GUID}
RunAs = value
Remarks
The value specifies the user name and must be either of the form UserName, Domain**\**UserName or of the
string "Interactive User". You can also specify the strings "nt authority\localservice" (for Local Service) and "nt
authority\networkservice" (for Network Service). You can also specify the string "nt authority\system" when
{AppID_GUID} refers to a COM server that is already started or that has an entry in the class table. However, you
cannot use "nt authority\system" with a COM server that is not already started. The default password for "nt
authority\localservice", "nt authority\networkservice", and "nt authority\system" is "" (empty string).
NOTE
As of Windows Vista, an empty password is no longer required to configure the "nt authority\localservice", "nt
authority\networkservice" and "nt authority\system" RunAs settings.
Classes configured to run as a particular user may not be registered under any other identity, so calls to
CoRegisterClassObject with this CLSID fail unless the process was launched by COM on behalf of an actual
activation request.
The user-name is taken from the RunAs value under the class's AppID key. If the user name is "Interactive User",
the server is run in the identity of the user currently logged on and is connected to the interactive desktop.
Otherwise, the password is retrieved from a portion of the registry that is available only to administrators of the
computer and to the system. The user-name and password are then used to create a logon session in which the
server is run. When launched in this way, the user runs with its own desktop and window station and does not
share window -handles, the clipboard, or other UI elements with the interactive user or other user running in other
user accounts.
To establish a password for a RunAs class, you must use the DCOMCNFG administrative tool installed in the
system directory.
For RunAs identities used by DCOM servers, the user account specified in the value must have the rights to log
on as a batch job. This right can be added using Local Security Policy administrative tool. Go to Local Policies
and open User Rights Assignment. Select Log on as a batch job, and add the user account.
The RunAs value is not used for servers configured to be run as services. COM services that need to run under an
identity other than LocalSystem should set the appropriate user name and password using the services control
panel applet or the service controller functions. (For more information about these functions, see Services.)
NOTE
As of Microsoft Windows Server 2003, the class AppID is explicitly read from
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID, which, unlike most registry keys, is not interchangeable with
HKEY_CLASSES_ROOT\AppID.
Related topics
R
e
g
i
s
t
e
r
i
n
g
C
O
M
S
e
r
v
e
r
s
ServiceParameters
1/7/2020 • 2 minutes to read • Edit Online
Specifies the command-line parameters to be passed to an object installed for use by COM through the
LocalService registry value.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID
{AppID_GUID}
ServiceParameters = parameter
Remarks
This is a REG_SZ value. This string is passed to the service as a command-line argument as it is being launched.
Related topics
L
o
c
a
l
S
e
r
v
i
c
e
R
e
g
i
s
t
e
r
i
n
g
C
O
M
S
e
r
v
e
r
s
SRPTrustLevel
1/7/2020 • 2 minutes to read • Edit Online
Sets the software restriction policy (SRP ) trust level for applications.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID
{AppID_GUID}
SRPTrustLevel = value
Remarks
This is a REG_DWORD value that is available starting with Windows XP.
VALUE DESCRIPTION
0x40000 (SAFE_LEVELID_FULLYTRUSTED) The application has unrestricted access to the user's privileges.
If the SRPTrustLevel value does not exist, the default value of SAFER_LEVELID_DISALLOWED is used. If
SRPTrustLevel is of the wrong type or out of range, COM returns the error COMADMIN_E_SAFERINVALID. If
an activation of any sort fails because of SRP trust checks, COM returns the error CO_E_ACTIVATIONFAILED.
Related topics
S
e
c
u
r
i
t
y
i
n
C
O
M
S
R
P
A
c
t
i
v
a
t
e
A
s
A
c
t
i
v
a
t
o
r
C
h
e
c
k
s
S
R
P
R
u
n
n
i
n
g
O
b
j
e
c
t
C
h
e
c
k
s
CLSID Key
1/7/2020 • 2 minutes to read • Edit Online
A CLSID is a globally unique identifier that identifies a COM class object. If your server or container allows linking
to its embedded objects, you need to register a CLSID for each supported class of objects.
Registry Key
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{CLSID }
AutoTreatAs Automatically sets the CLSID for the TreatAs key to the
specified value.
Insertable Indicates that objects of this class should appear in the Insert
Object dialog box list box when used by COM container
applications.
TreatAs Specifies the CLSID of a class that can emulate the current
class.
Remarks
The HKEY_LOCAL_MACHINE\SOFTWARE\Classes key corresponds to the HKEY_CLASSES_ROOT key,
which was retained for compatibility with earlier versions of COM.
The CLSID key contains information used by the default COM handler to return information about a class when it
is in the running state.
To obtain a CLSID for your application, you can use the Uuidgen.exe, or use the CoCreateGuid function.
The CLSID is a 128-bit number, in hex, within a pair of curly braces.
Related topics
C
o
C
r
e
a
t
e
G
u
i
d
AppID
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
AppID = {AppID_GUID}
Remarks
This is a REG_SZ value.
Related topics
A
p
p
I
D
K
e
y
AutoConvertTo
1/7/2020 • 2 minutes to read • Edit Online
Specifies the automatic conversion of a given class of objects to a new class of objects.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
AutoConvertTo = value
Remarks
This is a REG_SZ value that specifies the class identifier of the object to which the given object or class of objects
should be converted.
This key is typically used to automatically convert files created by an older version of an application to a newer
version of the application.
Related topics
O
l
e
D
o
A
u
t
o
C
o
n
v
e
r
t
O
l
e
G
e
t
A
u
t
o
C
o
n
v
e
r
t
O
l
e
S
e
t
A
u
t
o
C
o
n
v
e
r
t
AutoTreatAs
1/7/2020 • 2 minutes to read • Edit Online
Automatically sets the CLSID for the TreatAs key to the specified value.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
AutoTreatAs = value
Remarks
This is a REG_SZ value that specifies the class identifier.
Related topics
C
o
T
r
e
a
t
A
s
C
l
a
s
s
AuxUserType
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
AuxUserType
2 = ShortDisplayName
3 = ApplicationName
Remarks
The recommended maximum length for ShortDisplayName is 15 characters. This name is used in menus, including
pop-up menus.
ApplicationName should contain the actual name of the application (such as "Acme Draw 2.0"). This name is used
in the Results field of the Paste Special dialog box.
Related topics
I
O
l
e
O
b
j
e
c
t
:
:
G
e
t
U
s
e
r
T
y
p
e
Control
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
Control
Remarks
This optional entry is used by containers to fill in dialog boxes. The container uses this subkey to determine
whether to include an object in a dialog box that displays ActiveX Controls. A control can omit this entry if it is
designed to work only with a specific container and therefore does is not intended to be inserted in other
containers.
Conversion
1/7/2020 • 2 minutes to read • Edit Online
Used by the Convert dialog box to determine the formats an application can read and write.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
Conversion
Readable
Main = rformat, ...
ReadWritable
Main = rwformat, ...
Remarks
Conversion information is used by the Convert dialog box to determine what formats an application can read and
write. A comma-delimited file format is indicated by a number if it is one of the Clipboard formats defined in
Windows.h. A string indicates the format is not one defined in Windows.h (private). In this case, the readable and
writable format is CF_OUTLINE (private).
The rformat value specifies the file format an application can read (convert from).
The rwformat value specifies the file format an application can read and write (activate as).
DataFormats
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
DataFormats
DefaultFile = file/format
GetSet
n = formats
Remarks
The file/format value specifies the default main file or object format for objects of this class.
The formats value specifies a list of formats for default implementations of EnumFormatEtc, where n is a zero-
based integer index. For example, n = format, aspect, medium, flag, where format is a clipboard format, aspect is
one or more members of DVASPECT, medium is one or more members of TYMED, and flag is one or more
members of DATADIR.
Related topics
I
D
a
t
a
O
b
j
e
c
t
:
:
E
n
u
m
F
o
r
m
a
t
E
t
c
I
D
a
t
a
O
b
j
e
c
t
:
:
G
e
t
D
a
t
a
I
D
a
t
a
O
b
j
e
c
t
:
:
S
e
t
D
a
t
a
DefaultIcon
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
DefaultIcon = path, resourceID
Remarks
This is a REG_SZ value that specifies the full path to the executable name of the object application and the
resource index of the icon within the executable.
DefaultIcon identifies the icon to use when, for example, a control is minimized to an icon. This entry contains the
full path to the executable name of the server application and the resource index of the icon within the executable.
Applications can use the information provided by DefaultIcon to obtain an icon handle with ExtractIcon.
InprocHandler
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
InprocHandler = handler.dll
Remarks
This is a REG_SZ value that specifies the custom handler used by the application. If a custom handler is not used,
the entry should be set to Ole32.dll.
If a container is searching the registry for a custom handler, the 16-bit version has priority with a 16-bit container
and the 32-bit version has priority with a 32-bit container.
Related topics
I
n
p
r
o
c
H
a
n
d
l
e
r
3
2
InprocHandler32
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
InprocHandler32 = handler.dll
Remarks
This is a REG_SZ value that specifies the custom handler used by the application. If a custom handler is not used,
the entry should be set to Ole32.dll.
If a container is searching the registry for a custom handler, the 16-bit version has priority with a 16-bit container
and the 32-bit version has priority with a 32-bit container.
Related topics
I
n
p
r
o
c
H
a
n
d
l
e
r
InprocServer
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
InprocServer
(Default) = path
Remarks
The InprocServer entry is relatively rare for insertable classes.
In-process servers are currently registered using the InprocServer registry entry. The 32-bit and 64-bit in-
process servers should use the InprocServer32 entry. If a container is searching the registry for an in-process
server, the 16-bit version has priority with a 16-bit container and 32-bit version has priority with a 32-bit container.
Related topics
I
n
p
r
o
c
S
e
r
v
e
r
3
2
InprocServer32
1/7/2020 • 2 minutes to read • Edit Online
Registers a 32-bit in-process server and specifies the threading model of the apartment the server can run in.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
InprocServer32
(Default) = path
ThreadingModel = value
Remarks
ThreadingModel is a REG_SZ value the specifies the threading model. The possible values are shown in the
following table.
VALUE DESCRIPTION
You must use the same value for every object provided by the in-process server.
If ThreadingModel is not present or is not set to a value, the server is loaded into the first apartment that was
initialized in the process. This apartment is sometimes referred to as the main single-threaded apartment (STA).
If the first STA in a process is initialized by COM, rather than by an explicit call to CoInitialize or
CoInitializeEx, it is called the host STA. For example, COM creates a host STA if an in-process server to be
loaded requires an STA but there is currently no STA in the process.
Whenever possible, the in-process server is loaded in the same apartment as the client that loads it. If the
threading model of the client apartment is not compatible with the model specified, the server is loaded as
indicated in the following table.
Main STA
If the threading model of the server is Apartment, the apartment the server is loaded in depends on the
apartment the client is running in, as indicated in the following table.
COM can also create a host multithreaded apartment (MTA). If a client in a single-threaded apartment requests
an in-process server whose threading model is Free when there is no MTA in the process, COM creates a host
MTA and loads the server into it.
For a 32-bit in-process server, the InprocHandler32, InprocServer, InprocServer32, and Insertable keys
must be registered. The InprocServer entry is needed only for backward compatibility. If it is missing, the class
still works but it cannot be loaded in 16-bit applications.
If a container is searching the registry for an in-process server, the 16-bit version has priority with a 16-bit
container and the 32-bit version has priority with a 32-bit container.
Related topics
I
n
p
r
o
c
S
e
r
v
e
r
Insertable
1/7/2020 • 2 minutes to read • Edit Online
Indicates that objects of this class should appear in the Insert Object dialog box list box when used by COM
container applications.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
Insertable
Remarks
This key is a required entry for 32-bit COM applications whose objects can be inserted into existing 16-bit
applications. Existing 16-bit applications look in the registry for this key, which informs the application that the
server supports embeddings. If the Insertable key exists, 16-bit applications may also attempt to verify that the
server exists on the machine. 16-bit applications typically retrieve the value of the LocalServer key from the class
and check to see whether it is a valid file on the system. Therefore, for a 32-bit application to be insertable by a 16-
bit application, the 32-bit application should register the LocalServer subkey in addition to registering
LocalServer32.
Used with controls, this entry indicates that an object can act only as an in-place embedded object with no special
control features. Objects that have this key appear in the Insert Object dialog box for their container. When used
with controls, this entry also indicates the control has been tested with non-control containers. This entry is also
optional and can be omitted when a control is not designed to work with older containers that do not understand
controls.
NOTE
This key is not present for internal classes like the moniker classes.
Related topics
Interface
1/7/2020 • 2 minutes to read • Edit Online
An optional entry that specifies all interface IDs (IIDs) supported by the associated class.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
Interface
{IID1} = name1
{IID2} = name2
...
Remarks
If an interface name is not present in this list, the interface can never be supported by an instance of this class.
Related topics
I
n
t
e
r
f
a
c
e
K
e
y
LocalServer
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
LocalServer = path
Remarks
This is a REG_SZ value that specifies the full path and can include any command-line arguments.
COM appends the "-Embedding" flag to the string, so the application that uses flags must parse the whole string
and check for the -Embedding flag.
To run a COM object server in a separate memory space, change the value of LocalServer as follows:
cmd /c start /separate path**.exe**
Related topics
L
o
c
a
l
S
e
r
v
e
r
3
2
LocalServer32
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
LocalServer32
(Default) = path
ServerExecutable = path
Remarks
The ServerExecutable value, which is of type REG_SZ and is supported starting with Windows Server 2003,
works in conjunction with the LocalServer32 subkey to prevent any ambiguity when using the CreateProcess
function. LocalServer32 specifies the location of the COM server application to launch, and this information is
passed as the first parameter lpApplicationName for CreateProcess. Depending on the implementation of
CreateProcess, this information might be ambiguous. For this reason, if ServerExecutable is specified, COM
passes the ServerExecutable named value to the lpApplicationName parameter of CreateProcess. If
ServerExecutable is not specified, COM passes NULL as the value for the first parameter of CreateProcess.
To help provide system security, use quoted strings in the path to indicate where the executable filename ends
and the arguments begin. For example, instead of specifying the following path as the LocalServer32 entry:
"C:\Program Files\Company Files\Application.exe param1 param2"
specify the path using the following syntax:
"\"C:\Program Files\Company Files\Application.exe\" param1 param2"
COM appends the "-Embedding" flag to the string, so the application that uses flags needs to parse the whole
string and check for the -Embedding flag.
When COM starts a 32-bit local server, the server must register a class object within an elapsed time set by the
user. By default, the elapsed time value must be at least 5 minutes, in milliseconds, but cannot exceed the number
of milliseconds in 30 days. Applications typically should not set this value, which is in the
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\COM2\ServerStartElapsedTime entry.
The required entries for 32-bit local servers are InprocHandler32, LocalServer, LocalServer32, and
Insertable.
If a container is searching the registry for a local server, a 32-bit local server has priority over a 16-bit local
server.
If you are implementing classes as services, you should be aware that the LocalService named value is used in
preference to the LocalServer32 key for local and remote activation requests—if LocalService exists and
refers to a valid service, the LocalServer32 key is ignored.
Related topics
L
o
c
a
l
S
e
r
v
e
r
L
o
c
a
l
S
e
r
v
i
c
e
MiscStatus
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
MiscStatus
(Default) = value
aspect = value
Remarks
For more information, see the OLEMISC enumeration and IOleObject::GetMiscStatus.
If no subkey that corresponds to a DVASPECT is found, the default value of MiscStatus is used.
Related topics
I
O
l
e
O
b
j
e
c
t
:
:
G
e
t
M
i
s
c
S
t
a
t
u
s
ProgID
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
ProgID = value
Remarks
Every insertable object class has a ProgID. For information on creating a ProgID, see the key.
Related topics
k
e
y
V
e
r
s
i
o
n
I
n
d
e
p
e
n
d
e
n
t
P
r
o
g
I
D
ToolBoxBitmap32
1/7/2020 • 2 minutes to read • Edit Online
Identifies the module name and resource ID for a 16 x 16 bitmap to use for the face of a toolbar or toolbox button.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
ToolBoxBitmap32 = filename, resourceID
Remarks
This is a REG_SZ value that specifies the module name and resource identifier for the bitmap.
The standard Windows icon size is too large to be used for this purpose. This requires control containers that have
a design mode in which one selects controls and places them on a form being designed.
TreatAs
1/7/2020 • 2 minutes to read • Edit Online
Specifies the CLSID of a class that can emulate the current class.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
TreatAs = {CLSID_TreatAs}
Remarks
This is a REG_SZ value.
Emulation is the ability of one application to open and edit an object of a different class, while retaining the
original format of the object. Resolution occurs on the local computer, so in remote activation case, resolution
occurs on the client computer using the CLSID specified by TreatAs.
DCOM looks at the local registry for TreatAs, even if you call the CoCreateInstance function and specify a
remote server. This means that if you have a TreatAs entry for Class1 to be treated as Class2 on your local
computer, but you call CoCreateInstance to create an instance of Class1 and you specify a remote server, DCOM
will try to create an instance of Class2 on the remote server, even if Class2 is not registered on the remote server,
which will cause the call to CoCreateInstance to fail.
Related topics
A
u
t
o
T
r
e
a
t
A
s
C
o
G
e
t
T
r
e
a
t
A
s
C
l
a
s
s
C
o
T
r
e
a
t
A
s
C
l
a
s
s
Verb
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
Verb
1 = verb1
2 = verb2
3 = ...
Remarks
Each verb is a REG_SZ value of the form "name, menu_flag, verb_flag". Verbs must be numbered consecutively.
The name describes how the verb is appended by an AppendMenu function call. For example, "&Play".
The menu_flag value indicates how the verb should appear in the menu. All flags supported by AppendMenu are
supported, except for MF_BITMAP, MF_OWNERDRAW, and MF_POPUP.
The verb_flag value describes attributes of the verbs. Use one of the values from OLEVERBATTRIB, or 0.
For more information, see OLEVERB, IOleObject::DoVerb, and IOleObject::EnumVerbs.
Related topics
A
p
p
e
n
d
M
e
n
u
O
L
E
V
E
R
B
O
L
E
V
E
R
B
A
T
T
R
I
B
Version
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
Version = value
Remarks
This is a REG_SZ value.
The version number should match the version of the type library associated with the control.
VersionIndependentProgID
1/7/2020 • 2 minutes to read • Edit Online
Associates a ProgID with a CLSID. This value is used to determine the latest version of an object application.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
{CLSID}
VersionIndependentProgID = Program.Component
Remarks
This is a REG_SZ value that specifies the latest version of the object application.
The version-independent ProgID is stored and maintained solely by application code. When given the version-
independent ProgID, the CLSIDFromProgID function returns the CLSID of the current version.
You can use CLSIDFromProgID and ProgIDFromCLSID to convert between these two representations.
<file_extension> Key
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes
.ext = ProgID
Remarks
The information contained in the file name extension key is used by both the Windows Explorer and file monikers.
GetClassFile uses the file name extension key to supply the associated CLSID.
The HKEY_LOCAL_MACHINE\SOFTWARE\Classes key corresponds to the HKEY_CLASSES_ROOT key,
which was retained for compatibility with earlier versions of COM.
Related topics
F
i
l
e
T
y
p
e
G
e
t
C
l
a
s
s
F
i
l
e
FileType Key
1/7/2020 • 2 minutes to read • Edit Online
Used by GetClassFile to match patterns against various file bytes in a non-compound file.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\FileType
{CLSID}
n = offset, cb, mask, value
o
f
f
s
e
t
Determines how far from the beginning or end of the file to begin the comparison. If the offset is a negative
value, the comparison begins from the end of the file minus the offset value. The offset value is a decimal
type unless preceded by "0x".
c
b
Represents the length in bytes from the beginning to the end of the file. Represents the byte range in the file.
The cb value is a decimal unless preceded by "0x".
m
a
s
k
A binary value used for masking, which is performed by using a logical AND operation, and the byte range
specified by offset and cb. If this value is omitted, the bytes are set to all ones. This value is always
hexadecimal.
v
a
l
u
e
Represents the pattern that must match for a file to be of this file type. The pattern is used to properly
identify a known file format from its contents, not by its extension.
Remarks
Entries are used by the GetClassFile function to match patterns against various file bytes in a non-compound file.
FileType has CLSID subkeys, each of which has a series of subkeys 0, 1, 2, 3. These values contain patterns that, if
one matches, yield the indicated CLSID. For example, a value of "0, 4, FFFFFFFF, ABCD1234" indicates that the
first 4 bytes must be ABCD1234, in that order. A value of "-4, 4, FEFEFEFE " indicates that the last four bytes in the
file must be FEFEFEFE. If either pattern matches, the CLSID is returned.
The HKEY_LOCAL_MACHINE\SOFTWARE\Classes key corresponds to the HKEY_CLASSES_ROOT key,
which was retained for compatibility with earlier versions of COM.
Related topics
<
f
i
l
e
_
e
x
t
e
n
s
i
o
n
>
G
e
t
C
l
a
s
s
F
i
l
e
Interface Key
1/7/2020 • 2 minutes to read • Edit Online
Registers new interfaces by associating an interface name with an interface ID (IID ). There must be one IID
subkey for each new interface.
Registry Key
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{IID }
Remarks
The HKEY_LOCAL_MACHINE\SOFTWARE\Classes key corresponds to the HKEY_CLASSES_ROOT key,
which was retained for compatibility with earlier versions of COM.
Related topics
I
n
t
e
r
f
a
c
e
BaseInterface
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface
{IID}
BaseInterface = name
Remarks
This is a REG_SZ value.
Related topics
I
n
t
e
r
f
a
c
e
NumMethods
1/7/2020 • 2 minutes to read • Edit Online
Contains the number of methods in the associated interface, including methods from derived interfaces.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface
{IID}
NumMethods = value
Remarks
This is a REG_SZ value.
Related topics
I
n
t
e
r
f
a
c
e
ProxyStubClsid
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface
{IID}
ProxyStubClsid = {CLSID}
Remarks
This is a REG_SZ value that specifies the CLSID for the IID.
If you add interfaces, you must use this entry to register them (16-bit systems) so that OLE can find the
appropriate remoting code to establish interprocess communication.
Related topics
I
n
t
e
r
f
a
c
e
P
r
o
x
y
S
t
u
b
C
l
s
i
d
3
2
ProxyStubClsid32
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface
{IID}
ProxyStubClsid32 = {CLSID}
Remarks
This is a REG_SZ value that specifies the CLSID for the IID.
This is a required entry since the IID -to-CLSID mapping may be different for 16-bit and 32-bit interfaces. The IID -
to-CLSID mapping depends on the way the interface proxies are packaged into a set of proxy DLLs.
If you add interfaces, you must use this entry to register them (32-bit systems) so that OLE can find the
appropriate remoting code to establish interprocess communication.
Related topics
I
M
a
r
s
h
a
l
I
n
t
e
r
f
a
c
e
P
r
o
x
y
S
t
u
b
C
l
s
i
d
Key
1/7/2020 • 2 minutes to read • Edit Online
A programmatic identifier (ProgID ) is a registry entry that can be associated with a CLSID. Like the CLSID, the
ProgID identifies a class but with less precision because it is not guaranteed to be globally unique.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\{ProgID }
Remarks
You can use a ProgID in programming situations where it is not possible to use a CLSID. ProgIDs should not
appear in the user interface. ProgIDs are not guaranteed to be unique, so they can be used only where name
collisions are manageable.
The format of a ProgID is <Program>.<Component>.<Version>, separated by periods and with no spaces, as in
Word.Document.6. The ProgID must comply with the following requirements:
Have no more than 39 characters.
Contain no punctuation (including underscores) except one or more periods.
Not start with a digit.
Be different from the class name of any OLE 1 application, including the OLE 1 version of the same
application, if there is one.
Because the ProgID should not appear in the user interface, you can obtain a displayable name by calling
IOleObject::GetUserType. Also, see OleRegGetUserType.
The HKEY_LOCAL_MACHINE\SOFTWARE\Classes key corresponds to the HKEY_CLASSES_ROOT key,
which was retained for compatibility with earlier versions of COM.
Related topics
I
O
l
e
O
b
j
e
c
t
:
:
G
e
t
U
s
e
r
T
y
p
e
O
l
e
R
e
g
G
e
t
U
s
e
r
T
y
p
e
CLSID
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes
{ProgID}
CLSID = CLSID
Remarks
This is a REG_SZ value that specifies the object's CLSID.
Insertable
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes
{ProgID}
Insertable
Remarks
This is a required entry for objects that are insertable in OLE 2 containers.
Protocol
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes
{ProgID}
Protocol
StdFileEditing
Server = path
Verb
0 = verb1
1 = verb2
...
Remarks
The StdFileEditing entry specifies OLE 1 compatibility information. It should be present only if objects of this
class are insertable in OLE 1 containers.
Server specifies the full path to the OLE 2 server application and Verb specifies the verbs. Verb 0 is the primary
verb and additional verbs must be numbered consecutively.
Shell
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes
{ProgID}
Shell
Open
command = path %1
Print
command = path %1
Remarks
These entries should provide the path and file name of the application.
Key
1/7/2020 • 2 minutes to read • Edit Online
Associates a ProgID with a CLSID. This key is used to determine the latest version of an object application.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Classes
<version-independent ProgID>
CurVer = ProgID
Remarks
The HKEY_LOCAL_MACHINE\SOFTWARE\Classes key corresponds to the HKEY_CLASSES_ROOT key,
which was retained for compatibility with earlier versions of COM.
The format for <version-independent ProgID> is <program>.<component>, separated by periods, no spaces, and
no version number. The version-independent ProgID, like the ProgID, can be registered with a human-readable
name.
ProgID is the ProgID of the latest installed version of the class.
Applications must register a version-independent programmatic identifier under the version-independent ProgID
key. The version-independent ProgID refers to the application's class and does not change from version to version,
instead remaining constant across all versions—for example, Microsoft Word Document. It is used with macro
languages and refers to the currently installed version of the application's class. The version-independent ProgID
must correspond to the name of the latest version of the object application.
For example, the version-independent ProgID is used when a container application creates a chart or table with a
toolbar button. In this situation, the application can use the version-independent ProgID to determine the latest
version of the needed object application.
The version-independent ProgID is stored and maintained solely by application code. When given the version-
independent ProgID, the CLSIDFromProgID function returns the CLSID of the current version.
You can use CLSIDFromProgID and ProgIDFromCLSID to convert between these two representations.
You can use IOleObject::GetUserType or OleRegGetUserType to change the identifier to a displayable string.
If a custom handler is not used, the entry should be set to OLE32.DLL, as shown in the following example:
HKEY_CLASSES_ROOT\CLSID\{00000402-0000-0000-C000-000000000046}
InprocHandler = ole32.dll
Related topics
C
L
S
I
D
F
r
o
m
P
r
o
g
I
D
P
r
o
g
I
D
F
r
o
m
C
L
S
I
D
K
e
y
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole
1/7/2020 • 2 minutes to read • Edit Online
The registry values associated with the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole key control the
default launch and access permission settings and call-level security capabilities for COM -based applications that
do not call CoInitializeSecurity.
Only administrators, the object creator, and the system have full access to this portion of the registry. All other
users have read-only access.
ActivationFailureLoggingLevel Sets the verbosity of event log entries about failed requests
for component launch and activation.
CallFailureLoggingLevel Sets the verbosity of event log entries about failed calls to
components.
DCOMSCMRemoteCallFlags Controls the behavior of calls from the local DCOM Service
Control Manager (DCOMSCM) to a remote DCOMSCM.
InvalidSecurityDescriptorLoggingLevel Sets the verbosity of event log entries about invalid security
descriptors for component launch and access permissions.
NonRedist Adds names to the list of files that should not be exported
when COM+ applications are packaged for installation on
other computers. Note that this is a subkey, not a value.
Sets the verbosity of event log entries about failed requests for component launch and activation.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole
ActivationFailureLoggingLevel = value
Remarks
This is a REG_DWORD value.
VALUE DESCRIPTION
If you need an application to control event logging, it is recommended that you set this value to 0 and write the
client code to override it when needed. It is strongly recommended that you do not set the value to 2. If event
logging is disabled, it is more difficult to diagnose problems. For machine restrictions permission failures, where
COM does not have the CLSCTX bits, COM will treat a value of 0 as 1.
Related topics
S
e
t
t
i
n
g
S
e
c
u
r
i
t
y
f
o
r
C
O
M
A
p
p
l
i
c
a
t
i
o
n
s
CallFailureLoggingLevel
1/7/2020 • 2 minutes to read • Edit Online
Sets the verbosity of event log entries about failed calls to components.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole
CallFailureLoggingLevel = value
Remarks
This is a REG_DWORD value.
VALUE DESCRIPTION
Related topics
S
e
t
t
i
n
g
S
e
c
u
r
i
t
y
f
o
r
C
O
M
A
p
p
l
i
c
a
t
i
o
n
s
DCOMSCMRemoteCallFlags
1/7/2020 • 2 minutes to read • Edit Online
Controls the behavior of calls from the local DCOM Service Control Manager (DCOMSCM ) to a remote
DCOMSCM.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole
DCOMSCMRemoteCallFlags = value
Remarks
This is a REG_DWORD value.
VALUE DESCRIPTION
0x1 DCOMSCM_ACTIVATION_USE_ALL_AUTHNSERVICES
0x2 DCOMSCM_ACTIVATION_DISALLOW_UNSECURE_CALL
0x4 DCOMSCM_RESOLVE_USE_ALL_AUTHNSERVICES
0x8 DCOMSCM_RESOLVE_DISALLOW_UNSECURE_CALL
0x10 DCOMSCM_PING_USE_MID_AUTHNSERVICE
DCOMSCM_ACTIVATION_USE_ALL_AUTHNSERVICES Description
When the client issues an activation request that uses the default security settings, the local DCOMSCM uses the
Negotiate authentication service when making the activation RPC call to the remote DCOMSCM. If the call fails,
the local DCOMSCM makes the activation RPC call using no security.
Windows Server 2003 and Windows XP/2000: If the activation RPC call that uses the Negotiate authentication
service fails, the local DCOMSCM makes the activation RPC call using Kerberos, NTLM, or other configured
security providers. If no security providers work, the local DCOMSCM makes the activation RPC call using no
security.
By setting this flag, the local DCOMSCM on Windows Vista or higher can be made to behave like pre-Vista
systems. It is not recommended to set this flag unless required for compatibility reasons.
DCOMSCM_ACTIVATION_DISALLOW_UNSECURE_CALL Description
If the DCOMSCM_ACTIVATION_DISALLOW_UNSECURE_CALL flag is set, the local DCOMSCM does not
make an unsecure activation RPC call. To enable clients to make activation requests with non-default security
settings, specify the COAUTHINFO structure when making the activation request. In this case, the
DCOMSCM_ACTIVATION_USE_ALL_AUTHNSERVICES and
DCOMSCM_ACTIVATION_DISALLOW_UNSECURE_CALL flags are ignored.
It is not recommended to set this flag unless all the clients and servers in the network are fully authenticated.
DCOMSCM_RESOLVE_USE_ALL_AUTHNSERVICES Description
When the client unmarshals an object reference, the local DCOMSCM uses the Negotiate authentication service
when making the OXID Resolution RPC call to the remote DCOMSCM. If the call fails, the local DCOMSCM
makes the OXID Resolution RPC call using no security.
Windows Server 2003 and Windows XP/2000: If the OXID Resolution RPC call using the Negotiate
authentication service fails, the local DCOMSCM makes the OXID Resolution RPC call by using Kerberos, NTLM,
or other configured security providers. If no security providers work, then the local DCOMSCM makes the OXID
Resolution RPC call using no security.
By setting this flag, the local DCOMSCM on Windows Vista or higher can be made to behave like pre-Vista
systems. It is not recommended to set this flag unless required for compatibility reasons.
DCOMSCM_RESOLVE_DISALLOW_UNSECURE_CALL Description
If the DCOMSCM_RESOLVE_DISALLOW_UNSECURE_CALL flag is set, the local DCOMSCM does not make
an unsecure OXID Resolution RPC call. In addition, the local DCOMSCM does not make an unsecure garbage
collection Ping RPC call. It is not recommended to set this flag unless all the clients and servers in the network are
fully authenticated.
DCOMSCM_PING_USE_MID_AUTHNSERVICE Description
The local DCOMSCM uses the Negotiate authentication service when making the garbage-collection Ping RPC
call to the remote DCOMSCM. If the call fails, the local DCOMSCM makes the garbage-collection Ping RPC call
using no security.
Windows Server 2003 and Windows XP/2000: If the garbage-collection Ping RPC call using the Negotiate
authentication service fails, the local DCOMSCM makes the garbage collection Ping RPC call by using Kerberos,
NTLM, and other configured security providers. If no security providers work, then the local DCOMSCM makes
the garbage collection Ping RPC call using no security.
By setting this flag, the local DCOMSCM on Windows Vista or above can be made to behave like pre-Vista
systems. It is not recommended to set the DCOMSCM_PING_USE_MID_AUTHNSERVICE flag unless required
for compatibility reasons.
Related topics
A
u
t
h
e
n
t
i
c
a
t
i
o
n
f
o
r
R
e
m
o
t
e
C
o
n
n
e
c
t
i
o
n
s
E
n
a
b
l
e
D
C
O
M
R
e
g
i
s
t
e
r
i
n
g
C
O
M
S
e
r
v
e
r
s
S
e
c
u
r
i
t
y
i
n
C
O
M
DefaultAccessPermission
1/7/2020 • 2 minutes to read • Edit Online
Sets the Access Control List (ACL ) of the principals that can access classes for which there is no
AccessPermission setting. This ACL is used only by applications that do not call CoInitializeSecurity and do
not have an AccessPermission value under their AppID key.
Cau t i on
It is not recommended that you change this value, because this will affect all COM server applications that do
not set their own process-wide security, and might prevent them from working properly. If you are changing this
value to affect the security settings for a particular COM application, then you should instead change the
process-wide security settings for that particular COM application. For more information on setting process-
wide security, see Setting Process-wide Security.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole
DefaultAccessPermission = ACL
Remarks
This is a REG_BINARY value.
The COM runtime in the server checks the ACL described by this value while impersonating the caller that is
attempting to connect to the object, and its success determines whether the access is allowed or disallowed. If
the access-check fails, the connection to the object is disallowed. If this named value does not exist, only the
server principal and local system are allowed to call the server.
By default, this value has no entries in it. Only the server principal and system are allowed to call the server.
This value provides a simple level of centralized administration of the default connection access to running
objects on a computer.
Related topics
A
c
c
e
s
s
P
e
r
m
i
s
s
i
o
n
R
e
g
i
s
t
e
r
i
n
g
C
O
M
S
e
r
v
e
r
s
S
e
t
t
i
n
g
P
r
o
c
e
s
s
-
w
i
d
e
S
e
c
u
r
i
t
y
DefaultLaunchPermission
1/7/2020 • 2 minutes to read • Edit Online
Defines the Access Control List (ACL ) of the principals that can launch classes that do not specify their own ACL
through the LaunchPermission registry value.
Cau t i on
It is not recommended that you change this value, because this will affect all COM server applications that do not
set their own process-wide security, and might prevent them from working properly. If you are changing this
value to affect the security settings for a particular COM application, then you should instead change the process-
wide security settings for that particular COM application. For more information on setting process-wide security,
see Setting Process-wide Security.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole
DefaultLaunchPermission = ACL
Remarks
This is a REG_BINARY value.
The default access permissions are as follows:
Administrators: allow launch
SYSTEM: allow launch
INTERACTIVE: allow launch
If the LaunchPermission value is set for a server, it takes precedence over the DefaultLaunchPermission
value. Upon receiving a local or remote request to launch a server whose AppID key has no LaunchPermission
value of its own, the ACL described by this value is checked while impersonating the client and its success either
allows or disallows the launching of the class code.
This value provides a simple level of centralized administration of the default launching access to otherwise
unadministered classes on a computer. For example, an administrator might use the DCOMCNFG tool to
configure the system to allow read-only access for Power Users. OLE would therefore restrict requests to launch
class code to members of the Power Users group. An administrator could subsequently configure launch
permissions for individual classes to grant the ability to launch class code to other groups or individual users as
needed.
Related topics
L
a
u
n
c
h
P
e
r
m
i
s
s
i
o
n
R
e
g
i
s
t
e
r
i
n
g
C
O
M
S
e
r
v
e
r
s
S
e
t
t
i
n
g
P
r
o
c
e
s
s
-
w
i
d
e
S
e
c
u
r
i
t
y
DoNotAddAllApplicationPackagesToRestrictions
1/7/2020 • 2 minutes to read • Edit Online
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole
DoNotAddAllApplicationPackagesToRestrictions = value
Remarks
This is a REG_DWORD value.
VALUE DESCRIPTION
Related topics
S
e
t
t
i
n
g
S
e
c
u
r
i
t
y
f
o
r
C
O
M
A
p
p
l
i
c
a
t
i
o
n
s
EnableDCOM
1/7/2020 • 2 minutes to read • Edit Online
Controls the global activation and call policies of the machine. Only administrators and the system have full access
to this portion of the registry. All other users have read-only access.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole
EnableDCOM = value
Remarks
This is a REG_SZ value.
VALUE DESCRIPTION
Related topics
D
e
f
a
u
l
t
L
a
u
n
c
h
P
e
r
m
i
s
s
i
o
n
L
a
u
n
c
h
P
e
r
m
i
s
s
i
o
n
S
e
c
u
r
i
t
y
i
n
C
O
M
InvalidSecurityDescriptorLoggingLevel
1/7/2020 • 2 minutes to read • Edit Online
Sets the verbosity of event log entries about invalid security descriptors for component launch and access
permissions.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole
InvalidSecurityDescriptorLoggingLevel = value
Remarks
This is a REG_DWORD value.
VALUE DESCRIPTION
If you set launch and access permission security descriptors (commonly called ACLs) directly, it is possible to
construct a security descriptor whose meaning cannot be interpreted unambiguously. COM makes an event log
entry when it encounters such an invalid security descriptor.
Note that ActivationFailureLoggingLevel and CallFailureLoggingLevel have no control over logging invalid
security descriptor errors. Use InvalidSecurityDescriptorLoggingLevel for full control over this functionality.
Related topics
S
e
t
t
i
n
g
S
e
c
u
r
i
t
y
f
o
r
C
O
M
A
p
p
l
i
c
a
t
i
o
n
s
LegacyAuthenticationLevel
1/7/2020 • 2 minutes to read • Edit Online
Sets the default authentication level for applications that do not call CoInitializeSecurity.
Cau t i on
It is not recommended that you change this value, because this will affect all COM server applications that do not
set their own process-wide security, and might prevent them from working properly. If you are changing this
value to affect the security settings for a particular COM application, then you should instead change the
process-wide security settings for that particular COM application. For more information on setting process-
wide security, see Setting Process-wide Security.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole
LegacyAuthenticationLevel = value
Remarks
This is a REG_WORD value that is equivalent to the RPC_C_AUTHN_LEVEL constants.
VALUE CONSTANT
1 RPC_C_AUTHN_LEVEL_NONE
2 RPC_C_AUTHN_LEVEL_CONNECT
3 RPC_C_AUTHN_LEVEL_CALL
4 RPC_C_AUTHN_LEVEL_PKT
5 RPC_C_AUTHN_LEVEL_PKT_INTEGRITY
6 RPC_C_AUTHN_LEVEL_PKT_PRIVACY
If this registry value is not present, the default authentication level established by the system is 2
(RPC_C_AUTHN_CONNECT).
Related topics
A
u
t
h
e
n
t
i
c
a
t
i
o
n
L
e
v
e
l
R
e
g
i
s
t
e
r
i
n
g
C
O
M
S
e
r
v
e
r
s
S
e
t
t
i
n
g
P
r
o
c
e
s
s
-
w
i
d
e
S
e
c
u
r
i
t
y
LegacyImpersonationLevel
1/7/2020 • 2 minutes to read • Edit Online
Sets the default level of impersonation for applications that do not call CoInitializeSecurity.
Cau t i on
It is not recommended that you change this value, because this will affect all COM server applications that do not
set their own process-wide security, and might prevent them from working properly. If you are changing this value
to affect the security settings for a particular COM application, then you should instead change the process-wide
security settings for that particular COM application. For more information on setting process-wide security, see
Setting Process-wide Security.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole
LegacyImpersonationLevel = value
Remarks
This is a REG_WORD value that is equivalent to the RPC_C_IMP_LEVEL constants.
VALUE CONSTANT
1 RPC_C_IMP_LEVEL_ANONYMOUS
2 RPC_C_IMP_LEVEL_IDENTIFY
3 RPC_C_IMP_LEVEL_IMPERSONATE
4 RPC_C_IMP_LEVEL_DELEGATE
If this registry value is not present, the default impersonation level established by the system is 2
(RPC_C_IMP_LEVEL_IDENTIFY ).
Related topics
R
e
g
i
s
t
e
r
i
n
g
C
O
M
S
e
r
v
e
r
s
S
e
t
t
i
n
g
P
r
o
c
e
s
s
-
w
i
d
e
S
e
c
u
r
i
t
y
LegacySecureReferences
1/7/2020 • 2 minutes to read • Edit Online
Determines whether AddRef/Release invocations are secured for applications that do not call
CoInitializeSecurity.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole
LegacySecureReferences = value
Remarks
This is a REG_SZ value. A value of 'Y' or 'y' indicate that AddRef and Release are secured. If this registry value is
not present or is set to a value other than 'Y' or 'y', AddRef and Release are not secured. Enabling secure
references slows remote calls.
Related topics
R
e
g
i
s
t
e
r
i
n
g
C
O
M
S
e
r
v
e
r
s
S
e
t
t
i
n
g
P
r
o
c
e
s
s
-
w
i
d
e
S
e
c
u
r
i
t
y
MachineAccessRestriction
1/7/2020 • 2 minutes to read • Edit Online
Changing this value will affect all COM server applications, and might prevent them from working properly. If
there are COM server applications that have restrictions that are less stringent than the computer-wide
restrictions, reducing the computer-wide restrictions may expose these applications to unwanted access.
Conversely, if you increase the computer-wide restrictions, some COM server applications might no longer be
accessible by calling applications.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole
MachineAccessRestriction = SECURITY_DESCRIPTOR
Remarks
This is a REG_BINARY value.
Principals not given permissions here cannot obtain them even if the permissions are granted by the
DefaultAccessPermission registry value or by the CoInitializeSecurity function.
By default, members of the Everyone group can obtain local and remote access permissions, and anonymous
users can obtain local access permissions.
Related topics
S
e
t
t
i
n
g
S
e
c
u
r
i
t
y
f
o
r
C
O
M
A
p
p
l
i
c
a
t
i
o
n
s
MachineLaunchRestriction
1/7/2020 • 2 minutes to read • Edit Online
Sets the computer-wide restriction policy for component launch and activation.
Cau t i on
Changing this value will affect all COM server applications, and might prevent them from working properly. If
there are COM server applications that have restrictions that are less stringent than the computer-wide
restrictions, reducing the computer-wide restrictions may expose these applications to unwanted access.
Conversely, if you increase the computer-wide restrictions, some COM server applications might no longer be
accessible by calling applications.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole
MachineLaunchRestriction = SECURITY_DESCRIPTOR
Remarks
This is a REG_BINARY value.
Principals not given permissions here cannot obtain them even if the permissions are granted by the
DefaultAccessPermission registry value or by the CoInitializeSecurity function.
By default, administrators may obtain local and remote launch and activation permissions, and members of the
Everyone group may obtain local activation and launch permissions.
Related topics
S
e
t
t
i
n
g
S
e
c
u
r
i
t
y
f
o
r
C
O
M
A
p
p
l
i
c
a
t
i
o
n
s
NONREDIST
1/7/2020 • 2 minutes to read • Edit Online
Adds names to the list of files that should not be exported when COM+ applications are packaged for installation
on other computers. Note that this is a subkey, not a value.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole
NONREDIST
name1
name2
Remarks
The files you add to the list are represented by name/value pairs stored under this key. In each name/value pair, the
name is the file name and the value is reserved.
SRPActivateAsActivatorChecks
1/7/2020 • 2 minutes to read • Edit Online
Determines whether software restriction policy (SRP ) trust levels are used during ActivateAsActivator activations.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole
SRPActivateAsActivatorChecks = value
Remarks
This is a REG_SZ value.
String values of {N, n, NO, No, no} indicate that the server object runs with the SRP trust level of the client object,
regardless of the SRP trust level with which it was configured. If this registry value is set to any other value or
does not exist, the SRP trust level that is configured for the server object is compared with the SRP trust level of
the client object and that the more stringent trust level is used to run the server object.
Related topics
S
R
P
T
r
u
s
t
L
e
v
e
l
SRPRunningObjectChecks
1/7/2020 • 2 minutes to read • Edit Online
Determines whether attempts to connect to running objects are screened for compatible software restriction
policy (SRP ) trust levels.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole
SRPRunningObjectChecks = value
Remarks
This is a REG_SZ value.
String values of {N, n, NO, No, no} indicate that attempts to connect to running objects are not screened for
compatible SRP trust levels. If this registry value is set to any other value or does not exist, the running object
cannot have a less stringent SRP trust level than the client object. For example, the running object cannot have a
Disallowed trust level if the client object has an Unrestricted trust level.
Related topics
S
R
P
T
r
u
s
t
L
e
v
e
l
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows
NT\CurrentVersion
1/7/2020 • 2 minutes to read • Edit Online
SUBKEY DESCRIPTION
The DebugObjectRPCEnabled enables remote COM debugging over RPC. If this key is not defined on the
server, remote debugging is disabled.
Registry Key
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows
NT\CurrentVersion\DebugObjectRPCEnabled
Related topics
D
l
l
D
e
b
u
g
O
b
j
e
c
t
R
P
C
H
o
o
k
I
O
r
p
c
D
e
b
u
g
N
o
t
i
f
y
O
R
P
C
_
D
B
G
_
A
L
L
AeDebug
1/7/2020 • 2 minutes to read • Edit Online
Registry Key
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows
NT\CurrentVersion\DebugObjectRPCEnabled\AeDebug
Related topics
D
l
l
D
e
b
u
g
O
b
j
e
c
t
R
P
C
H
o
o
k
I
O
r
p
c
D
e
b
u
g
N
o
t
i
f
y
O
R
P
C
_
D
B
G
_
A
L
L
Auto
1/7/2020 • 2 minutes to read • Edit Online
Determines if the debugger is automatically launched when a COM RPC notification is sent.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DebugObjectRPCEnabled\AeDebug
Auto = value
Remarks
This is a REG_WORD value.
VALUE DESCRIPTION
Related topics
D
l
l
D
e
b
u
g
O
b
j
e
c
t
R
P
C
H
o
o
k
I
O
r
p
c
D
e
b
u
g
N
o
t
i
f
y
O
R
P
C
_
D
B
G
_
A
L
L
Debugger
1/7/2020 • 2 minutes to read • Edit Online
Stores the name of the preferred debugger to use with remote COM debugging over RPC.
Registry Entry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DebugObjectRPCEnabled\AeDebug
Debugger = value
Remarks
This is a REG_SZ value.
Related topics
D
l
l
D
e
b
u
g
O
b
j
e
c
t
R
P
C
H
o
o
k
I
O
r
p
c
D
e
b
u
g
N
o
t
i
f
y
O
R
P
C
_
D
B
G
_
A
L
L
Structures
1/7/2020 • 2 minutes to read • Edit Online
The ORPC_DBG_ALL structure is used to pass parameters to the methods of the IOrpcDebugNotify
interface.
NOTE
Each method of the IOrpcDebugNotify interface uses a different combination of the members below. If a member is not
indicated as used by a method, it is undefined when passed to that method.
Syntax
typedef struct ORPC_DBG_ALL {
BYTE *pSignature;
RPCOLEMESSAGE *pMessage;
const IID *refiid;
IRpcChannelBuffer *pChannel;
IUnknown *pUnkProxyMgr;
void *pInterface;
IUnknown *pUnkObject;
HRESULT hresult;
void *pvBuffer;
ULONG *cbBuffer;
ULONG *lpcbBuffer;
void *reserved;
} ORPC_DBG_ALL, *LPORPC_DBG_ALL;
Members
p
S
i
g
n
a
t
u
r
e
NOTE
Used by all methods of the IOrpcDebugNotify interface.
p
M
e
s
s
a
g
e
NOTE
Used by the ClientFillBuffer, ClientGetBufferSize, ClientNotify, ServerFillBuffer, ServerGetBufferSize, and
ServerNotify methods.
r
e
f
i
i
d
NOTE
Used by the ClientFillBuffer, ClientGetBufferSize, ClientNotify, ServerFillBuffer, ServerGetBufferSize, and
ServerNotify methods.
p
C
h
a
n
n
e
l
A pointer to the IRpcChannelBuffer interface of the COM RPC channel implementation on the server.
NOTE
Used by the ServerFillBuffer, ServerGetBufferSize, and ServerNotify methods.
p
U
n
k
P
r
o
x
y
M
g
r
A pointer to the IUnknown interface of the object involved in this debugger invocation. May be NULL,
however, this reduces debugger functionality.
NOTE
Used by the ClientFillBuffer, ClientGetBufferSize, and ClientNotify methods.
p A pointer to the COM interface of the method that will be invoked by this RPC. Must not be NULL.
I
n NOTE
t Used by the ServerFillBuffer, ServerGetBufferSize, and ServerNotify methods.
e
r
f
a
c
e
p Must be NULL.
U
n NOTE
k Used by the ServerFillBuffer, ServerGetBufferSize, and ServerNotify methods.
O
b
j
e
c
t
h
r
e
s
u
l
t
NOTE
Used by the ClientGetBufferSize, ClientNotify, and ServerGetBufferSize methods.
p
v
B
u
f
f
e
r
A pointer to an ORPC_DBG_BUFFER structure that contains the RPC marshalled debug information. Is
undefined if cbBuffer is zero.
NOTE
Used by the ClientFillBuffer, ClientNotify, ServerFillBuffer, and ServerNotify methods.
l
p
c
b
B
u
f
f
e
r
The number of bytes the client debugger will transmit to the server debugger. If zero, no information
need be transmitted. This value supersedes the value returned in hresult.
NOTE
Used by the ClientFillBuffer, ClientGetBufferSize methods.
r Reserved. Do not use.
e
s
e
r
v
e
d
Requirements
Header
N/A
See also
O
R
P
C
_
D
B
G
_
B
U
F
F
E
R
O
R
P
C
_
I
N
I
T
_
A
R
G
S
D
l
l
D
e
b
u
g
O
b
j
e
c
t
R
P
C
H
o
o
k
I
O
r
p
c
D
e
b
u
g
N
o
t
i
f
y
ORPC_DBG_BUFFER structure
1/7/2020 • 2 minutes to read • Edit Online
The ORPC_DBG_BUFFER structure is the buffer format used to marshalled RPC data to the methods of the
IOrpcDebugNotify interface.
Syntax
typedef struct _ORPC_DBG_BUFFER {
DWORD alwaysOrSometimes;
BYTE verMajor;
BYTE verMinor;
DWORD cbRemaining;
GUID guidSemantic;
union {
BOOL fStopOnOtherSide;
USHORT wDebuggingOpCode;
USHORT cExtent;
BYTE padding[2];
struct {
ULONG cb;
GUID guidExtent;
BYTE *rgbData;
};
};
} ORPC_DBG_BUFFER, *PORPC_DBG_BUFFER;
Members
a A value that controls debugger spawning. alwaysOrSometimes can be one of the following values:
l
w VALUE MEANING
a
y If set, COM will always raise the client or server
OR notification on the receiver.
s PC_
O DEB
r UG_
AL
S WA
o YS
m 0x0
e 000
000
t 0
i
m
e
s
VALUE MEANING
g
u
i
d
S
e
m
a
n
t
i
c
A GUID that determines which members of the union are present below. guidSemantic can take one of the
following values:
VALUE MEANING
f
S
t
o
p
O
n
O
t
h
e
r
S
i
d
e
If TRUE, single stepping is performed by the debugger and it should step out of the server and continue
execution once the other side is reached. Otherwise, single stepping is not performed and debugger
execution stops on the other side.
w
D
e
b
u
g
g
i
n
g
O
p
C
o
d
e
A value that allows for one of a series of operations to be specified. wDebuggingOpCode can take one of
the following values:
VALUE MEANING
No operation.
0x0
000
r
g
b
D
a
t
a
A BYTE buffer used to pass RPC marshalled COM data between the client and server debuggers. The
contents of rgbData are determined by the GUID in guidExtent.
Remarks
This members of this structure have 1-byte alignment and are always transmitted in little-endian byte order.
Requirements
Header
N/A
See also
O
R
P
C
_
D
B
G
_
A
L
L
O
R
P
C
_
I
N
I
T
_
A
R
G
S
D
l
l
D
e
b
u
g
O
b
j
e
c
t
R
P
C
H
o
o
k
I
O
r
p
c
D
e
b
u
g
N
o
t
i
f
y
ORPC_INIT_ARGS structure
1/7/2020 • 2 minutes to read • Edit Online
The ORPC_INIT_ARGS structure contains information used to initialize remote debugging using the
IOrpcDebugNotify interface.
Syntax
typedef struct ORPC_INIT_ARGS {
IOrpcDebugNotify *lpIntfOrpcDebug;
void *pvPSN;
DWORD *dwReserved1;
DWORD *dwReserved2;
} ORPC_INIT_ARGS, *LPORPC_INIT_ARGS;
Members
l
p
I
n
t
f
O
r
p
c
D
e
b
u
g
A pointer to the IOrpcDebugNotify interface for use by in-process debuggers. If the debugger is not in-
process or is a Macintosh system, this field must be NULL.
p
v
P
S
N
A pointer to the Macintosh process serial number of the debuggee's process. If the debuggee is not a
Macintosh system, this field must be NULL.
d Reserved. Must be 0.
w
R
e
s
e
r
v
e
d
1
d Reserved. Must be 0.
w
R
e
s
e
r
v
e
d
2
Requirements
Header
N/A
See also
O
R
P
C
_
D
B
G
_
A
L
L
O
R
P
C
_
D
B
G
_
B
U
F
F
E
R
D
l
l
D
e
b
u
g
O
b
j
e
c
t
R
P
C
H
o
o
k
I
O
r
p
c
D
e
b
u
g
N
o
t
i
f
y
Functions
1/7/2020 • 10 minutes to read • Edit Online
FUNCTION DESCRIPTION
CoAllowSetForegroundWindow Enables the COM server process called to take focus away
from the client application by using the IForegroundTransfer
interface.
CoAllowUnmarshalerCLSID Adds an unmarshaler CLSID to the allowed list for the calling
process only.
CoCreateGuid Creates a GUID, a unique 128-bit integer used for CLSIDs and
interface identifiers.
CoFreeAllLibraries Frees all the DLLs that have been loaded with the
CoLoadLibrary function (called internally by
CoGetClassObject), regardless of whether they are currently
in use.
CoFreeUnusedLibrariesEx Unloads any DLLs that are no longer in use and whose unload
delay has expired.
CoGetCallContext Retrieves the context of the current call on the current thread.
CoGetPSClsid Returns the CLSID of the DLL that implements the proxy and
stub for the specified interface.
CoGetTreatAsClass Returns the CLSID of an object that can emulate the specified
object.
CoImpersonateClient Enables the server to impersonate the client of the current call
for the duration of the call.
CoInitialize Initializes the COM library on the current thread and identifies
the concurrency model as single-thread apartment (STA).
FUNCTION DESCRIPTION
CoInitializeEx Initializes the COM library for use by the calling thread, sets
the thread's concurrency model, and creates a new apartment
for the thread if one is required.
CoInitializeSecurity Registers security and sets the default security values for the
process.
CoInvalidateRemoteMachineBindings Tells the service control manager to flush any cached RPC
binding handles for the specified computer.
CoQueryClientBlanket Called by the server to find out about the client that invoked
the method executing on the current thread.
CoRevokeClassObject Informs OLE that a class object, previously registered with the
CoRegisterClassObject function, is no longer available for
use.
CoSuspendClassObjects Prevents any new activation requests from the SCM on all
class objects registered within the process.
CoTestCancel Determines whether the call being executed on the server has
been canceled by the client.
CoUninitialize Closes the COM library on the current thread, unloads all
DLLs loaded by the thread, frees any other resources that the
thread maintains, and forces all RPC connections on the
thread to close.
CoUnmarshalInterface Initializes a newly created proxy using data written into the
stream by a previous call to the CoMarshalInterface
function, and returns an interface pointer to that proxy.
DllGetClassObject Retrieves the class object from a DLL object handler or object
application.
MonikerCommonPrefixWith Creates a new moniker based on the common prefix that this
moniker (the one comprising the data of this moniker object)
shares with another moniker.
MonikerRelativePathTo Provides a moniker that, when composed onto the end of the
first specified moniker (or one with a similar structure), yields
the second specified moniker.
OleRegGetUserType Gets the user type of the specified class from the registry.
Syntax
BOOL WINAPI DllDebugObjectRPCHook(
BOOL fTrace,
LPORPC_INIT_ARGS lpOrpcInitArgs
);
Parameters
f If TRUE, remote debugging is enabled. If FALSE, remote debugging is not enabled.
T
r
a
c
e
Return value
TRUE if successful, FALSE otherwise
Requirements
Library
Ole
32.li
b
DLL
Ole
32.d
ll
See also
O
R
P
C
_
D
B
G
_
A
L
L
O
R
P
C
_
D
B
G
_
B
U
F
F
E
R
O
R
P
C
_
I
N
I
T
_
A
R
G
S
I
O
r
p
c
D
e
b
u
g
N
o
t
i
f
y
OLE and Data Transfer
1/7/2020 • 2 minutes to read • Edit Online
The following sections describe compound documents, the mechanism provided by the Component Object Model
(COM ) to transfer data between applications, and the APIs that are used to create compound documents and
perform data transfer.
Guide
Reference
Related topics
C
o
m
p
o
n
e
n
t
O
b
j
e
c
t
M
o
d
e
l
(
C
O
M
)
Guide
1/7/2020 • 2 minutes to read • Edit Online
This guide describes compound documents and the COM data transfer mechanism.
Compound Documents
Data Transfer
Related topics
R
e
f
e
r
e
n
c
e
Compound Documents
1/7/2020 • 2 minutes to read • Edit Online
OLE compound documents enable users working within a single application to manipulate data written in
various formats and derived from multiple sources. For example, a user might insert into a word processing
document a graph created in a second application and a sound object created in a third application. Activating
the graph causes the second application to load its user interface, or at least that part containing tools necessary
to edit the object. Activating the sound object causes the third application to play it. In both cases, a user is able to
manipulate data from external sources from within the context of a single document.
OLE compound document technology rests on a foundation consisting of COM, structured storage, and uniform
data transfer. As summarized below, each of these core technologies plays a critical role in OLE compound
documents:
C
O
M
A compound document object is essentially a COM object that can be embedded in, or linked to, an
existing document. As a COM object, a compound document object exposes the IUnknown interface,
through which clients can obtain pointers to its other interfaces, including several, such as IOleObject,
IOleLink, and IViewObject2, that provide special features unique to compound document objects.
S
t
r
u
c
t
u
r
e
d
S
t
o
r
a
g
e
A compound document object must implement the IPersistStorage or, optionally, IPersistStream
interfaces to manage its own storage. A container used to create compound documents must supply the
IStorage interface, through which objects store and retrieve data. Containers almost always provide
instances of IStorage obtained from OLE's Compound Files implementation. Containers must also use an
object's IPersistStorage and/or IPersistStream interfaces.
U
n
i
f
o
r
m
D
a
t
a
T
r
a
n
s
f
e
r
Applications that support compound documents must implement IDataObject because embedded
objects and linked objects begin as data that has been transferred using special OLE clipboard formats,
rather than standard Microsoft Windows clipboard formats. In other words, formatting data as an
embedded or linked object is simply one more option provided by OLE's uniform data transfer model.
OLE's compound document technology benefits both software developers and users alike. Instead of feeling
obligated to cram every conceivable feature into a single application, software developers are now free, if they
like, to develop smaller, more focused applications that rely on other applications to supply additional features. In
cases where a software developer decides to provide an application with capabilities beyond its core features, the
developer can implement these additional services as separate DLLs, which are loaded into memory only when
their services are required. Users benefit from smaller, faster, more capable software that they can mix and match
as needed, manipulating all required components from within a single master document.
For more information, see the following topics:
Containers and Servers
Linking and Embedding
Object Handlers
In-Process Servers
Linked Objects and Monikers
Notifications
Compound Document Interfaces
Object States
Implementing In-Place Activation
Creating Linked and Embedded Objects from Existing Data
View Caching
Related topics
D
a
t
a
T
r
a
n
s
f
e
r
S
t
r
u
c
t
u
r
e
d
S
t
o
r
a
g
e
Containers and Servers
1/7/2020 • 2 minutes to read • Edit Online
Compound document applications are of two basic types: container applications and server applications. OLE
container applications provide users with the ability to create, edit, save, and retrieve compound documents. OLE
server applications provide users with the means to create documents and other data representations that can be
contained as either links or embeddings in container applications. An OLE application can be a container
application, a server application, or both.
OLE server applications also differ in whether they are implemented as in-process servers or local servers. An in-
process server is a dynamic link library (DLL ) that runs in the container application's process space. You can run an
in-process server only from within the container application.
NOTE
Future releases of OLE will enable linking and embedding across computer boundaries, so that a container application on one
computer will be able to use a compound document object provided by a remote server running on another computer. From
a container application's point of view, any OLE server application that runs in its own process space, whether on the same
computer or a remote computer, is an out-of-process server.
Related topics
C
o
m
p
o
u
n
d
D
o
c
u
m
e
n
t
s
I
n
-
P
r
o
c
e
s
s
S
e
r
v
e
r
s
Linking and Embedding
1/7/2020 • 2 minutes to read • Edit Online
Users can create two types of compound-document objects: linked or embedded. The difference between the two
types lies in how and where the object's source data is stored. Where the object resides affects, in turn, the object's
portability and methods of activation, how data updates are performed, and the size and structure of its container.
Linked Objects
Embedded Objects
Related topics
C
o
m
p
o
u
n
d
D
o
c
u
m
e
n
t
s
Linked Objects
1/7/2020 • 2 minutes to read • Edit Online
When a link to an object is inserted in a compound document, the source data, or link source, continues to reside
wherever it was initially created, usually in another document. The compound document contains only a reference,
or link, to the actual data stored at the link source, along with information about how to present that data to the
user.
Activating a link runs the link source's server application, which the user requires in order to edit or otherwise
manipulate the link data. Linking keeps the size of a compound document small. It is also useful when the data
source is maintained by someone else and must be shared among many users. If the person maintaining the link
source changes the data, the change is automatically updated in all documents containing a link to that data. In
addition to creating simple links, users can nest links and combine linked and embedded objects to create complex
documents.
Related topics
C
r
e
a
t
i
n
g
L
i
n
k
e
d
a
n
d
E
m
b
e
d
d
e
d
O
b
j
e
c
t
s
f
r
o
m
E
x
i
s
t
i
n
g
D
a
t
a
D
i
s
t
r
i
b
u
t
e
d
L
i
n
k
T
r
a
c
k
i
n
g
a
n
d
O
b
j
e
c
t
I
d
e
n
t
i
f
i
e
r
s
L
i
n
k
e
d
O
b
j
e
c
t
s
a
n
d
M
o
n
i
k
e
r
s
Embedded Objects
1/7/2020 • 2 minutes to read • Edit Online
An embedded object is physically stored in the compound document, along with all the information needed to
manage the object. In other words, the embedded object is actually a part of the compound document in which it
resides. This arrangement has a couple of disadvantages. First, a compound document containing embedded
objects will be larger than one containing the same objects as links. Second, changes made to the source of an
embedded object will not be automatically replicated in the embedded copy, and changes in the source will not be
reflected in the source, as they are with a link.
Still, for certain purposes, embedding offers several advantages over links. First, users can transfer compound
documents with embedded objects to other computers, or other locations on the same computer, without breaking
a link. Second, users can edit embedded objects without changing the content of the original. Sometimes, this
separation is precisely what is required. Third, embedded objects can be activated in place, meaning that the user
can edit or otherwise manipulate the object without having to work in a separate window from that of the object's
container. Instead, when the object is activated, the container application's user interface changes to expose those
tools that are necessary to manage or modify the object.
Related topics
C
r
e
a
t
i
n
g
L
i
n
k
e
d
a
n
d
E
m
b
e
d
d
e
d
O
b
j
e
c
t
s
f
r
o
m
E
x
i
s
t
i
n
g
D
a
t
a
Object Handlers
1/7/2020 • 2 minutes to read • Edit Online
If an OLE server application is a local server, meaning that it runs in its own process space, communication
between container and server must occur across process boundaries. Because this process is expensive, OLE relies
on a surrogate object loaded into the container's process space to act on behalf of a local server application. This
surrogate object, known as an object handler, services container requests that do not require the attention of the
server application, such as requests for drawing. When a container requests something that the object handler
cannot provide, the handler communicates with the server application using COM's out-of-process
communication mechanism.
An object handler is unique to an object class. When you create an instance of a handler for one class, you cannot
use it for another. When used for a compound document, the object handler implements the container-side data
structures when objects of a particular class are accessed remotely.
OLE provides a default object handler that local server applications can use. For applications that require special
behaviors, developers can implement a custom handler that either replaces the default handler or uses it to
provide certain default behaviors.
An object handler is a DLL containing several interacting components. These components include remoting pieces
to manage communication between the handler and its server application, a cache for storing an object's data,
along with information on how that data should be formatted and displayed, and a controlling object that
coordinates the activities of the DLL's other components. In addition, if an object is a link, the DLL also includes a
linking component, or linked object, which keeps track of the name and location of the link source.
The cache contains data and presentation information sufficient for the handler to display a loaded, but not
running, object in its container. OLE provides an implementation of the cache used by OLE's default object handler
and the link object. The cache stores data in formats needed by the object handler to satisfy container draw
requests. When an object's data changes, the object sends a notification to the cache so that an update can occur.
For more information on the cache, see View Caching.
For more information, see the following topic:
The Default Handler and Custom Handlers
Related topics
C
o
m
p
o
u
n
d
D
o
c
u
m
e
n
t
s
The Default Handler and Custom Handlers
1/7/2020 • 2 minutes to read • Edit Online
The default handler, an implementation provided by OLE, is used by most applications as the handler. An
application implements a custom handler when the default handler's capabilities are insufficient. A custom handler
can either completely replace the default handler or use parts of the functionality it provides where appropriate. In
the latter case, the application handler is implemented as an aggregate object composed of a new control object
and the default handler. Combination application/default handlers are also known as in-process handlers. The
remoting handler is used for objects that are not assigned a CLSID in the system registry or that have no specified
handler. All that is required from a handler for these types of objects is that they pass information across the
process boundary.
Related topics
O
b
j
e
c
t
H
a
n
d
l
e
r
s
In-Process Servers
1/7/2020 • 2 minutes to read • Edit Online
If you implement an OLE server application as an in-process server — a DLL running in the process space of the
container application — rather than as a local server — an EXE running in its own process space —
communication between container and server is simplified because communication between the two can take the
form of normal function calls. Remote procedure calls are not required because the two applications run in the
same process space. As you would expect, the objects that manage the marshaling of parameters are also
unnecessary, although they may be aggregated within the DLL without interfering with the communication
between container and server.
When an OLE server application is implemented as an in-process server, a separate object handler is not required
because the server itself lives in the client's process space. The main difference between an in-process server and
object handler is that the server is able to manage the object in a running state while the handler cannot. One
consequence of this difference is that a server must provide a user interface for manipulating the running object,
while a handler delegates this requirement to the object's server. In creating an in-process server, you can
aggregate on the OLE default handler, letting it handle basic chores, such as display, storage, and notifications
while you implement only those services that the handler either does not provide or does not implement in the
way you require.
For more information, see the following topics:
Advantages
Disadvantages
Related topics
C
o
m
p
o
u
n
d
D
o
c
u
m
e
n
t
s
Advantages
1/7/2020 • 2 minutes to read • Edit Online
The advantages of implementing your application as an in-process server are speed and combining some the
advantages of an object handler and a local server. In-process servers are faster than local servers for several
reasons. First, because they are smaller and run in the process space of the container application, they load more
quickly. Second, they are optimized to perform certain tasks. Third, communication between container and server
does not rely on remote procedure calls.
Related topics
D
i
s
a
d
v
a
n
t
a
g
e
s
I
n
-
P
r
o
c
e
s
s
S
e
r
v
e
r
s
Disadvantages
1/7/2020 • 2 minutes to read • Edit Online
In-process servers provide the speed and size advantage of an object handler with the editing capability of a local
server. So why would you ever choose to implement your OLE application as a local server rather than an in-
process server? There are several reasons:
Security. Only a local server has its address space isolated from that of the client. An in-process server shares
the address space and process context of the client and can therefore be less robust in the face of faults or
malicious programming.
Granularity. A local server can host multiple instances of its object across many different clients, sharing server
state between objects in multiple clients in ways that would be difficult or impossible if implemented as an in-
process server, which is simply a DLL loaded into each client.
Compatibility. If you choose to implement an in-process server, you relinquish compatibility with OLE 1, which
does not support such servers. This will not be a consideration for many developers, but if it is, then it is of
critical concern.
Inability to support links. An in-process server cannot serve as a link source. Since a DLL cannot run by itself, it
cannot create a file object to be linked to.
Despite these disadvantages, an in-process server can be an excellent choice for its speed and size — if it fits all
your other requirements.
Related topics
A
d
v
a
n
t
a
g
e
s
I
n
-
P
r
o
c
e
s
s
S
e
r
v
e
r
s
Linked Objects and Monikers
1/7/2020 • 2 minutes to read • Edit Online
Linked objects, like embedded objects, rely on an object handler to communicate with server applications. The
linked object itself, however, manages the naming and tracking of link sources. The linked object acts like an in-
process server. For example, when activated, a linked object locates and launches the OLE server application that is
the link source.
A linked object's handler is made up of two main components: the handler component and the linking component.
The handler component contains the controlling and remoting pieces and functions much like a handler for an
embedded object. The linking component has its own controller and cache and provides access to the object's
structured storage. The linking components controller supports source naming through the use of monikers, and
binding, the process of locating and running the link source. (For more information on monikers and binding, see
The Component Object Model.)
When a user initially creates a linked object or loads an existing one from storage, the container loads an instance
of the linking component into memory, along with the object handler. The linking component supplies interfaces
— most notably IOleLink— that identify the object as a link and enable it to manage the naming, tracking, and
updating of its link source.
By implementing the IOleLink interface, a linked object provides its container with functions that support linking.
Only linked objects implement IOleLink, and by querying for this interface a container can determine whether a
given object is embedded or linked. The most important function provided by IOleLink enables a container to
binding to the source of the linked object, that is, to activate the connection to the document that stores the linked
object's native data. IOleLink also defines functions for managing information about the linked object, such as
cached presentation data and the location of the link source.
When a compound document containing a linked object is saved, the link's data is saved with the link source, not
with the container. Only information about its name and location is saved along with the compound document.
This behavior is in contrast to that of an embedded object, whose data is stored along with that of its container.
Container applications can provide information about their embedded objects such that the latter, or portions
thereof, can act as link sources. By implementing support for linking to your container's embedded objects, you
make nested embeddings possible, relieving the user of having to track down the originals of every embedding
object to which a link is desired. For example, if a user wants to embed a Microsoft Excel worksheet in Microsoft
Word, and the worksheet contains a bitmap created in Paintbrush, the user can link to a copy of the bitmap
contained in the worksheet rather than the original.
Related topics
C
o
m
p
o
u
n
d
D
o
c
u
m
e
n
t
s
I
n
-
P
r
o
c
e
s
s
S
e
r
v
e
r
s
O
b
j
e
c
t
H
a
n
d
l
e
r
s
Notifications
1/7/2020 • 2 minutes to read • Edit Online
Notifications are callbacks generated by an object when it detects a change in its name, state, data, or presentation.
Containers and other clients require notifications to respond appropriately to these changes. A container registers
to receive notifications by setting up an advisory connection to an object of interest. Other interested clients can do
the same. The container also creates an advisory sink to receive the notifications. Using the connection established
by the container, an object experiencing a change notifies the advisory sink. Upon receiving a notification, the
container takes whatever action has been defined for the type of change that has occurred.
For more information, see the following topics:
Types of Notifications
How Notifications Work
Related topics
C
o
m
p
o
u
n
d
D
o
c
u
m
e
n
t
s
Types of Notifications
1/7/2020 • 2 minutes to read • Edit Online
Notifications fall into three groups: compound document, data, and view. An object sends compound document
notifications in response to being renamed, saved, closed or, in the case of a link, having its link source renamed. As
you would expect, objects send data notifications in response to changes in their data and send view notifications
in response to changes in their presentation. Container applications must register separately for each of these
notification types, but all can be handled by a single advisory sink.
All containers, the object handler, and the linked object register for compound document notifications. The typical
container also registers for view notifications. Data notifications are usually sent to both the linked object and
object handler. A special purpose container, such as one that renders the data itself, might benefit from receiving
data notifications instead of view notifications. For example, an embedded chart container with a link to a table can
register for data notifications. Because a change to the table affects the chart, the receipt of a data notification
would direct the container to get the new tabular data.
Related topics
N
o
t
i
f
i
c
a
t
i
o
n
s
How Notifications Work
1/7/2020 • 2 minutes to read • Edit Online
Notifications originate in the object application and flow to the container by way of the object handler. If the object
is a linked object, the linked object intercepts the notifications from the object handler and notifies the container
directly.
An object application must manage registration requests, keeping track of where to send which notifications and
sending those notifications when appropriate. OLE provides two component objects to simplify this task: the
OleAdviseHolder for compound document notifications and the DataAdviseHolder for data notifications.
Object applications determine the conditions that prompt the sending of each specific notification and the
frequency with which each notification should be sent. When it is appropriate for multiple notifications to be sent, it
does not matter which notification is sent first; they can be sent in any order.
The timing of notifications affects the performance and coordination between an object application and its
containers. Whereas notifications sent too frequently slow processing, notifications sent too infrequently result in
an out-of-sync container. Notification frequency can be compared with the rate at which an application repaints.
Therefore, using similar logic for the timing of notifications (as is used for repainting) is wise.
Related topics
C
r
e
a
t
e
D
a
t
a
A
d
v
i
s
e
H
o
l
d
e
r
C
r
e
a
t
e
O
l
e
A
d
v
i
s
e
H
o
l
d
e
r
N
o
t
i
f
i
c
a
t
i
o
n
s
Compound Document Interfaces
1/7/2020 • 2 minutes to read • Edit Online
The following tables list the interfaces implemented by OLE containers, OLE servers, and compound document
objects. The required interfaces must be implemented on the components for which they are listed. All other
features are optional. If you want to include a particular feature in your application, however, you must implement
the interfaces shown for that feature in the table below. All other interfaces are required only if you are including a
particular feature.
The following table lists required and optional behaviors for OLE containers and which interfaces you must
implement for each.
BEHAVIOR INTERFACES
Linking none
The following table lists required and optional behaviors for OLE servers and their compound document objects
and which interfaces you must implement for each. The table distinguishes OLE servers and their objects in order
to clarify which component implements which interfaces. The table also notes the different requirements of objects
provided by out-of-process versus in-process servers.
Related topics
C
o
m
p
o
u
n
d
D
o
c
u
m
e
n
t
s
Object States
1/7/2020 • 2 minutes to read • Edit Online
A compound object exists in one of three states: passive, loaded, or running. A compound-document object's state
describes the relationship between the object in its container and the application responsible for its creation. The
following table summarizes these states.
Loaded The object's data structures created by the object handler are
in the container's memory. The container has established
communication with the object handler and there is cached
presentation data available for rendering the object. Calls are
processed by the object handler. This state, because of its low
overhead, is used when a user is simply viewing or printing an
object.
Running The objects that control remoting have been created and the
OLE server application is running. The object's interfaces are
accessible, and the container can receive notification of
changes. In this state, an end user can edit or otherwise
manipulate the object.
Related topics
C
o
m
p
o
u
n
d
D
o
c
u
m
e
n
t
s
Entering the Loaded State
1/7/2020 • 2 minutes to read • Edit Online
When an object enters the loaded state, the in-memory structures representing the object are created so that
operations can be invoked on it. The object's handler or in-process server is loaded. This process, referred to as
instantiation, occurs when an object is loaded from persistent storage (a transition from the passive to the loaded
state) or when an object is being created for the first time.
Internally, instantiation is a two-phase process. An object of the appropriate class is created, after which a method
on that object is called to perform initialization and give access to the object's data. The initialization method is
defined in one of the object's supported interfaces. The particular initialization method called depends on the
context in which the object is being instantiated and the location of the initialization data.
Entering the Running State
1/7/2020 • 2 minutes to read • Edit Online
When an embedded object makes the transition to the running state, the object handler must locate and run the
server application in order to utilize the services that only the server provides. Embedded objects are placed in the
running state either explicitly through a request by the container, such as a need to draw a format not currently
cached, or implicitly by OLE in response to invoking some operation, such as when a user of the container double-
clicks the object.
When a linked object makes the transition into the running state, the process is known as binding. In the process of
binding, the object handler asks its stored moniker to locate the link's data, then runs the server application.
At first glance, binding a linked object appears to be no more complicated than running an embedded object.
However, the following points complicate the process:
A link can refer to an object, or a portion thereof, that is embedded in another container. This capability implies
a potential for nested embeddings. Resolving references to such a hierarchy requires recursively traversing a
composite moniker, beginning with the rightmost member.
When the link source is running, OLE binds to the running instance of the object rather than running another
instance. In the case of nested embedded objects, one of which is the link source, OLE must be able to bind to
an already running object at any point.
Running an object requires accessing the storage area for the object. When an embedded object is run, OLE
receives a pointer to the storage during the load process, which it passes on to the OLE server application. For
linked objects, however, there is no standard interface for accessing storage. The OLE server application may
use the file system interface or some other mechanism.
Entering the Passive State
1/7/2020 • 2 minutes to read • Edit Online
Object closure forces an embedded or linked object into the passive state. It is typically initiated from the OLE
server application's user interface, such as when the user selects the File Close command. In this case, the OLE
server application notifies the container, which releases its reference count on the object. When all references to the
object have been released, the object can be freed. When all objects have been freed, the OLE server application
can safely terminate.
A container application can also initiate object closure. To close an object, the container releases its reference count
after completing an optional save operation. You can design containers to release objects when they are
deactivating after an in-place activation session, allowing the user to click outside the object without losing the
active editing session.
Implementing In-Place Activation
1/7/2020 • 2 minutes to read • Edit Online
In-place activation enables a user to interact with an embedded object without leaving the container document.
When a user activates the object, a composite menu bar comprising elements from both the container application's
and server application's menu bars replaces the container's main menu bar. Commands and features from both
applications are thus available to the user, including context sensitive help for the active object. When a user begins
working with some non-object portion of the document, the object is deactivated, causing the container
document's original menu to replace the composite menu.
This capability originally went by the name of in-place editing. The name was changed because editing is only one
way for a user to interact with a running object. Sound clips, for example, can be listened to instead of editing.
Video clips can be viewed instead of editing. In-place activation is particularly apt in the case of video clips because
it allows them to run in place, without calling up a separate window. This could be critical if the video were to be
viewed, say, in conjunction with adjacent text data in the container document.
Implementing in-place activation is strictly optional for both container and server applications. OLE still supports
the model in which activating an object causes the server application to open a separate window. Linked objects
always open in a separate window to emphasize that they reside in a separate document.
In-place activation begins with the object in response to an IOleObject::DoVerb call from its container. This call
usually happens in response to a user double-clicking the object or selecting a command (verb) from the container
application's Edit menu.
The in-place window receives keyboard and mouse input while the embedded object is active. When a user selects
commands from the composite menu bar, the command and associated menu messages are sent to the container
or object application, depending on which owns the particular drop-down menu selected. Input by means of an
object's rulers, toolbars, or frame adornments go directly to the embedded object, which owns these windows.
An in-place-activated embedded object remains active until either the container deactivates it in response to user
input or the object voluntarily gives up the active state, as a video clip might do, for example. A user can deactivate
an object by clicking inside the container document but outside the object's in-place-activation window, or simply
by clicking another object. An in-place-activated object remains active, however, if the user clicks the container's
title bar, scroll bar or, in particular, menu bar.
You can implement an in-place-activation-object server either as an in-process server (DLL ) or a local server (EXE ).
In both cases, the composite menu bar contains items (typically drop-down menus) from both the server and
container processes. In the case of a in-process server, the in-place activation window is simply another child
window in the container's window hierarchy, receiving its input through the container application's message pump.
In the case of a local server, the in-place activation window belongs to the embedded object's server application
process, but its parent window belongs to the container. Input for the in-place-activation window appears in the
server's message queue and is dispatched by the server's message loop. The OLE libraries are responsible for
seeing to it that menu commands and messages are dispatched correctly.
Related topics
C
o
m
p
o
u
n
d
D
o
c
u
m
e
n
t
s
Creating Linked and Embedded Objects from
Existing Data
1/7/2020 • 2 minutes to read • Edit Online
A user typically assembles a compound document by using either the clipboard or drag and drop to copy a data
object from its server application to the user's container application. With applications that support OLE, the user
can initiate the transfer from either the server or the container. For example, the server can copy data to the
clipboard in the server application, then switch to the container application and choose Paste Special/Embedded
Object or an equivalent menu command to create a new embedded object from the selected data. Or, the user can
drag the data from one application to the other. The process is similar for creating a linked object.
NOTE
An application that functions as both OLE server and container can use a selection of its own data to create an embedded or
linked object at a new location within the same document.
Data transfer between OLE server and container applications is built on uniform data transfer, as described in
Data Transfer. OLE servers and object handlers implement IDataObject in order to make their data available for
transfers using either the clipboard or drag and drop. OLE objects support all the usual clipboard formats. In
addition, they support six clipboard formats that support the creation of linked and embedded objects from a
selected data object.
OLE clipboard formats describe data objects that, upon being dropped or pasted in OLE containers, are to become
embedded or linked compound-document objects. The data object presents these formats to container
applications in order of their fidelity as descriptions of the data. In other words, the object presents first the format
that best represents it, followed by the next best format, and so on. This intentional ordering encourages a
container application to use the best possible format.
Related topics
C
o
m
p
o
u
n
d
D
o
c
u
m
e
n
t
s
D
a
t
a
T
r
a
n
s
f
e
r
View Caching
1/7/2020 • 4 minutes to read • Edit Online
A container application must be able to obtain a presentation of an object for the purpose of displaying or printing
it for users when the document is open but the object's server application is not running or is not installed on the
user's machine. To assume, however, that the servers for all the objects that might conceivably be found in a
document are installed on every user's machine and can always run on demand is unrealistic. The default object
handler, which is available at all times, solves this dilemma by caching object presentations in the document's
storage and manipulating these presentations on any platform regardless of the availablility of the object server
on any particular installation of the container.
Containers can maintain drawing presentations for one or more specific target devices in addition to the one
required to maintain the object on screen. Moreover, if you port the object from one platform to another, OLE
automatically converts the object's data formats to ones supported on the new platform. For example, if you move
an object from Windows to the Macintosh, OLE will convert its metafile presentations to PICT formats.
In order to present an accurate representation of an embedded object to the user, the object's container application
initiates a dialog with the object handler, requesting data and drawing instructions. To be able to fulfill the
container's requests, the handler must implement the IDataObject, IViewObject2, and IOleCache interfaces.
IDataObject enables an OLE container application to get data from and send data to its embedded or linked
objects. When data changes in an object, this interface provides a way for the object to make its new data available
to its container and provides the container with a way to update the data in its copy of the object. (For a discussion
of data transfer in general, see Chapter 4, Data Transfer.)
The IViewObject2 interface is very much like the IDataObject interface except that it asks an object to draw
itself on a device context, such as a screen, printer, or metafile, rather than move or copy its data to memory or
some other transfer medium. The purpose of the interface is to enable an OLE container to obtain alternative
pictorial representations of its embedded objects, whose data it already has, thereby avoiding the overhead of
having to transfer entirely new instances of the same data objects simply to obtain new drawing instructions.
Instead, the IViewObject2interface enables the container to ask an object to provide a pictorial representation of
itself by drawing on a device context specified by the container.
When calling the IViewObject2 interface, a container application can also specify that the object draw itself on a
target device different than the one on which it will actually be rendered. This enables the container, as needed, to
generate different renderings from a single object. For example, the caller could ask the object to compose itself
for a printer even though the resulting drawing will be rendered on screen. The result, of course, would be a print-
preview of the object.
The IViewObject2interface also provides methods that enable containers to register for view -change
notifications. As with data and OLE advisories, a view advisory connection enables a container to update its
renderings of an object at its own convenience rather than in response to a call from the object. For example, if a
new version of an object's server application were to offer additional views of the same data, the object's default
handler would call each container's implementation of IAdviseSink::OnViewChange to let them know that the
new presentations were available. The container would retrieve this information from the advise sink only when
needed.
Because Windows device contexts have meaning only within a single process, you cannot pass IViewObject2
pointers across process boundaries. As a result, OLE local and remote servers have no need whatsoever to
implement the interface, which wouldn't work properly even if they did. Only object handlers and in-process
servers implement the IViewObject2interface. OLE provides a default implementation, which you can use in your
own OLE in-process servers and object handlers simply by aggregating the OLE default handler. Or you can write
your own implementation of IViewObject2.
An object implements the IOleCache interface in order to let the handler know what capabilities it should cache.
The object handler also owns the cache and ensures it is kept up to date. As the embedded object enters the
running state, the handler sets up appropriate advisory connections on the server object, with itself acting as the
sink. The IDataObject and IViewObject2interface implementations operate out of data cached on the client side.
The handler's implementation of IViewObject2is responsible for determining what data formats to cache in order
to satisfy client draw requests. The handler's implementation of IDataObject is responsible for getting data in
various formats, etc., between memory and the underlying IStorage instance of the embedded object. Custom
handlers can use these implementations by aggregating on the default handler.
NOTE
The IViewObject2 interface is a simple functional extension of IViewObject and should be implemented instead of the latter
interface, which is now obsolete. In addition to providing the IViewObject methods, the IViewObject2 interface provides a
single additional member, GetExtent, which enables a container application to get the size of an object's presentation from
the cache without first having to move the object into the running state with a call to IOleObject::GetExtent.
Related topics
C
o
m
p
o
u
n
d
D
o
c
u
m
e
n
t
s
Data Transfer
1/7/2020 • 2 minutes to read • Edit Online
The Component Object Model (COM ) provides a standard mechanism for transferring data between applications.
This mechanism is the data object, which is simply any COM object that implements the IDataObject interface.
Some data objects, such as a piece of text copied to the clipboard, have IDataObject as their sole interface.
Others, such as compound document objects, expose several interfaces, of which IDataObject is simply one.
Data objects are fundamental to the working of compound documents, although they also have widespread
application outside that OLE technology.
By exchanging pointers to a data object, providers and consumers of data can manage data transfers in a uniform
manner, regardless of the format of the data, the type of medium used to transfer the data, or the target device on
which it is to be rendered. You can include support in your application for basic clipboard transfers, drag and drop
transfers, and OLE compound document transfers with a single implementation of IDataObject. Having done
that, the amount of code required to accommodate the special semantics of each protocol is minimal.
For more information, see the following topics:
Data Transfer Interfaces
Data Formats and Transfer Media
Drag and Drop
Related topics
C
o
m
p
o
u
n
d
D
o
c
u
m
e
n
t
s
Data Transfer Interfaces
1/7/2020 • 2 minutes to read • Edit Online
The IDataObject interface provides consumers of data with methods for getting and setting an object's data,
determining which formats the object supports, and registering for and receiving notifications when data in the
object changes. When obtaining data, a caller can specify the format in which it wants to render the data. The
source of the data, however, determines the storage medium, which it returns in an out parameter provided by the
caller.
By itself, IDataObject supplies all the tools you need to implement Windows clipboard transfers or compound
document transfers in your applications. If you also want to support drag and drop transfers, you need to
implement the IDropSource and IDropTarget interfaces along with IDataObject.
The IDataObject interface combined with OLE clipboard APIs provide all the capabilities of the Windows
clipboard APIs. It is not generally necessary to use both clipboard APIs. Data suppliers that support either drag
and drop transfers or OLE compound documents must implement the IDataObject interface. If your application
supports only clipboard transfers now, but you intend to add drag and drop or compound documents in later
releases, you may want to implement IDataObject and the OLE clipboard APIs now in order to minimize the
amount of time spent recoding and debugging later. You may also want to implement IDataObject in order to
utilize transfer media other than global memory.
The following table summarizes which ones to use, depending on what types of data transfer you want to support:
TO SUPPORT USE
Clipboard transfers now but drag and drop or compound IDataObject and the interfaces and function listed above for
documents later "Drag and drop transfers"
When a user initiates a data transfer operation, the source application creates an instance of IDataObject and
through it makes the data available in one or more formats. In a clipboard transfer, the application calls the
OleSetClipboard function to pass a data-object pointer to OLE. (OleSetClipboard also offers standard clipboard
data formats for both OLE version 1 and non-OLE applications.) In a drag and drop transfer, the application calls
the DoDragDrop function instead.
On the receiving side of the transfer, the destination receives the IDataObject pointer either as an argument to an
invocation of IDropTarget::Drop or by calling the OleSetClipboard function, depending on whether the transfer
is by means of drag and drop or the clipboard. Having obtained this pointer, the destination calls
IDataObject::EnumFormatEtc to learn what formats are available for retrieval and on what types of media they
can be obtained. Armed with this information, the receiving application requests the data with a call to
IDataObject::GetData.
Related topics
D
a
t
a
T
r
a
n
s
f
e
r
Data Formats and Transfer Media
1/7/2020 • 2 minutes to read • Edit Online
Most platforms, including Windows, define a standard protocol for transferring data between applications, based
on a set of functions called the clipboard. Applications using these functions can share data even if their native data
formats are wildly different. Generally, these clipboards have two significant shortcomings that COM has
overcome.
First, data descriptions use only a format identifier, such as the single 16-bit clipboard format identifier on
Windows, which means the clipboard can only describe the structure of its data, that is, the ordering of the bits. It
can report, "I have a bitmap" "or I have some text," but it cannot specify the target devices for which the data is
composed, which views or aspects of itself the data can provide, or which storage media are best suited for its
transfer. For example, it cannot report, "I have a string of text that is stored in global memory and formatted for
presentation either on screen or on a printer" or "I have a thumbnail sketch bitmap rendered for a 100 dpi dot-
matrix printer and stored as a disk file."
Second, all data transfers using the clipboard generally occur through global memory. Using global memory is
reasonably efficient for small amounts of data but horribly inefficient for large amounts, such as a 20 MB
multimedia object. Global memory is slow for a large data object, whose size requires considerable swapping to
virtual memory on disk. In cases where the data being exchanged is going to reside mostly on disk anyway,
forcing it through this virtual-memory bottleneck is highly inefficient. A better way would skip global memory
entirely and simply transfer the data directly to disk.
To alleviate these problems, COM provides two data structures: FORMATETC and STGMEDIUM. For more
information, see the following topics:
The FORMATETC Structure
The STGMEDIUM Structure
Related topics
D
a
t
a
T
r
a
n
s
f
e
r
The FORMATETC Structure
1/7/2020 • 2 minutes to read • Edit Online
The FORMATETC structure is a generalized clipboard format, enhanced to encompass a target device, an aspect or
view of the data, and a storage medium. A data consumer, such as an OLE container application, passes the
FORMATETC structure as an argument in calls to IDataObject to indicate the type of data it wants from a data
source, such as a compound document object. The source uses the FORMATETC structure to describe what
formats it can provide.
FORMATETC can describe virtually any data, including other objects such as monikers. A container can ask one of
its embedded objects to list its data formats by calling IDataObject::EnumFormatEtc, which returns an
enumerator object that implements the IEnumFORMATETC interface. Instead of replying merely that it has "text
and a bitmap," the object can provide a detailed description of the data, including the device (normally screen or
printer) for which it is rendered, the aspect to be presented to the user (full contents, thumbnail, icon, or formatted
for printing), and the storage medium containing the data (global memory, disk file, storage object, or stream). This
ability to tightly describe data will, in time, result in higher quality printer and screen output as well as more
efficiency in data browsing, where a thumbnail sketch is much faster to retrieve and display than a fully detailed
rendering.
The following table lists fields of the FORMATETC data structure and the information that they specify.
FIELD SPECIFIES
dwAspect The aspect or view of the data to be rendered; can be the full
contents, a thumbnail sketch, an icon, or formatted for
printing.
lindex The part of the aspect that is of interest; for the present, the
value must be -1, indicating that the entire view is of interest.
tymed The data's storage medium, which can be global memory, disk
file, or an instance of one of COM's structured-storage
interfaces.
Related topics
D
a
t
a
F
o
r
m
a
t
s
a
n
d
T
r
a
n
s
f
e
r
M
e
d
i
a
The STGMEDIUM Structure
1/7/2020 • 2 minutes to read • Edit Online
Just as the FORMATETC structure is an enhancement of the Windows clipboard format identifier, so the
STGMEDIUM structure is an improvement of the global memory handle used to transfer the data. The
STGMEDIUM structure includes a member, tymed, which indicates the medium to be used, and a union
comprising pointers and a handle for getting whichever medium is specified in tymed.
The STGMEDIUM structure enables both data sources and consumers to choose the most efficient exchange
medium on a per-rendering basis. If the data is so large that it should be kept on disk, the data source can indicate
a disk-based medium in its preferred format, only using global memory as a backup if that's the only medium the
consumer understands. Being able to use the best medium for exchanges as the default improves overall
performance of data exchange between applications. For example, if some of the data to be transferred is already
on disk, the source application can move or copy it to a new destination, either in the same application or in some
other, without having first to load the data into global memory. At the receiving end, the consumer of the data does
not have to write it back to disk.
Related topics
D
a
t
a
F
o
r
m
a
t
s
a
n
d
T
r
a
n
s
f
e
r
M
e
d
i
a
Drag and Drop
1/7/2020 • 2 minutes to read • Edit Online
Drag and drop refers to data transfers in which a mouse or other pointing device is used to specify both the data
source and its destination. In a typical drag and drop operation, a user selects the object to be transferred by
moving the mouse pointer to it and holding down either the left button or some other button designated for this
purpose. While continuing to hold down the button, the user initiates the transfer by dragging the object to its
destination, which can be any OLE container. Drag and drop provides exactly the same functionality as the OLE
clipboard copy and paste but adds visual feedback and eliminates the need for menus. In fact, if an application
supports clipboard copy and paste, little extra is needed to support drag and drop.
During an OLE drag and drop operation, the following three separate pieces of code are used.
DoDragDrop function Implemented by OLE and used to initiate a drag and drop
operation. After the operation is in progress, it facilitates
communication between the drag source and the drop target.
The IDropSource and IDropTarget interfaces can be implemented in either a container or in an object
application. The role of drag source or drop target is not limited to any one type of OLE application.
The OLE function DoDragDrop implements a loop that tracks mouse and keyboard movement until such time as
the drag is canceled or a drop occurs. DoDragDrop is the key function in the drag and drop process, facilitating
communication between the drag source and drop target.
During a drag and drop operation, three types of feedback can be displayed to the user.
Source feedback Provided by the drag source, the source feedback indicates
the data is being dragged and does not change during the
course of the drag. Typically, the data is highlighted to signal it
has been selected.
Pointer feedback Provided by the drag source, the pointer feedback indicates
what happens if the mouse is released at any given moment.
Pointer feedback changes continually as the user moves the
mouse and/or presses a modifier key. For example, if the
pointer is moved into a window that cannot accept a drop, the
pointer changes to the "not allowed" symbol.
Target feedback Provided by the drop target, target feedback indicates where
the drop is to occur.
Related topics
D
r
a
g
a
n
d
D
r
o
p
Data Notification
1/7/2020 • 2 minutes to read • Edit Online
Objects that consume data from an external source sometimes need to be informed when data in that source
changes. For example, a stock ticker tape viewer that relies on data in some spreadsheet needs to be notified when
that data changes so it can update its display. Similarly, a compound document needs information about data
changes in its embedded objects so that it can update its data caches. In cases such as this, where dynamic
updating of data is desirable, sources of data require some mechanism of notifying data consumers of changes as
they occur without obligating the consumers to drop everything in order to update their data. Ideally, having been
notified that a change has occurred in the data source, a consuming object can ask for an updated copy at its
leisure.
COM's mechanism for handling asynchronous notifications of this type is an object called an advise sink, which is
simply any COM object that implements an interface called IAdviseSink. Consumers of data implement the
IAdviseSink. They register to receive notifications by handing a pointer to the data object of interest.
The IAdviseSink interfaces exposes the following methods for receiving asynchronous notifications:
OnViewChange The instructions for drawing the calling object have changed.
As the table indicates, the IAdviseSink interface exposes methods for notifying the advise sink of events other
than changes in the calling object's data. The calling object can also notify the sink when the way in which it draws
itself changes, or it is renamed, saved, or closed. These other notifications are used mainly or entirely in the context
of compound documents, although the notification mechanism is identical. For more information on compound-
document notifications, see "Compound Documents."
In order to take advantage of the advise sink, a data source must implement IDataObject::DAdvise,
IDataObject::DUnadvise, and IDataObject::EnumDAdvise. A data consumer calls the DAdvise mothod to
notify a data object that it wishes to be notified when the object's data changes. The consuming object calls the
DUnadvise method to tear down this connection. Any interested party can call the EnumDAdvise method to
learn the number of objects having an advisory connection with a data object.
When data changes at the source, the data object calls IAdviseSink::OnDataChange on all data consumers that
have registered to receive notifications. To keep track of advisory connections and manage the dispatch of
notifications, data sources rely on an object called a data advise holder. You can create your own data advise holder
by implementing the IDataAdviseHolder interface. Or, you can let COM do it for you by calling the helper
function CreateDataAdviseHolder.
Related topics
D
a
t
a
T
r
a
n
s
f
e
r
Reference
1/7/2020 • 2 minutes to read • Edit Online
The following programming elements are used to implement compound documents and perform data transfer
between applications.
Constants
Enumerations
Functions
Interfaces
Structures
Constants
1/7/2020 • 2 minutes to read • Edit Online
The following constants are used to implement compound documents and perform data transfer between
applications.
DROPEFFECT Constants
DROPEFFECT Constants
1/7/2020 • 2 minutes to read • Edit Online
Represents information about the effects of a drag-and-drop operation. The DoDragDrop function and many of
the methods in the IDropSource and IDropTarget use the values of this enumeration.
CONSTANT/VALUE DESCRIPTION
Remarks
Your application should always mask values from the DROPEFFECT enumeration to ensure compatibility with
future implementations. Presently, only some of the positions in a DROPEFFECT value have meaning. In the
future, more interpretations for the bits will be added. Drag sources and drop targets should carefully mask these
values appropriately before comparing. They should never compare a DROPEFFECT against, say,
DROPEFFECT_COPY by doing the following:
if (dwDropEffect == DROPEFFECT_COPY)...
Instead, the application should always mask for the value or values being sought as using one of the following
techniques:
This allows for the definition of new drop effects, while preserving backward compatibility with existing code.
Requirements
Header
OleI
dl.h
See also
D
o
D
r
a
g
D
r
o
p
I
D
r
o
p
S
o
u
r
c
e
I
D
r
o
p
T
a
r
g
e
t
Enumerations
1/7/2020 • 2 minutes to read • Edit Online
The following enumerations are used to implement compound documents and perform data transfer between
applications.
ACTIVATEFLAGS
ADVF
DATADIR
DISCARDCACHE
DOCMISC
DVASPECT
DVASPECT2
DVASPECTINFOFLAG
DVEXTENTMODE
HITRESULT
OLECLOSE
OLECMDEXECOPT
OLECMDF
OLECMDID
OLECMDID_WINDOWSTATE_FLAG
OLECMDTEXTF
OLECONTF
OLEDCFLAGS
OLEGETMONIKER
OLELINKBIND
OLEMISC
OLERENDER
OLEUIPASTEFLAG
OLEUPDATE
OLEVERBATTRIB
OLEWHICHMK
TYMED
UASFLAGS
USERCLASSTYPE
VIEWSTATUS
Functions
1/7/2020 • 2 minutes to read • Edit Online
The following functions are used to implement compound documents and perform data transfer between
applications.
CreateDataAdviseHolder
CreateDataCache
CreateFormatEnumerator
CreateOleAdviseHolder
DoDragDrop
OleCreate
OleCreateDefaultHandler
OleCreateEmbeddingHelper
OleCreateEx
OleCreateFontIndirect
OleCreateFromData
OleCreateFromDataEx
OleCreateFromFile
OleCreateFromFileEx
OleCreateLink
OleCreateLinkEx
OleCreateLinkFromData
OleCreateLinkFromDataEx
OleCreateLinkToFile
OleCreateLinkToFileEx
OleCreateMenuDescriptor
OleCreatePictureIndirect
OleCreateStaticFromData
OleDestroyMenuDescriptor
OleDraw
OleDuplicateData
OleFlushClipboard
OleGetClipboard
OleInitialize
OleIsCurrentClipboard
OleIsRunning
OleLoad
OleLoadFromStream
OleLoadPicture
OleLoadPictureEx
OleLockRunning
OleMetafilePictFromIconAndLabel
OleNoteObjectVisible
OleQueryCreateFromData
OleQueryLinkFromData
OleRegEnumFormatEtc
OleRegEnumVerbs
OleRun
OleSave
OleSaveToStream
OleSetClipboard
OleSetContainedObject
OleSetMenuDescriptor
OleTranslateAccelerator
OleUIAddVerbMenu
OleUIBusy
OleUICanConvertOrActivateAs
OleUIChangeIcon
OleUIChangeSource
OleUIConvert
OleUIEditLinks
OleUIInsertObject
OleUIObjectProperties
OleUIPasteSpecial
OleUIPromptUser
OleUIUpdateLinks
OleUninitialize
RegisterDragDrop
ReleaseStgMedium
RevokeDragDrop
Interfaces
1/7/2020 • 4 minutes to read • Edit Online
The following interfaces are used to implement compound documents and perform data transfer between
applications.
INTERFACE DESCRIPTION
IOleUILinkContainer OLE common dialog boxes use this interface to manage the
properties of a container's links.
The following structures are used to implement compound documents and perform data transfer between
applications.
DVASPECTINFO
DVEXTENTINFO
DVTARGETDEVICE
FORMATETC
OBJECTDESCRIPTOR
OLECMD
OLECMDTEXT
OLEINPLACEFRAMEINFO
OLEMENUGROUPWIDTHS
OLEUIBUSY
OLEUICHANGEICON
OLEUICHANGESOURCE
OLEUICONVERT
OLEUIEDITLINKS
OLEUIGNRLPROPS
OLEUIINSERTOBJECT
OLEUILINKPROPS
OLEUIOBJECTPROPS
OLEUIPASTEENTRY
OLEUIPASTESPECIAL
OLEUIVIEWPROPS
OLEVERB
POINTF
STATDATA
STGMEDIUM
Controls and Property Pages
1/7/2020 • 2 minutes to read • Edit Online
The following sections describe ActiveX controls, standard property pages, and the APIs that are used to create
property pages:
Guide
Reference
Related topics
C
o
m
p
o
n
e
n
t
O
b
j
e
c
t
M
o
d
e
l
(
C
O
M
)
Guide
1/7/2020 • 2 minutes to read • Edit Online
This guide describes ActiveX controls, property pages, and property sheets.
ActiveX Controls
Property Pages and Property Sheets
ActiveX Control and Control Container Guidelines
Related topics
R
e
f
e
r
e
n
c
e
ActiveX Controls
1/7/2020 • 3 minutes to read • Edit Online
ActiveX controls technology rests on a foundation consisting of COM, connectable objects, compound
documents, property pages, OLE automation, object persistence, and system-provided font and picture objects.
As summarized below, each of these core technologies plays a role in controls.
C
O
M
A control is essentially a COM object that exposes the IUnknown interface, through which clients can
obtain pointers to its other interfaces. Controls can support licensing through IClassFactory2 and self-
registration. See The Component Object Model for more information on COM, licensing, and self-
registration.
C
o
n
n
e
c
t
a
b
l
e
o
b
j
e
c
t
s
Controls can support outgoing interfaces through connectable objects so that the control can communicate
with its client. For example, an outgoing interface can trigger an action in the client, can notify the client of
some change in the control, or can request permission from the client before the control takes some action.
See Events in COM and Connectable Objects for more information on how connectable objects work.
U
n
i
f
o
r
m
d
a
t
a
t
r
a
n
s
f
e
r
Controls can support being dragged and dropped within a container with help from their container. See
IOleInPlaceObjectWindowless::GetDropTarget for more information on drag and drop.
C
o
m
p
o
u
n
d
d
o
c
u
m
e
n
t
s
A control can be an in-place active object that can be embedded in a containing client. An end-user activates
the control to initiate an action in the container application. See Compound Documents for more
information on in-place activation and other compound document interfaces.
P
r
o
p
e
r
t
y
p
a
g
e
s
Controls can provide property pages so end users can view and change the control's properties. See
Property Pages and Property Sheets for more information on how property pages work.
O
L
E
a
u
t
o
m
a
t
i
o
n
Controls can provide programmability through OLE automation so clients can take advantage of the
control's features through a programming language supplied by the client. See the OLE Automation section
for more information on OLE automation.
P
e
r
s
i
s
t
e
n
t
s
t
o
r
a
g
e
A control can implement one or more of several persistence interfaces to support persistence of its state.
The control implementer must decide what kinds of persistence are most important and implement the
appropriate persistence interfaces. The client decides which interface it prefers to use. See The Component
Object Model for more information on all the persistence interfaces.
F
o
n
t
a
n
d
p
i
c
t
u
r
e
o
b
j
e
c
t
s
Controls can use these system provided objects to provide a visual representation of themselves within the
client. The font object implements several interfaces, including IFont and IFontDisp. A font object can be
created with OleCreateFontIndirect. The picture object also implements several interfaces, including
IPicture and IPictureDisp. A picture object can be created using OleCreatePictureIndirect and can
loaded from a stream with OleLoadPicture.
It is important to understand that these features can be used in any OLE object. One does not need to implement
a control in order to use these features. Also, the only required interface on a control is IUnknown. The control
optionally supports other interfaces based on the need to support the related features.
In addition to these features, the following interfaces and functions are specific to controls technology:
IOleControl, IOleControlSite, ISimpleFrameSite, and OleTranslateColor. Also specific to controls are a set
of standards for properties and methods that a control or a control container can support.
NOTE
The system library OleAut32.dll contains implementations of the functions ( OleCreatePropertyFrame,
OleCreatePropertyFrameIndirect, OleCreateFontIndirect, OleCreatePictureIndirect, OleLoadPicture, and
OleTranslateColor). In addition, OleAut32.dll contains the implementations of the standard font and picture objects, as
well as a type library for all the interfaces used with controls as well as the additional data structures and data types.
Related topics
A
c
t
i
v
e
X
C
o
n
t
r
o
l
a
n
d
C
o
n
t
r
o
l
C
o
n
t
a
i
n
e
r
G
u
i
d
e
l
i
n
e
s
ActiveX Controls Architecture
1/7/2020 • 2 minutes to read • Edit Online
ActiveX controls technology builds on a foundation of many lower-level objects and interfaces in OLE. The exact
interfaces available on a control vary with its capabilities. This section takes a closer look at the capabilities a
control might provide.
ActiveX controls are used to provide the building blocks for creating user interfaces in applications. For example, a
button that initiates some action in the container application when it is clicked is a simple control. The following
aspects are involved in providing these user interface building blocks:
A control can be embedded within its container client to support some user interface activity within the client.
Thus, a control needs to provide a visual representation of itself when it is embedded within the container and
needs to provide a way to save its state, for example, its property values and its position within its container. The
client must support being a container with objects embedded in it.
By activating the control using a keyboard or mouse, the end user initiates some action in the client application.
Thus, a control must respond to keyboard activity and must be able to communicate with its client so it can
notify its container of its activities and trigger events in the client.
The client also typically provides a programming language through which the end user can initiate actions
provided by the control's properties and methods. Thus, a control must support automation and some set of
design-time versus run-time features as well.
As a result of its role in providing user interface building blocks, a control typically supports features in the
following areas using OLE technologies as indicated:
P
r
o
p
e
r
t
i
e
s
a
n
d
m
e
t
h
o
d
s
Like any OLE object, a control can provide much of its functionality through a set of incoming interfaces with
properties and methods. The container can supply additional ambient properties, and it can support
extending the control's properties through aggregation. These features rest on OLE automation, property
pages, connectable objects, and ActiveX control technologies.
E
v
e
n
t
s
In addition to providing properties and methods, an ActiveX control can also provide outgoing interfaces to
notify its client of events. The client must support handling of these events. These features use OLE
automation and connectable objects.
V
i
s
u
a
l
r
e
p
r
e
s
e
n
t
a
t
i
o
n
A control can support positioning and displaying itself within its container. The container positions the
control and determines its size. These features use compound document technology, including OLE drag and
drop technology.
K
e
y
b
o
a
r
d
h
a
n
d
l
i
n
g
A control can respond to keyboard accelerators so the end-user can initiate actions performed by the control.
The container manages keyboard activity for all its embedded controls. These features use control and
compound document technologies.
P
e
r
s
i
s
t
e
n
c
e
A control can save its state. The client manages the persistence of its embedded controls. These features use
structured storage and object persistence technologies.
R
e
g
i
s
t
r
a
t
i
o
n
a
n
d
l
i
c
e
n
s
i
n
g
A control typically supports self-registration and creates a set of registry entries when it is instantiated. A
control can also be licensed to help prevent unauthorized use.
Most of these features involve both the control and its client container.
Related topics
A
c
t
i
v
e
X
C
o
n
t
r
o
l
s
ActiveX Controls Interfaces
1/7/2020 • 2 minutes to read • Edit Online
In addition to other mechanisms for communicating between the control and its client, ActiveX controls technology
specifies the IOleControl and IOleControlSite interfaces for client-control communication. There is also the
ISimpleFrameSite interface for simple control containers.
These three interfaces are, however, specific to controls and are not generally useful outside the context of controls.
These interfaces are defined as follows.
Some controls, like a group box, are merely a simple container of other controls. In such cases, the simple control,
called a simple frame, doesn't have to implement all the container requirements. It can delegate most of the
interface calls from its contained controls to the container that manages the simple frame. Besides interface calls,
the simple frame also has to deal with Windows messages that potentially come from controls within it. For this
reason, a container supplies ISimpleFrameSite to allow such simple frame controls to pass messages up to the
container. PreMessageFilter processes the message first; PostMessageFilter is called after the simple frame has
processed the message itself.
Related topics
A
c
t
i
v
e
X
C
o
n
t
r
o
l
s
Properties and Methods
1/7/2020 • 2 minutes to read • Edit Online
Like any OLE object, a control provides much of its functionality through a set of incoming interfaces with
properties and methods.
A control exposes properties and methods through OLE automation so that containers can access them under the
control of a container-supplied programming language.
To support access to properties through a user interface, a control provides property pages, support for
OLEIVERB_PROPERTIES, per property browsing, and data binding through property change notfications.
Through property pages a control can display its properties, independent of its container, if necessary.
By supporting OLEIVERB_PROPERTIES, the Properties item is displayed on the container's menu. Then, the
end user can select the Properties item to view the control's property pages and modify the properties.
Per property browsing supports a container that can display the control's properties as part of a larger property
sheet that may include properties from several controls in the container.
Through property change notification, a control can notify a client that its properties have change, allowing the
client to take any necessary actions as a result.
For more information, see the following topics:
Control Properties
Control Methods
Related topics
A
c
t
i
v
e
X
C
o
n
t
r
o
l
s
P
r
o
p
e
r
t
y
P
a
g
e
s
a
n
d
P
r
o
p
e
r
t
y
S
h
e
e
t
s
Control Properties
1/7/2020 • 2 minutes to read • Edit Online
In addition to properties defined and implemented by the control itself, ActiveX controls technology also involves:
A
m
b
i
e
n
t
p
r
o
p
e
r
t
i
e
s
These are exposed by the container through a control client site to provide environmental values that apply
to all controls embedded in the container. For example, a container can provide a default background color
or a default font that the control can use. Ambient properties are exposed through IDispatch implemented
on a container's site object. The container calls the control's IOleControl::OnAmbientPropertyChange
method when any of its ambient properties change value. In response, a control may need to update its own
internal or visual state in response. The container indicates which ambient property changed with the
DISPID parameter or may pass DISPID_UNKNOWN to indicate that multiple ambient properties changed.
E
x
t
e
n
d
e
d
p
r
o
p
e
r
t
i
e
s
These are actually implemented by a container to wrap the controls it contains to provide container-
managed properties that appear as if they were native control properties. The container can aggregate the
control, adding the extended properties to supplement or override the control's properties. The aggregated
object is called an extended control. To the container, the extended control appears as the control itself and
extended properties appear to be exposed by the control. The container supports an extended control
through its client site method IOleControlSite::GetExtendedControl. The GetExtendedControl method
allows controls to navigate through the site to the extended control object provided for them by the
container, if the container supports this feature. A container can also choose to show property pages for its
extended controls in addition to those pages that a control would normally specify through
ISpecifyPropertyPages. Because of this, a control has to ask a container to show a property frame before
the control attempts to do so itself. The control calls IOleControlSite::ShowPropertyFrame to do this. If
the container implements this function then it shows the property frame itself; if the method returns an error
then the control can show the property frame.
Related topics
C
o
n
t
r
o
l
M
e
t
h
o
d
s
Standard Properties
1/7/2020 • 3 minutes to read • Edit Online
OLE defines a set of standard DISPIDs for all three kinds of properties: control, ambient, and extended. The
following tables list these standards for control properties, ambient properties, and extended properties.
BackStyle, FillStyle, BorderStyle, short or long Bits that define a control's visual
BorderWidth, BorderVisible, DrawStyle, behavior, such as being solid or
DrawWidth transparent, having thick or thin
borders, line styles, and so forth.
All of these standard properties have negative DISPID values, indicating their standard status.
Note that to avoid conflicts in the programmatic symbols for these DISPIDs, all ambient properties are given
symbols in the form DISPID_AMBIENT_property as in DISPID_AMBIENT_FORECOLOR. All other symbols use
DISPID_property as usual.
Some ambient properties, as well as control properties, involve colors. The OLE_COLOR type mentioned in the
previous tables can refer to a standard COLORREF type, an index to a palette, a palette-relative index, or a system
color index used with the GetSysColor function. The OleTranslateColor function converts an OLE_COLOR type
to a COLORREF type given a palette.
Related topics
C
o
n
t
r
o
l
P
r
o
p
e
r
t
i
e
s
Standard Font Object
1/7/2020 • 2 minutes to read • Edit Online
The standard ambient font property supplied by the container and the standard font property supplied by the
control both provide a standard font object. That is, these standard fonts supply an IDispatch pointer to a
standard font object.
The font object is a system-provided implementation of a set of interfaces on top of the underlying GDI font
support. A font object is created through the API function OleCreateFontIndirect given a FONTDESC structure.
The font object supports a number of read/write properties as well as custom methods through its interface IFont,
and supports the same set of properties (but not the methods) through a dispinterface IFontDisp. The
dispinterface is used for the font properties mentioned previously. The properties correspond to the GDI font
attributes that are described in the LOGFONT structure.
The font object also supports the outgoing interface IPropertyNotifySink so that a client can determine when
font properties change. Since the font object supports at least one outgoing interface, it also implements
IConnectionPointContainer and one connection point for IPropertyNotifySink for this purpose.
The font object provides an hFont property that is a Windows font handle that conforms to the other attributes
specified for the font. The font object delays realizing this font when possible, so consecutively setting two
properties on a font won't cause an intermediate font to be realized. In addition, as an optimization, the standard
font object maintains a cache of font handles. Two font objects in the same process that have identical properties
will return the same font handle. The font object can remove fonts from this cache at will, which introduces special
considerations for clients using this hFont property. See IFont::get_hFont for more details.
The font object also supports IPersistStream such that it can save and load itself from an instance of IStream.
Any other object that uses a font object internally would normally save and load the font as part of the object's
own persistence handling.
In addition, the font object supports IDataObject through which it provides a property set containing typed
values for each font property.
Related topics
C
o
n
t
r
o
l
P
r
o
p
e
r
t
i
e
s
Standard Picture Object
1/7/2020 • 2 minutes to read • Edit Online
The standard picture object provides a language-neutral abstraction for GDI images: bitmaps, icons, metafiles, and
enhanced metafiles. As with the standard font object, the system provides a standard implementation of this object.
Its primary interfaces are IPicture and IPictureDisp, the latter being derived from IDispatch to provide access to
the picture's properties through OLE automation. A picture object is created new with OleCreatePictureIndirect.
The picture object also supports the outgoing interface IPropertyNotifySink so that a client can determine when
picture properties change. Accordingly, the picture object also supports IConnectionPointContainer and one
connection point for IPropertyNotifySink.
The picture object also supports IPersistStream such that it can save and load itself from an instance of IStream.
An object that uses a picture object internally would normally save and load the picture as part of the object's own
persistence handling. The OleLoadPicture function simplifies the creation of a picture object based on stream
contents.
Related topics
C
o
n
t
r
o
l
P
r
o
p
e
r
t
i
e
s
Control Methods
1/7/2020 • 2 minutes to read • Edit Online
There are three standard methods that controls can support: Refresh, DoClick, and AboutBox. These standard
methods have negative DISPID values, indicating their standard status.
Related topics
C
o
n
t
r
o
l
P
r
o
p
e
r
t
i
e
s
Control Events
1/7/2020 • 2 minutes to read • Edit Online
In addition to providing properties and methods, a control also provides outgoing interfaces to notify its client of
events. The client must support handling of these events. See Events in COM and Connectable Objects for more
information on how connectable objects work.
A control can support different outgoing interfaces for different purposes. All outgoing interfaces are marked as
source interfaces in the control's type information, but only one is marked default to indicate that it is the primary
outgoing interface.
A container can support one or more of the outgoing interfaces defined by a control. The control should be
prepared to deal with containers that only provide support for some of their outgoing interfaces.
Controls support four kinds of events:
Request events. A control requests permission from its client to do something by calling a method in the
outgoing interface, thus triggering a request event. The client signals the control through a boolean, out-
parameter in the method that the control called. The client can thus prevent the control from performing the
action.
Before events. A control notifies its client hat it is going to do something by calling a method in the outgoing
interface, thus triggering a before event. The client does not have the opportunity to prevent the action, but it
can take any necessary steps given the action that is about to occur.
After events. A control notifies its client that it has just done something by calling a method in the outgoing
interface, thus triggering an after event. Again, the client cannot cancel this action, but it can take necessary
steps given the action that has occurred.
Do events. A control triggers a do event to allow its client to override the control's action and provide some
alternative or supplementary actions. Usually, the method that a control calls for a do event has a number of
parameters for negotiating with the client about the actions that will occur.
The following dispids are defined for standard events that controls can support: Click, DblClick, KeyDown,
KeyPress, KeyUp, MouseMove, MouseUp, and Error. All of these standard events have negative DISPID values,
indicating their standard status.
The IOleControl::FreezeEvents method, when called with TRUE, tells a control whether the container will bother
handling events from the control until FreezeEvents is again called with FALSE. During this time control cannot
depend on the container actually handling any events. If an event must be handled, the control should queue the
event in order to fire it when FreezeEvents is called with FALSE.
Related topics
A
c
t
i
v
e
X
C
o
n
t
r
o
l
s
Visual Representation
1/7/2020 • 2 minutes to read • Edit Online
A control supports positioning and displaying itself within its container through compound document technology
and OLE drag and drop technology that involves both the control and its container. The control must be able to
draw itself while the container manages the position of the control and its size.
Controls add to the basic functions provided by OLE documents. A control calls its client's
IOleClientSite::RequestNewObjectLayout method to tell its container that it wants to change its size. The client
calls the control's IOleObject::GetExtent to get the new size and calls IOleInPlaceObject::SetObjectRects to
set the control to its new size.
Controls that support only IPersistStream or IPersistStreamInit do not support caching through IOleCache2
because the cache requires support for IPersistStorage. However, these controls should provide a way for the
client to render the control through IDataObject::GetData so the client can optionally create and manage its own
cache of the presentation data for the control.
Controls use the HIMETRIC type for its coordinates. However, different containers can use different coordinate
systems. The container wants to receive coordinates in its own system, but the control does not necessarily know
what coordinates its container is using. To communicate successfully, the control needs a way to convert values to
its container's coordinates. The container provides a site object with the IOleControlSite::TransformCoords
method. The control calls this method on its container's client site first to convert its coordinates into the
appropriate coordinates for the container. Then, it can pass the converted coordinates to the container.
Controls can call IOleControlSite::LockInPlaceActive in the container's site object to prevent the container from
attempting to demote the control out of the in-place active state. Demoting the control in this way causes the
control to be deactivated and its window destroyed, so if the control must maintain its window for a known
duration it can call LockInPlaceActive to guarantee its state.
Related topics
A
c
t
i
v
e
X
C
o
n
t
r
o
l
s
Keyboard Handling for Controls
1/7/2020 • 2 minutes to read • Edit Online
A control responds to keyboard accelerators so the end-user can initiate actions performed by the control. The
container manages keyboard activity for all its embedded controls. With compound documents, keyboard
accelerators apply only to the currently active object. With controls, a mechanism has been added so that a control
can respond to its keyboard mnemonics even if it is not currently UI-active.
The IOleControl::GetControlInfo and IOleControl::OnMnemonic methods and the
IOleControlSite::OnControlInfoChanged method handle a control's keyboard mnemonics. A CONTROLINFO
structure describes a control's mnemonic accelerators, and the flags passed back with it through the
GetControlInfo method describe the controls behavior with the Enter and Esc keys. When a control changes its
mnemonics, it calls OnControlInfoChanged so the container can reload the structure if necessary.
When a control is UI active, it is also the control with the focus. As controls are activated and deactivated between
the in-place active and the UI active states, the control calls IOleControlSite::OnFocus to tell the container of
such changes.
In addition, when a control is UI active, it will have first chance to process any keystrokes. To give a container the
opportunity to process the keystroke before the control, the control calls IOleControlSite::TranslateAccelerator.
If the container does not handle the keystroke, the control then processes it.
Related topics
A
c
t
i
v
e
X
C
o
n
t
r
o
l
s
Persistence
1/7/2020 • 2 minutes to read • Edit Online
A control implements one or more of several persistence interfaces to support persistence of its state. For example,
the IPersistStreamInit interface supports stream-based persistence of the control's state. IPersistStreamInit is a
replacement for IPersistStream and adds an initialization method, InitNew. The other methods are the same in
both interfaces. IPersistStreamInit is not derived from IPersistStream; an object supports only one of the two
interfaces based on whether it requires the ability to initialize new instances of itself.
Other persistence interfaces that a control can offer include: IPersistStorage, IPersistMemory,
IPersistPropertyBag, IPersistMoniker. The control implementer must decide what kinds of persistence are most
important and implement the appropriate persistence interfaces. The control implementer also decides what to
save. For example, a control can save the current values of its properties or its location and size within its container.
The client decides which interface it prefers to use.
Before loading a control from its persistent state, a client can check the OLEMISC_SETCLIENTSITEFIRST flag to
determine if the control supports getting its client site and ambient properties before loading its persistent state.
This optimization can save time when instantiating a control since the control is then free to ignore its persistent
values rather than loading them only to have them overridden by ambient properties supplied by the client.
A control can also support saving and restoring its state in an OLE property set, a set of identifiers and values in a
specified format. This feature can be useful with containers such as Visual Basic, which saves its programs in a
textual form. A control that wants to support this feature implements IDataObject::GetData and
IDataObject::SetData to pass its property values to and from the container, respectively. It is the container's job
to convert this information to text and save it. The identifiers used by the control correspond to the control's
property names and the values. See the OLE CDK for the definition of this property set.
Related topics
A
c
t
i
v
e
X
C
o
n
t
r
o
l
s
Registration and Licensing
1/7/2020 • 2 minutes to read • Edit Online
A control is usually provided as an in-process server (.DLL ), although it can also be a local or remote server (.EXE ).
A control typically supports self-registration and creates a set of registry entries when it is instantiated. A control
can also be licensed to help prevent unauthorized use. See The Component Object Model for more information on
self registration and licensing.
For more information, see ActiveX Controls Registry Information.
Related topics
A
c
t
i
v
e
X
C
o
n
t
r
o
l
s
A
c
t
i
v
e
X
C
o
n
t
r
o
l
s
R
e
g
i
s
t
r
y
I
n
f
o
r
m
a
t
i
o
n
ActiveX Controls Registry Information
1/7/2020 • 2 minutes to read • Edit Online
There are a number of registry entries and flags that are used. Additionally, controls can support component
categories to classify the features they provide.
Registry keys related to controls are marked with an asterisk in the following tree:
HKEY_CLASSES_ROOT
CLSID
{control_CLSID}
ProgID = <identifier>
InprocServer32 = <filename>.dll
*DefaultIcon = <filename>.<ext>,resourceID
*ToolboxBitmap32 = <filename>.<ext>,resourceID
*Control
verb
*n = &Properties...
*MiscStatus = 0
TypeLib = {object_typelibID}
*Version = version_number
The DefaultIcon entry is used to identify an icon to be displayed when the control is minimized to an icon. The
ExtractIcon function is used to get the icon from the .DLL or .EXE file specified.
The ToolboxBitmap32 entry identifies the module name and resource identifier for a 16*15 bitmap to use for the
face of a toolbar or toolbox button. The standard Windows icon size is too large to be used for this purpose. This
entry specifically supports control containers that have a design mode in which one selects controls and places
them on a form being designed. For example, in Visual Basic, the control's icon is displayed in the Visual Basic
toolbox during design mode.
The Control entry marks an object as a control. This entry is often used by containers to fill in dialog boxes. The
container uses this sub-key to determine whether to include an object in a dialog box that displays controls.
The Insertable sub-key can also be used with controls, depending on whether the object can act only as an in-
place embedded object with no special control features. Objects marked with Insertable appear in the Insert
Object dialog box of their container. The Insertable entry generally means that the control has been tested with
non-control containers.
Both the Insertable and the Control sub-keys are optional. A control can omit the Insertable sub-key if it not
designed to work with older containers that do not understand controls. A control can omit the Control key if it is
only designed to work with a specific container and thus does not wish to be inserted in other containers.
Controls should have a Properties verb, OLEIVERB_PROPERTIES, along with any other verbs they support. The
Properties verb, as well as the standard verb OLEIVERB_PRIMARY, instructs the control to display its property
sheet. The Properties verb is displayed as the Properties item on the container's menu when the control is active.
This way, the control can display its own property page allowing some useful functionality to the end user, even if
the container does not handle controls.
A control defines the MiscStatus key to describe itself to potential containers. The bits take on the values from
OLEMISC, and controls add several values to this enumeration. See the OLEMISC enumeration values for more
information. The client can obtain this information by calling IOleObject::GetMiscStatus without having to
instantiate the control first.
Finally, Version describes the version of the control which should match the version of the type library associated
with this control.
Also in the type information for a control, the attribute control marks a coclass entry as describing a control.
Property Pages and Property Sheets
1/7/2020 • 2 minutes to read • Edit Online
OLE property pages enable an object to display its properties in a tabbed dialog box known as a property sheet.
An end user can then view and change the object's properties. An object can display its property pages
independent of its client, or the client can manage the display of property pages from a number of contained
objects in a single property sheet. Property pages also provide a means for notifying a client of changes in an
object's properties.
Any object that wants to provide a user interface for its changing properties can use this technology.
For more information, see the following topics:
Property Sheets and Property Pages
Data Binding through IPropertyNotifySink
Property Sheets and Property Pages
1/7/2020 • 5 minutes to read • Edit Online
An object's properties are exposed to clients the same as methods through either COM interfaces or the object's
IDispatch implementation, allowing properties to be changed by programs calling these methods. The OLE
technology of property pages provides the means to build a user interface for an object's properties according to
Windows user interface standards. Thus, the properties are exposed to end users. An object's property sheet is a
tabbed-dialog where each tab corresponds to a specific property page. The OLE model for working with property
pages consists of these features:
Each property page is managed by an in-process object that implements either IPropertyPage or
IPropertyPage2. Each page is identified with its own unique CLSID.
An object specifies its support for property pages by implementing ISpecifyPropertyPages. Through this
interface the caller can obtain a list of CLSIDs identifying the specific property pages that the object supports. If
the object specifies a property page CLSID, the object must be able to receive property changes from the
property page.
Any piece of code (client or object) that wants to display an object's property sheet passes the object's
IUnknown pointer (or an array if multiple objects are to be affected) along with an array of page CLSIDs to
OleCreatePropertyFrame or OleCreatePropertyFrameIndirect, which creates the tabbed-dialog box.
The property frame dialog instantiates a single instance of each property page, using CoCreateInstance on
each CLSID. The property frame obtains at least an IPropertyPage pointer for each page. In addition, the
frame creates a property page site object in itself for each page. Each site implements IPropertyPageSite and
this pointer is passed to each page. The page then communicates with the site through this interface pointer.
Each page is also made aware of the object or objects for which it has been invoked; that is, the property frame
passes the IUnknownpointers of the objects to each page. When instructed to apply changes to the objects,
each page queries for the appropriate interface pointer and passes new property values to the objects in
whatever way is desired. There are no stipulations on how such communication has to happen.
An object can also support per property browsing through the IPerPropertyBrowsing interface permitting the
object to specify which property should receive initial focus when the property page is displayed and to specify
strings and values that can be displayed by the client in its own user interface.
These features are illustrated in the following diagram:
The ISpecifyPropertyPages::GetPages method returns a counted array of UUID (GUID ) values each of which
describe the CLSID of a property page that the object would like displayed. Whoever invokes the property sheet
with OleCreatePropertyFrame or OleCreatePropertyFrameIndirect passes this array to the function. Note
that if the caller wishes to display property pages for multiple objects, it must only pass the intersection of the
CLSID lists of all the objects to these functions. In other words, the caller must only invoke property pages that are
common to all objects.
In addition, the caller passes the IUnknown pointers to the affected objects to the API functions as well. Both API
functions create a property frame dialog and instantiate a page site with IPropertyPageSite for each page it will
load. Through this interface a property page can:
Retrieve the current language used in the property sheet through GetLocaleID.
Ask the frame to process keystrokes through TranslateAccelerator.
Notify the frame of changes in the page through OnStatusChange.
Obtain an interface pointer for the frame itself through GetPageContainer, although there are no interfaces
defined for the frame at this time for this function always returns E_NOTIMPL.
The property frame instantiates each property page object and obtain each page's IPropertyPage interface.
Through this interface the frame informs the page of its page site (SetPageSite), retrieves page dimensions and
strings (GetPageInfo), passes the interface pointers to the affected objects (SetObjects), tells the page when to
create and destroy its controls (Activate and Deactivate), instructs the page to show or reposition itself (Show
and Move), instructs the page to apply its current values to the affected objects (Apply), checks on the page's dirty
status (IsPageDirty), invokes help (Help), and passes keystrokes to the page (TranslateAccelerator).
An object can also support per-property browsing, which provides:
1. A way (through IPerPropertyBrowsing and IPropertyPage2) to specify which property on which property
page should be given the initial focus when a property sheet is first displayed
2. A way (through IPerPropertyBrowsing) for the object to specify predefined values and corresponding
descriptive strings that could be displayed in a client's own user interface for properties.
An object can choose to support (2) without supporting (1), such as when the object has no property sheet.
The IPropertyPage2 and IPerPropertyBrowsing interfaces are defined as follows:
To specify its support for such capabilities, the object implements IPerPropertyBrowsing. Through this interface,
the caller can request the information necessary to achieve the browsing, such as predefined strings
(GetPredefinedStrings) and values (GetPredefinedValue) as well as a display string for a given property
(GetDisplayString).
In addition, the client can obtain the CLSID of the property page that allows the user to edit a given property
identified with a DISPID (MapPropertyToPage). The client then instructs the property frame to activate that page
initially by passing the CLSID and the DISPID to OleCreatePropertyFrameIndirect. The frame activates that
page first and passes the DISPID to the page through IPropertyPage2::EditProperty. The page then sets the
focus to that property's editing field. In this way, a client can jump from a property name in its own user interface
to the property page that can manipulate that property.
Related topics
P
r
o
p
e
r
t
y
P
a
g
e
s
a
n
d
P
r
o
p
e
r
t
y
S
h
e
e
t
s
Data Binding through IPropertyNotifySink
1/7/2020 • 2 minutes to read • Edit Online
Objects that support properties, for example, through OLE Automation and the IDispatch interface, may want to
allow clients to be notified when certain properties change value. Such a property is called a bindable property
because the notifications allow a client to synchronize its own display of the object's current property values. In
addition, the same objects may wish to allow a client to control when certain properties are allowed to change.
Such properties are called request edit properties.
The IPropertyNotifySink is a standard notification interface that supports bindable and request-edit properties.
IPropertyNotifySink is supported from an object with properties as an outgoing interface. That is, the interface
itself is implemented by a client's sink object, and the client connects the sink to the supporting object through the
connection point mechanism described earlier. The IPropertyNotifySinkis defined as follows:
When an object wishes to notify its connected sinks that a bindable property identified with a given DISPID has
changed, it calls OnChanged. If an object changes multiple properties at once, it can pass DISPID_UNKNOWN to
OnChanged in which case a client refreshes its cache of all property values of interest.
When a request edit property is about to change, an object can ask the client whether it will allow that change to
occur. The object calls OnRequestEdit passing the DISPID of the property in question (or DISPID_UNKNOWN
to identify all properties). The client's sink returns S_OK to indicate that the change is allowed, or S_FALSE (or an
error) to indicate that change is not allowed. When an object calls OnRequestEdit, it is required to obey the
client's wishes by following the exact semantics of S_OK and S_FALSE return values.
Note that OnRequestEdit cannot be used for data validation because at the time of the call, the new value of the
property is not yet available. The notification can only be used to control a read-only state for a property.
Objects control which properties are bindable and request edit and mark such properties in the object's type
information. In the type information, the attribute bindable marks a property as supporting OnChanged. The
attribute requestedit marks a property as supporting OnRequestEdit.
One property can support both behaviors in which case OnRequestEdit is called first, and only if change is
allowed is OnChanged called.
The one exception to the behavior of such properties is that no notifications are sent as a result of an object's
initialization or loading procedures. At such times, it is assumed that all properties change and that all must be
allowed to change. Notifications to this interface are therefore only meaningful in the context of a fully
initialized/loaded object.
Two other attributes can be applied to properties in an object's type information. The defaultbind attribute marks a
bindable property as being the one that best represents the state of the object as a whole. The displaybind attribute
marks a bindable property as suitable for display in a client's own user interface.
Related topics
P
r
o
p
e
r
t
y
P
a
g
e
s
a
n
d
P
r
o
p
e
r
t
y
S
h
e
e
t
s
ActiveX Control and Control Container Guidelines
1/7/2020 • 2 minutes to read • Edit Online
The following topics provide guidelines for implementing ActiveX controls and containers that will interoperate
well with other controls and containers. This section defines the minimum set of interfaces, methods, and features
that are required of ActiveX controls and containers to accomplish seamless and useful interoperability.
Overview of Control and Control Container Guidelines
Controls
Containers
Component Categories
General Guidelines
Event Coordinate Translation
Standard DISPIDS
Databinding
Related topics
A
c
t
i
v
e
X
C
o
n
t
r
o
l
s
Overview of Control and Control Container
Guidelines
1/29/2020 • 3 minutes to read • Edit Online
An ActiveX control is essentially a simple OLE object that supports the IUnknown interface. It will usually support
more interfaces in order to offer functionality, but all additional interfaces may be viewed as optional and as such, a
control container should not rely on any additional interfaces being supported. By not specifying additional
interfaces that a control must support, a control may efficiently target a particular area of functionality without
having to support particular interfaces to qualify as a control. As always with OLE, whether in a control or a control
container, it should never be assumed that an interface is available and standard return-checking conventions
should always be followed. It is important for a control or control container to degrade gracefully and offer
alternative functionality if an interface required is not available.
An ActiveX control container must be able to host a minimal ActiveX control; it will also support a number of
additional interfaces as specified in Containers. There are a number of interfaces and methods that a container may
optionally support, which are grouped into functional areas known as component categories. A container may
support any combination of component categories, for example, a component category exists for databinding and
a container may or may not support the databinding functionality, depending on the market needs of the container.
If a control needs databinding support from a container to function, then it will enter this requirement in the
registry. This allows a control container to only offer for insertion those controls that it knows it can successfully
host. It is important to note that component categories are specified as part of OLE and are not specific to ActiveX
controls, the controls architecture uses component categories to identify areas of functionality that an OLE
component may support. Component categories are not cumulative or exclusive, so a control container can
support one category without necessarily supporting another.
It is important for controls that require optional features, or features specific to a certain container to be clearly
packaged and marketed with those requirements. Similarly containers that offer certain features or component
categories must be marketed and packaged as offering those levels of support when hosting ActiveX controls. It is
recommended that controls target and test with as many containers as possible and degrade gracefully to offer
less or alternative functionality if interfaces or methods are not available. In a situation where a control cannot
perform its designated job function without the support of a component category, that category should be entered
as a requirement in the registry in order to prevent the control being inserted in an inappropriate container.
These guidelines define those interfaces and methods that a control may expect a control container to support,
although as always a control should check the return values when using QueryInterface or other methods to
obtain pointers to these interfaces. A container should not expect a control to support anything more than the
IUnknown interface, and these guidelines identify what interfaces a control may support and what the presence of
a particular interface means.
Related topics
A
c
t
i
v
e
X
C
o
n
t
r
o
l
a
n
d
C
o
n
t
r
o
l
C
o
n
t
a
i
n
e
r
G
u
i
d
e
l
i
n
e
s
Controls
1/29/2020 • 2 minutes to read • Edit Online
An ActiveX control is really just another term for OLE object or more specifically, COM object. In other words, a
control, at the very least, is some COM object that supports the IUnknown interface and is also self-registering.
Through IUnknown::QueryInterface a container can manage the lifetime of the control as well as dynamically
discover the full extent of a control's functionality based on the available interfaces. This allows a control to
implement as little functionality as it needs to, instead of supporting a large number of interfaces that actually
don't do anything. In short, this minimal requirement for nothing more than IUnknown allows any control to be
as lightweight as it can.
In short, other than IUnknown and self-registration, there are no other requirements for a control. There are,
however, conventions that should be followed about what the support of an interface means in terms of
functionality provided to the container by the control. This section then describes what it means for a control to
actually support an interface, as well as methods, properties, and events that a control should provide as a
baseline if it has occasion to support methods, properties, and events.
For more information, see the following topics:
Self Registration for Controls
What Support for an Interface Means
Persistence Interfaces
Optional Methods in Control Interfaces
Class Factory Options
Exposing Properties through IDispatch
Exposing Methods through IDispatch
Events in Controls
Property Pages
Ambient Properties for Controls
Using the Container's Functionality
Related topics
A
c
t
i
v
e
X
C
o
n
t
r
o
l
a
n
d
C
o
n
t
r
o
l
C
o
n
t
a
i
n
e
r
G
u
i
d
e
l
i
n
e
s
Self Registration for Controls
1/7/2020 • 2 minutes to read • Edit Online
Related topics
C
o
n
t
r
o
l
s
What Support for an Interface Means
1/7/2020 • 5 minutes to read • Edit Online
Besides the IUnknown interface, an ActiveX Control or COM Object for that matter expresses whatever optional
functionality it supports through additional interfaces. This is to say that no other interfaces are required above
IUnknown. To that end, the following table lists the interfaces that an ActiveX Control might support, and what it
means to support that interface.
IOleObject If the control requires communication with its client site for
anything other than events (see
IConnectionPointContainer), then IOleObject is a necessity.
When implementing this interface, the control must also
support the semantics of the following methods:
SetHostNames, Close, EnumVerbs, Update, IsUpToDate,
GetUserClassID, GetUserType, GetMiscStatus, and the
Advise, Unadvise, and EnumAdvise methods that work in
conjunction with a container's IAdviseSink implementation. A
control implementing IOleObject must be able to handle
IAdviseSink if the container provides one; a container may
not, in which case a control ensures, of course, that it does not
attempt to call a non-existent sink.
IOleControl Expresses the control's ability and desire to deal with (a)
mnemonics (GetControlInfo, OnMnemonic methods), (b)
ambient properties (OnAmbientPropertyChange), and/or (c)
events that the control requires the container to handle
(FreezeEvents). Note that mnemonics are different than
accelerators that are handled through
IOleInPlaceActiveObject: mnemonics have associated UI
and are active even when the control is not UI active. A
control's support for mnemonics means that the control also
knows how to use the container's
IOleControlSite::OnControlInfoChanged method. Because
this requires the control to know the container's site, support
for mnemonics also means support for IOleObject. In
addition, knowledge of mnemonics requires in-place support
and thus IOleInPlaceObject.
If a control uses any container-ambient properties, then it
must also implement this interface to receive change
notifications, as following the semantics of changes is required.
Because ambient properties are only available through the
container site's IDispatch, ambient property support means
that the control supports IOleObject (to get the site) as well
as being able to generate IDispatch::Invoke calls.
The FreezeEvents method is necessary for controls that must
know when a container is not going to handle an event this is
the only way for control to know this condition. If
FreezeEvents is only necessary in isolation, such that other
IOleControl methods are not implemented, then
IOleControl can stand alone without IOleObject or
IOleInPlaceObject.
IDataObject Indicates that the control can supply at least (a) graphical
renderings of the control (CF_METAFILEPICT is the minimum if
the control has any visuals at all) and/or (b) property sets, if
the control has any properties to provide. The methods
GetData, QueryGetData, EnumFormatEtc, DAdvise,
DUnadvise, and EnumDAdvise are required. Support for
graphical formats other than CF_METAFILEPICT is optional.
IViewObject2 Indicates that the control has some interesting visuals when it
is not in-place active. If implemented, a control must support
the methods Draw, GetAdvise, SetAdvise, and GetExtent.
IDispatch Indicates that the control has either (a) custom methods, or
(b) custom properties that are both available via late-binding
through IDispatch::Invoke. This also requires that the control
provides type information through other IDispatch methods.
A control may support multiple IDispatch implementations
where only one is associated with IID_IDispatch the others
must have their own unique dispinterface identifiers.
A control is encouraged to supply dual interfaces for custom
method and property access, but this is optional if methods
and properties exist.
INTERFACE COMMENTS/WHAT IT MEANS TO SUPPORT THE INTERFACE
IProvideClassInfo Indicates that the object can provide its own coclass type
IProvideClassInfo2 information directly through
IProvideClassInfo::GetClassInfo. If the control supports the
later variation IProvideClassInfo2, then it also indicates its
ability to provide its primary source IID through
IProvideClassInfo2::GetGUID. All methods of this interface
must be implemented.
ISpecifyPropertyPages Indicates that the control has property pages that it can
display such that a container can coordinate this control's
property pages with other control's pages when property
pages are to be shown for a multi-control selection. All
methods of this interface must be implemented when support
exists.
IPerPropertyBrowsing Indicates the control's ability to (a) provide a display string for
a property, (b) provide predefined strings and values for its
properties and/or (c) map a property dispID to a specific
property page. Support for this interface means that support
for properties through IDispatch as above is provided. If (c) is
supported, then it also means that the object's property
pages mapped through
IPerPropertyBrowsing::MapPropertyToPage themselves
implement IPropertyPage2 as opposed to the basic
IPropertyPage interface.
IExternalConnection Indicates that the control supports external links to itself; that
is, the control is not marked with OLEMISC_CANTLINKINSIDE
and supports IOleObject::SetMoniker and
IOleObject::GetMoniker. A container will never query for
this interface itself nor call it directly as calls are generated
from inside OLE's remoting layer.
Related topics
C
o
n
t
r
o
l
s
Persistence Interfaces
1/7/2020 • 2 minutes to read • Edit Online
Objects that have a persistent state of any kind must implement at least one IPersist* interface, and preferably
multiple interfaces, in order to provide the container with the most flexible choice of how it wishes to save a
control's state.
If a control has any persistent state whatsoever, it must, as a minimum, implement either IPersistStream or
IPersistStreamInit (the two are mutually exclusive and shouldn't be implemented together for the most part). The
latter is used when a control wishes to know when it is created new as opposed to reloaded from an existing
persistent state (IPersistStream does not have the created new capability). The existence of either interface
indicates that the control can save and load its persistent state into a stream, that is, an instance of IStream.
Beyond these two stream-based interfaces, the IPersist* interfaces listed in the following table can be optionally
provided in order to support persistence to locations other than an expandable IStream.
A set of component categories is identified to cover the support for persistency interfaces see Component
Categories.
INTERFACE USAGE
IPersistMemory The object can save and load its state into a fixed-length
sequential byte array (in memory).
IPersistStorage The object can save and load its state into an IStorage
instance. Controls that wish to be marked Insertable as other
compound document objects (for insertion into non-control
aware containers) must support this interface.
IPersistPropertyBag The object can save and load its state as individual properties
written to IPropertyBag which the container implements. This
is used for Save As Text functionality in some containers.
IPersistMoniker The object can save and load its state to a location named by
a moniker. The control calls IMoniker::BindToStorage to
retrieve the storage interface it requires, such as IStorage,
IStream, ILockBytes, IDataObject, etc.
While support for IPersistPropertyBag is optional, it is strongly recommended as an optimization for containers
with Save As Text features, such as Visual Basic.
With the exception of IPersistStream::GetSizeMax, IPersistStreamInit::GetSizeMax, and
IPersistMemory::GetSizeMax, all methods of each interface must be fully implemented.
Related topics
C
o
n
t
r
o
l
s
Optional Methods in Control Interfaces
1/7/2020 • 2 minutes to read • Edit Online
Implementing an interface doesn't necessarily mean implementing all methods of that interface to do anything
more than return E_NOTIMPL or S_OK as appropriate. The following table identifies the methods of the interfaces
listed in the What Support for an Interface Means topic that a control may implement in this manner. Any method
not listed here must be fully implemented if the interface is supported.
IOLECONTROL COMMENTS
IOleObject
InitFromData Optional
GetClipboardData Optional
SetColorScheme Optional
IOleInPlaceObject
ContextSensitiveHelp Optional
ReactivateAndUndo Optional
IOleInPlaceActiveObject
ContextSensitiveHelp Optional
IViewObject2
Freeze Optional
IOLECONTROL COMMENTS
Unfreeze Optional
GetColorSet Optional
1. A control with property pages must support IOleObject::DoVerb for the OLEIVERB_PROPERTIES and
OLEIVERB_PRIMARY verbs. A control that can be active must support DoVerb for the
OLEIVERB_INPLACEACTIVATE verb. A control that can be UI active must also support DoVerb for the
OLEIVERB_UIACTIVATE verb.
2. If a control supports IPersistStream or IPersistStreamInit and can return an accurate value, then it should do
so.
Related topics
C
o
n
t
r
o
l
s
Class Factory Options
1/7/2020 • 2 minutes to read • Edit Online
An ActiveX Control, by virtue of being a COM object, must have associated server code that supports control
creation through IClassFactory as a minimum.
It is optional, not required, that this class object also support IClassFactory2 for licensing management. Only
those vendors that are concerned about licensing need to support COM's licensing mechanism. In other words,
because IClassFactory2 is the only way to achieve COM -level licensing, this interface is required on the class
object for those controls that want to be licensed.
Related topics
C
o
n
t
r
o
l
s
Exposing Properties through IDispatch
1/7/2020 • 2 minutes to read • Edit Online
Although most controls do have properties, controls are not required to expose any properties and thus the
control does not require IDispatch. If the control does have properties, there are no requirements for which
properties a control must expose.
Related topics
C
o
n
t
r
o
l
s
Exposing Methods through IDispatch
1/7/2020 • 2 minutes to read • Edit Online
Although most controls do expose and support several methods, controls are not required to expose or support
any methods and thus the control does not require IDispatch. If the control does have any methods, there are no
requirements for which methods a control must expose.
Related topics
C
o
n
t
r
o
l
s
Events in Controls
1/7/2020 • 2 minutes to read • Edit Online
Although most controls do expose and fire several events, controls are not required to expose or fire any events
and thus the control does not require IConnectionPointContainer. If the control does have any events, there are
no requirements for which events a control must expose.
Related topics
C
o
n
t
r
o
l
s
Property Pages
1/7/2020 • 2 minutes to read • Edit Online
Support for property pages and per-property browsing is strongly recommended, but not required. If a control
does implement property pages, then those pages should conform to one of the standard sizes: 250x62 or
250x110 dialog units (DLUs).
Related topics
C
o
n
t
r
o
l
s
Ambient Properties for Controls
1/7/2020 • 2 minutes to read • Edit Online
If a control supports any ambient properties at all, it must at least respect the values of the following ambient
properties under the conditions stated in the following table using the standard dispids.
Related topics
C
o
n
t
r
o
l
s
Using the Container's Functionality
1/7/2020 • 2 minutes to read • Edit Online
The previous sections have described some of the necessary caller-side support that an ActiveX control must have
in order to access certain features of its container. The following table describes a control's usage of container-side
interfaces and when such usage would occur.
Other event sink interfaces Varies A control that has outgoing interfaces
other than IPropertyNotifySink will be
handed other interface pointers of the
correct IID to the control's
IConnectionPoint::Advise
implementations (which are usually
found in sub-objects of the control). A
control always knows how to call its
own event interfaces because the
control defines those interfaces.
Related topics
C
o
n
t
r
o
l
s
Containers
1/7/2020 • 2 minutes to read • Edit Online
An ActiveX Control container is an OLE container that supports the following additional features:
Embedded objects from in-process servers
In-place activation
OLEMISC_ACTIVATEWHENVISIBLE
Event handling
ActiveX Control Containers must provide support for all of these features.
For more information, see the following topics:
Required Interfaces
Optional Methods
Miscellaneous Status Bits Support
Keyboard Handling in Controls
Storage Interfaces
Ambient Properties
Extended Properties, Events and Methods
Message Reflection
Automatic Clipping
Degrading Gracefully in the Absence of an Interface
Related topics
A
c
t
i
v
e
X
C
o
n
t
r
o
l
a
n
d
C
o
n
t
r
o
l
C
o
n
t
a
i
n
e
r
G
u
i
d
e
l
i
n
e
s
Required Interfaces
1/7/2020 • 2 minutes to read • Edit Online
The table below lists the ActiveX Control Container interfaces, and denotes which interfaces are optional, and
which are mandatory and must be implemented by control containers.
IOleClientSite Yes
IOleInPlaceSite Yes
IOleControlSite Yes
IOleInPlaceFrame Yes
IDispatch for ambient properties Yes See note 2 and Ambient Properties for
Controls
1. IOleContainer is implemented on the document or form object (or appropriate analog) that holds the
container sites. Controls use IOleContainer to navigate to other controls in the same document or form.
2. Support for dual interfaces is not mandatory, but is strongly recommended. Writing ActiveX control containers
to take advantage of dual interfaces will afford better performance with controls that offer dual interface
support.
ActiveX control containers must support OLE Automation exceptions. If a control container supports dual
interfaces, then it must capture automation exceptions through IErrorInfo.
Related topics
C
o
n
t
a
i
n
e
r
s
Optional Methods
1/7/2020 • 2 minutes to read • Edit Online
An OLE component can implement an interface without implementing all the semantics of every method in the
interface, instead returning E_NOTIMPL or S_OK as appropriate. The following table describes those methods that
an ActiveX control container is not required to implement (i.e. the control container can return E_NOTIMPL ).
The table below describes optional methods; note that the method must still exist, but can simply return
E_NOTIMPL instead of implementing real semantics. Note that any method from a mandatory interface that is not
listed below must be considered mandatory and may not return E_NOTIMPL.
IOleClientSite
METHOD COMMENTS
IOleInPlaceSite
METHOD COMMENTS
ContextSensitiveHelp Optional
IOleControlSite
METHOD COMMENTS
LockInPlaceActive Optional
GetTypeInfoCount The control knows its own type information, so it has no need
to call this.
GetTypeInfo The control knows its own type information, so it has no need
to call this.
GetIDsOfNames The control knows its own type information, so it has no need
to call this.
IOleInPlaceFrame
METHOD COMMENTS
ContextSensitiveHelp
EnableModeless Optional
TranslateAccelerator Optional
IOleContainer
METHOD COMMENTS
Related topics
C
o
n
t
a
i
n
e
r
s
Miscellaneous Status Bits Support
1/7/2020 • 2 minutes to read • Edit Online
ActiveX Control Containers must recognize and support the following OLEMISC_ status bits.
ACTIVATEWHENVISIBLE Yes
ALWAYSRUN Yes
NOUIACTIVATE Yes
ALIGNABLE No
IMEMODE No
Related topics
C
o
n
t
a
i
n
e
r
s
Keyboard Handling in Controls
1/7/2020 • 2 minutes to read • Edit Online
Keyboard handling support for the following functionality is strongly recommended, although it is recognized that
it is not applicable to all containers.
Support for OLEMISC_ACTSLIKELABEL and OLEMISC_ACTSLIKEBUTTON status bits.
Implementing the DisplayAsDefault ambient property (if it exists, it can return FALSE ).
Implementing tab handling, including tab order.
Some containers will use ActiveX controls in traditional compound document scenarios. For example, a
spreadsheet may allow a user to embed an ActiveX control into a worksheet. In such scenarios, the container
would do keyboard handling differently, because the keyboard interface should remain consistent with the user's
expectations of a spreadsheet. Documentation for such products should inform users of differences in control
handling in these different scenarios. Other containers should endeavor to honor the above functionality correctly,
including Mnemonic handling.
Related topics
C
o
n
t
a
i
n
e
r
s
Storage Interfaces
1/7/2020 • 2 minutes to read • Edit Online
Control containers must be able to support controls that implement IPersistStorage, IPersistStream, or
IPersistStreamInit. Optionally, a container can support any other persistence interfaces such as IPersistMemory,
IPersistPropertyBag, and IPersistMoniker for those controls that provide support.
Once an ActiveX control container has chosen and initialized a storage interface to use (IPersistStorage,
IPersistStream, IPersistStreamInit, etc), that storage interface will remain the primary storage interface for the
lifetime of the control, i.e. the control will remain in possession of the storage. This does not preclude the container
from saving to other storage interfaces.
ActiveX control containers do not need to support a save as text mechanism, thus using IPersistPropertyBag and
the associated container-side interface IPropertyBag are optional.
Related topics
C
o
n
t
a
i
n
e
r
s
Ambient Properties
1/7/2020 • 2 minutes to read • Edit Online
At a minimum, ActiveX Control containers must support the following ambient properties using the standard
dispids.
LocaleID -705
Related topics
C
o
n
t
a
i
n
e
r
s
Extended Properties, Events and Methods
1/7/2020 • 2 minutes to read • Edit Online
ActiveX control containers are not required to support extended controls. However, if the control container does
support extended properties, then it must support the following minimal set:
Visible
Parent
Default
Cancel
Currently, extended properties, events, and methods do not have standard dispids.
Related topics
C
o
n
t
a
i
n
e
r
s
Message Reflection
1/7/2020 • 2 minutes to read • Edit Online
It is strongly recommended that an ActiveX control container supports message reflection. This will result in more
efficient operation for subclassed controls. If message reflection is supported, the MessageReflect ambient
property must be supported and have a value of TRUE. If a container does not implement message reflection,
then the OLE CDK creates two windows for every subclassed control, to provide message reflection on behalf on
the control container.
Related topics
C
o
n
t
a
i
n
e
r
s
Automatic Clipping
1/7/2020 • 2 minutes to read • Edit Online
It is strongly recommended that an ActiveX control container supports automatic clipping of its controls. This will
result in more efficient operation for most controls. If automatic clipping is supported, the AutoClip ambient
property must be supported and have a value of TRUE.
Automatic clipping is the ability of a container to ensure that a control's drawn output goes only to the container's
current clipping region. In a container that supports automatic clipping, a control can paint without regard to its
clipping region, because the container will automatically clip any painting that occurs outside the control's area. If a
container does not support automatic clipping, then CDK-generated controls will create an extra parent window if
a non-null clipping region is passed.
Related topics
C
o
n
t
a
i
n
e
r
s
Degrading Gracefully in the Absence of an Interface
1/29/2020 • 5 minutes to read • Edit Online
Because a control may not support any interface other than IUnknown, a container has to degrade gracefully
when it encounters the absence of any particular interface.
One might question the usefulness of a control with nothing more than IUnknown. But consider the advantages
that a control receives from a container's visual programming environment (such as VB ) when the container
recognizes the object as a control:
A button for the object appears in a toolbox.
One can create an object by dragging it from the toolbox onto a form.
One can give the object a name that is recognized in the visual programming environment.
The same name in (3) above can be used immediately in writing any other code for controls on the same form
(or even a different form).
The container can automatically provide code entry points for any events available from that object.
The container provides its own property browsing UI for any available properties.
When an object isn't recognized as a control, then it potentially loses all of these very powerful and beneficial
integration features. For example, in Visual Basic 4.0 it is very difficult to really integrate some random object that
is not a control in the complete sense, but may still have properties and events. Because Visual Basic 4's idea of a
control is very restrictive, the object does not gain any of the integration features above. But even a control with
IUnknown, where the mere lifetime of the control determines the existence of some resource, should be able to
gain the integration capabilities described above.
As current tools require a large set of control interfaces to gain any advantage, controls are generally led to over-
implementation, such that they contain more code than they really need. Controls that could be 7K might end up
being 25K, which is a big performance problem in areas such as the Internet. This has also led to the perception
that one can only implement a control with one tool like the CDK because of the complexity of implementing all
the interfaces, and this has implications when a large DLL like OC30.DLL is required for such a control, increasing
the working set. If not all interfaces are required, then this opens up many developers to writing very small and
light controls with straight OLE or with other tools as well, minimizing the overhead for each control.
This is why this appendix recognizes a control as any object with a CLSID and an IUnknown interface. Even with
nothing more than IUnknown, a container with a programming environment should be able to provide at least
features #3 and ) registry entry, it gains #1 and #2. If the object supplies IConnectionPointContainer (and
IProvideClassInfo generally) for some event set, it gains #5, and if it supports IDispatch for properties and
methods, it gains #6, as well as better code integration in the container.
In short, an object should be able to implement as little as IDispatch and one event set exposed through
IConnectionPointContainer to gain all of those visual features above.
With this in mind, the following table describes what a container might do in the absence of any possible interface.
Note that only those interfaces are listed that the container will directly obtain through QueryInterface. Other
interfaces, like IOleInPlaceActiveObject, are obtained through other means.
IViewObject2 The control has no visuals that it will draw itself, so has no
definite extents to provide. In run-time, the container simply
doesn't attempt to draw anything when this interface is
absent. In design time, the container must at least draw some
kind of default rectangle with a name in it for such a control,
so a user in a visual programming environment can select the
object and check out its properties, methods, and events that
exist. Handling the absence of IViewObject2 is critical for
good visual programming support.
IOleObject The control doesn't need the site whatsoever, nor does it take
part in any embedded object layout negotiation. Any
information (like control extents) that a container might expect
from this interface should be filled in with container-provided
defaults.
IOleInPlaceObject The control doesn't go in-place active (like a label) and thus
never attempts to activate in this manner. Its only activation
may be its property pages.
ISpecifyPropertyPages The control has no property pages, so if the container has any
UI that would invoke them, the container should disable that
UI.
Related topics
C
o
n
t
a
i
n
e
r
s
Component Categories
1/7/2020 • 2 minutes to read • Edit Online
OLE's component categories enable a software component's abilities and requirements to be identified by entries
in the registry. In a scenario where a container may not want to or not be able to support an area of functionality,
such as databinding for example, the container will not want to host controls that require databinding in order to
perform their job function. Component categories allow areas of functionality such as databinding to be
identified, so that the control container can avoid those controls that state it to be a requirement. Component
categories are specified separately as part of OLE and are not specific to the ActiveX control architecture, the
specification for component categories includes APIs for manipulation of the component category registry keys.
For more information, see the following topics:
Component Categories and How they Work
Simple Frame Site Containment
Simple Data Binding
Advanced Data Binding
Visual Basic Private Interfaces
Internet-Aware Objects
Windowless Controls
Categorizing DCOM Proxies and Stubs
Related topics
A
c
t
i
v
e
X
C
o
n
t
r
o
l
a
n
d
C
o
n
t
r
o
l
C
o
n
t
a
i
n
e
r
G
u
i
d
e
l
i
n
e
s
Component Categories and How they Work
1/7/2020 • 3 minutes to read • Edit Online
Component categories identify those areas of functionality that a software component supports and requires, a
registry entry is used for each category or identified area of functionality. Each component category is identified by
a globally unique identifier (GUID ), when a control is installed it registers itself as a control in the system registry
using the component category ID for control, see Self Registration for Controls. Within the controls self
registration it will also register those component categories that it implements and those component categories
that it requires a container to support in order to successfully host the control.
When a control container is offering controls to the user to insert, it only allows the user to select and instantiate
those controls that will be able to function adequately in that environment. For example, if the control container
does not support databinding, then the container will not allow the user to select and instantiate those controls that
have an entry in the registry signifying that they require the databinding component category. A common dialog
for control insertion and APIs to handle the registry entries are available.
Component categories are not cumulative or exclusive, a control can require any mix of component categories to
function. A control that has no required entries for component categories may be expected to be capable of
functioning in any control container and not require any specific functionality of a control container to function.
The following component categories are identified here, where necessary more detailed specifications of the
categories may be available.
ISimpleFrameSite control containment.
Simple Databinding through the IPropertyNotifySink interface.
Advanced Databinding (as supported by the additional databinding interfaces of VB4.0).
Visual Basic private interfaces - IVBFormat, IVBGetControl
Internet aware controls.
Windowless controls.
This is not a definitive list of categories; further categories are likely to be defined in the future as new
requirements are identified. An up-to-date list of component categories is available from Microsoft; this list reflects
those component categories that have been identified by Microsoft and any others that about which vendors have
informed Microsoft.
It is important to remember that controls should attempt to work in as many environments as possible. If it is
possible, the control should degrade its functionality when placed in a container that does not support certain
interfaces. The purpose of component categories is to prevent a situation where the control is placed in an
environment that is unsuitable and the control cannot achieve its desired task. Generally, a control should degrade
gracefully when interfaces are not present, a control may choose to advise the user with a message box that some
functionality is not available or clearly document the functionality required of a control container for optimal
performance.
Note older controls and containers do not make use of component categories and instead rely on the control
keyword being present against the control in the registry. In order to be recognized by older containers controls
may wish to register the control keyword in the registry, control developers should check that the control can
successfully be hosted in such containers before doing this. Containers that use component categories may
successfully use them to host older controls as the components category DLL handles the mapping, a separate
category exists for older controls CATID_ControlV1 so that a container may optionally exclude them if necessary.
As component categories are identified by GUIDs it is possible for containers that offer particular specific
functionality to have their own category IDs, generated using a GUID generation tool. However this can possibly
undermine the advantage of interoperability of controls and containers so it is preferred that wherever possible
existing component categories be used. Vendors are encouraged to consult together when defining new
component categories to ensure that they meet the common requirements of the marketplace, and follow the spirit
of interoperability of ActiveX controls.
Related topics
C
o
m
p
o
n
e
n
t
C
a
t
e
g
o
r
i
e
s
Simple Frame Site Containment
1/7/2020 • 2 minutes to read • Edit Online
A container control is an ActiveX control that is capable of containing other controls. A group box that contains a
collection of radio buttons is an example of a container control. Container controls should set the
OLEMISC_SIMPLEFRAME status bit, and should call its container's ISimpleFrameSite implementation. An
ActiveX control container that supports container controls must implement ISimpleFrameSite.
CATID - {157083E0-2368-11cf-87B9-00AA006C8166} CATID_SimpleFrameControl
Related topics
C
o
m
p
o
n
e
n
t
C
a
t
e
g
o
r
i
e
s
Simple Data Binding
1/7/2020 • 2 minutes to read • Edit Online
The ActiveX controls architecture defines a data-binding mechanism, whereby an ActiveX control can specify that
one or more of its properties are bindable. In most cases, a data-bound control should not absolutely require data
binding, so that it could be inserted into a container that does not support data binding. Obviously, in such a
situation, the functionality of the control may be reduced.
CATID - {157083E1-2368-11cf-87B9-00AA006C8166} CATID_PropertyNotifyControl
Related topics
C
o
m
p
o
n
e
n
t
C
a
t
e
g
o
r
i
e
s
Advanced Data Binding
1/7/2020 • 2 minutes to read • Edit Online
There is a set of advanced data binding interfaces that allow a more complex databinding scenario to be supported.
This component category covers that area of functionality.
CATID - {157083E2-2368-11cf-87B9-00AA006C8166} CATID_VBDataBound
Related topics
C
o
m
p
o
n
e
n
t
C
a
t
e
g
o
r
i
e
s
Visual Basic Private Interfaces
1/7/2020 • 2 minutes to read • Edit Online
Two interfaces that are implemented by Visual Basic are identified here for component categories. It is not
expected that controls should require these categories because it is possible for controls to offer alternative
functionality when these are not available.
The IVBFormat interface allows controls to better integrate into the Visual Basic environment when formatting
data.
CATID - {02496840-3AC4-11cf-87B9-00AA006C8166} CATID_VBFormat
The IVBGetControl interface allows a control to enumerate other controls on the VB form.
CATID - {02496841-3AC4-11cf-87B9-00AA006C8166} CATID_VBGetControl
Two additional private interfaces, IGetVBAObject and IGetOleObject, are described here even though they do
not define component categories. Use of these four interfaces is not recommended because they are not supported
by containers other than Visual Basic.
Related topics
C
o
m
p
o
n
e
n
t
C
a
t
e
g
o
r
i
e
s
Internet-Aware Objects
1/7/2020 • 2 minutes to read • Edit Online
There are certain categories identified to cover the persistency interfaces; these have been identified as a result of
defining how controls function across the Internet. A container that does not support the full range of persistency
interfaces should ensure that it does not host a control that requires a combination of interfaces that it does not
support.
The following tables describe the meaning for various categories as both implemented and required categories.
CATID_PersistsToMoniker, CATID_PersistsToStreamInit, Each of these categories is mutually exclusive and only used
CATID_PersisitsToStream, CATID_PersistsToStorage, when an object supports only one persistence mechanism at
CATID_PersistsToMemory, CATID_PersistsToFile, all (hence the mutual exclusion). Containers that do not
CATID_PersistsToPropertyBag support the persistence mechanism described by one of these
categories should prevent themselves from creating any
objects of classes so marked.
CATID_RequiresDataPathHost The object requires the ability to save data to one or more
paths and requires container involvement, therefore requiring
container support for IBindHost.
The following table provides the exact CATIDs assigned to each category:
CATEGORY CATID
CATID_RequiresDataPathHost 0de86a50-2baa-11cf-a229-00aa003d7352
CATID_PersistsToMoniker 0de86a51-2baa-11cf-a229-00aa003d7352
CATID_PersistsToStorage 0de86a52-2baa-11cf-a229-00aa003d7352
CATID_PersistsToStreamInit 0de86a53-2baa-11cf-a229-00aa003d7352
CATID_PersistsToStream 0de86a54-2baa-11cf-a229-00aa003d7352
CATID_PersistsToMemory 0de86a55-2baa-11cf-a229-00aa003d7352
CATID_PersistsToFile 0de86a56-2baa-11cf-a229-00aa003d7352
CATID_PersistsToPropertyBag 0de86a57-2baa-11cf-a229-00aa003d7352
Related topics
C
o
m
p
o
n
e
n
t
C
a
t
e
g
o
r
i
e
s
Windowless Controls
1/7/2020 • 2 minutes to read • Edit Online
The ActiveX Controls 96 specification includes a definition for windowless controls. Such controls do not operate
in their own window and require a container to offer a shared window into which the control may draw, see the
ActiveX SDK. Windowless controls are designed to be compatible with older control containers by creating their
own window in that situation, windowless control containers should host windowed controls in the traditional way
with no problem. It may however be useful for a container to distinguish those controls that can operate in a
windowless mode, so an appropriate component category is defined.
CATID - {1D06B600-3AE3-11cf-87B9-00AA006C8166} CATID_WindowlessObject
Related topics
C
o
m
p
o
n
e
n
t
C
a
t
e
g
o
r
i
e
s
Categorizing DCOM Proxies and Stubs
1/7/2020 • 2 minutes to read • Edit Online
DCOM marshals references to objects by constructing OBJREFs that contain CLSIDs. These CLSIDs are
vulnerable to security attacks because arbitrary DLLs can be loaded during marshaling. However, the
EOAC_NO_CUSTOM_MARSHAL flag can be specified when calling CoInitializeSecurity (see
EOLE_AUTHENTICATION_CAPABILITIES ). Setting this flag helps protect server security when using DCOM
because it reduces the chances of executing arbitrary DLLs. When this flag is set, the server allows the marshaling
only of CLSIDs that are implemented in ole32.dll, comadmin.dll, comsvcs.dll, or es.dll, or that implement the
CATID_MARSHALER category ID.
CATID_MARSHALER is a component category GUID that can be associated with a CLSID that is being custom
marshaled. The interfaces being custom marshaled with this CLSID are allowed when the
EOAC_NO_CUSTOM_MARSHAL is set via CoInitializeSecurity.
Related topics
C
o
m
p
o
n
e
n
t
C
a
t
e
g
o
r
i
e
s
General Guidelines
1/7/2020 • 2 minutes to read • Edit Online
The following topics describe various features, hints and tips for ActiveX Control and ActiveX Control container
developers to help maintain good interoperability between controls and control containers:
Overloading IPropertyNotifySink
Container-Specific Private Interfaces
Multi-Threaded Issues
Event Freezing
Container Controls
WS_GROUP and WS_TABSTOP Flags in Controls
Multiple Controls in One DLL
The IOleContainer::EnumObjects Method
Enhanced Metafiles
Licensing
Dual Interfaces
IPropertyBag and IPersistPropertyBag
Related topics
A
c
t
i
v
e
X
C
o
n
t
r
o
l
a
n
d
C
o
n
t
r
o
l
C
o
n
t
a
i
n
e
r
G
u
i
d
e
l
i
n
e
s
Overloading IPropertyNotifySink
1/7/2020 • 2 minutes to read • Edit Online
Many ActiveX control containers implement a modeless property browsing window. If a control's properties are
altered through the control's property pages, then the control's properties can get out of sync with the container's
view of those properties (the control is always right, of course). To ensure that it always has the current values for a
control's properties, an ActiveX control container can overload the IPropertyNotifySink interface (data binding)
and also use it to be notified that a control property has changed. This technique is optional and is not required of
ActiveX control containers or ActiveX controls.
Note that a control should use OnRequestEdit only for data binding; it is free to use OnChanged for either or
both purposes.
Container-Specific Private Interfaces
1/7/2020 • 2 minutes to read • Edit Online
Some containers provide container-specific private interfaces for additional functionality or improved
performance. Controls that rely on those container-specific interfaces should, if possible, work without those
container-specific interfaces present so that the control functions in different containers. For example, Visual Basic
implements private interfaces that provide string formatting functionality to controls. If a control makes use of
these private formatting interfaces, it should be able to run with default formatting support if these interfaces are
not available. If the control can function without the private interfaces, it should take appropriate action (such as
warn the user of reduced functionality) but continue to work. If this is not an option, a component category should
be registered as required so that only containers supporting this functionality can host these controls.
Multi-Threaded Issues
1/7/2020 • 2 minutes to read • Edit Online
OLE provides support for multithreaded applications, allowing applications to make OLE calls from multiple
threads. This multithreaded support is called the apartment model, it is important that all OLE components using
multiple threads follow this model. The apartment model requires that interface pointers are marshaled (using
CoMarshalInterface, and CoUnmarshalInterface) when passed between threads.
Related topics
P
r
o
c
e
s
s
e
s
,
T
h
r
e
a
d
s
,
a
n
d
A
p
a
r
t
m
e
n
t
s
Event Freezing
1/7/2020 • 2 minutes to read • Edit Online
A container can notify a control that it is not ready to respond to events by calling IOleControl::FreezeEvents
with TRUE. It can unfreeze the events by calling FreezeEvents with FALSE. When a container freezes events, it is
freezing event processing, not event receiving; that is, a container can still receive events while events are frozen. If
a container receives an event notification while its events are frozen, the container should ignore the event. No
other action is appropriate.
A control should take note of a container's call to FreezeEvents with TRUE if it is important to the control that an
event is not missed. While a container's event processing is frozen, a control should implement one of the
following techniques:
Fire the events in the full knowledge that the container will take no action.
Discard all events that the control would have fired.
Queue up all pending events and fire them after the container has called FreezeEvents with FALSE.
Queue up only relevant or important events and fire them after the container has called FreezeEvents with
FALSE.
Each technique is acceptable and appropriate in different circumstances. The control developer is responsible for
determining and implementing the appropriate technique for the control's functionality.
Container Controls
1/7/2020 • 2 minutes to read • Edit Online
As described above, container controls are ActiveX controls that visually contain other controls. The ActiveX
controls architecture specifies the ISimpleFrameSite interface to enable container controls. Containers may also
support container controls without supporting ISimpleFrameSite, although the behavior cannot be guaranteed.
For this reason, a component category exists for SimpleFrameSite controls where the full functionality of this
interface is required.
To support container controls without implementing ISimpleFrameSite, an ActiveX control container must:
Activate all controls at all times.
Reparent the contained controls to the hWnd of the containing control.
Remain the parent of the container control.
WS_GROUP and WS_TABSTOP Flags in Controls
1/7/2020 • 2 minutes to read • Edit Online
A control should not use the WS_GROUP and WS_TABSTOP flags internally; some containers rely on these flags
to manage keyboard handling.
Multiple Controls in One DLL
1/7/2020 • 2 minutes to read • Edit Online
A single .ocx DLL can container any number of ActiveX controls, thus simplifying the distribution and use of a set
of related controls.
If you ship multiple controls in a single DLL, be sure to include the vendor name in each control name in the
package. Including the vendors' names in each control name will enable users to easily identify controls within a
package. For example, if you ship a DLL that implements three controls, Con1, Con2, and Con3, then the control
names should be:
Your company name Con1 Control
Your company name Con2 Control
Your company name Con3 Control
The IOleContainer::EnumObjects Method
1/7/2020 • 2 minutes to read • Edit Online
This method is used to enumerate over all the OLE objects contained in a document or form, returning an interface
pointer for each OLE object. The container must return pointers to each OLE object that shares the same container.
Nested forms or nested controls must also be enumerated.
Some containers implement extender controls, which wrap non-ActiveX controls, and then return pointers to these
extender controls as a form is enumerated. This behavior enables ActiveX controls and ActiveX control containers
to integrate well with non-ActiveX controls, and is thus recommended, but not required.
Enhanced Metafiles
1/7/2020 • 2 minutes to read • Edit Online
Not surprisingly, enhanced metafiles provide more functionality than standard metafiles; using enhanced metafiles
generally simplifies rendering code. An enhanced metafile DC is used in exactly the same way as a standard
metafile DC. OLE supports enhanced metafiles, and includes backward compatibility with standard metafiles.
ActiveX control containers should use enhanced metafiles instead of standard metafiles.
Licensing
1/7/2020 • 2 minutes to read • Edit Online
In order to embed licensed controls successfully, ActiveX control containers must use IClassFactory2 instead of
IClassFactory. Several OLE creation and loading helper functions (OleLoad and CoCreateInstance) explicitly
call IClassFactory and not IClassFactory2, and therefore cannot be used to create or load licensed ActiveX
controls. ActiveX control containers should explicitly create and load ActiveX Controls using IClassFactory2.
Dual Interfaces
1/7/2020 • 2 minutes to read • Edit Online
OLE Automation enables an object to expose a set of methods in two ways: via the IDispatch interface, and
through direct OLE VTable binding. IDispatch is used by most tools available today, and offers support for late
binding to properties and methods.
VTable binding offers much higher performance because this method is called directly instead of through
IDispatch::Invoke. IDispatch offers late bound support, where direct VTable binding offers a significant
performance gain; both techniques are valuable and important in different scenarios. By labeling an interface as
[dual] in the type library, an OLE Automation interface can be used either via IDispatch, or it can be bound to
directly. Containers can thus choose the most appropriate technique. Support for dual interfaces is strongly
recommended for both controls and containers.
IPropertyBag and IPersistPropertyBag
1/7/2020 • 2 minutes to read • Edit Online
IPropertyBag and IPersistPropertyBag optimize save as text mechanisms, and therefore are recommended for
ActiveX Control containers that implement a save as text mechanism. IPropertyBag is implemented by a
container, and is roughly analogous to IStream. IPersistPropertyBag is implemented by controls, and is roughly
analogous to IPersistStream.
Event Coordinate Translation
1/7/2020 • 2 minutes to read • Edit Online
The 96 specification for controls requires that coordinates passed for events fired by the control change from being
HIMETRIC to being points based. This change brings the event passing of coordinates in line with properties and
methods and thus coordinate translation is no longer the responsibility of the container. This raises certain
compatibility issues where a control fires events using a coordinate base that it is not expecting, this should only be
an issue where a 96 control container is hosting an older pre-96 control as follows:
When an older pre-96 container hosts a 96 control the control will present the event coordinates as points, this
should not cause the container any problems as the container should recognize the parameter type.
When a 96 container hosts a pre-96 control the control will present the container with coordinates and expect
the container to any translation necessary. However the 96 container will be expecting a control to conform to
the 96 controls specification and present its coordinates as points. The control uses the TransformCoords
method on the IOleControlSite interface provided by the container in the same way as it does for properties
and methods to achieve this.
As a result the user of a 96 container hosting pre-96 controls will need to be aware that further translation of
coordinates may be necessary when events are fired.
Standard DISPIDS
1/7/2020 • 2 minutes to read • Edit Online
A number of standard dispids have been defined for the controls specification.
DISPID_MOUSEPOINTER
Property of type integer.
VALUE DESCRIPTION
1 Arrow
3 I Beam
8 Size NW, SE
10 Up Arrow
11 Hourglass (wait)
12 No Drop
15 Size all
DISPID_PICTURE
Property of type picture.
DISPID_VALID
Used to determine if the control has valid data or not.
Property of type BOOL.
DISPID_ AMBIENT_PALETTE
Used to allow the control to get the container's HPAL. If the container supplies an ambient palette then that is the
only palette that may be realized into the foreground. Controls that want to realize their own palettes must do so in
the background. If there is no ambient palette provided by the container, then the active control can realize its
palette in the foreground. Palette handling is further discussed in Palette Behavior for OLE Controls which is in the
ActiveX SDK.
A new databinding attribute has been added to allow properties distinguish between communicating changes only
when focus leaves the control or during all property change notifications.
The new attribute, known as ImmediateBind, enables controls to differentiate two different types of bindable
properties. One type of bindable property needs to notify every change to the database, for example with a check
box control where every change needs to be sent through to the underlying database even though the control has
not lost the focus. However controls such as a listbox only wish to have the change of a property notified to the
database when the control loses focus, as the user may have changed the highlighted selection with the arrow keys
before finding the desired setting, to have the change notification sent to the database every time that the user hit
the arrow key would be give unacceptable performance. The new immediate bind property allows individual
bindable properties on a form to have this behavior specified, when this bit is set all changes will be notified.
The new ImmediateBind bit maps through to the new VARFLAG_FIMMEDIATEBIND (0x80) and the
FUNCFLAG_FIMMEDIATEBIND (0x80) bits in the VARFLAGS and FUNCFLAGS enumerations for the ITypeInfo
interface allowing for the properties attributes to be inspected.
Reference
1/7/2020 • 2 minutes to read • Edit Online
The following programming elements are used to create standard COM objects and property pages.
Constants
Enumerations
Functions
Interfaces
Structures
Constants
1/7/2020 • 2 minutes to read • Edit Online
The following constants are used to create standard COM objects and property pages.
PICTYPE Constants
PICTYPE Constants
1/7/2020 • 2 minutes to read • Edit Online
Describe the type of a picture object as returned by IPicture::get_Type, as well as to describe the type of picture in
the picType member of the PICTDESC structure that is passed to OleCreatePictureIndirect.
CONSTANT/VALUE DESCRIPTION
Requirements
Header
Ole
Ctl.h
See also
I
P
i
c
t
u
r
e
:
:
g
e
t
_
T
y
p
e
O
l
e
C
r
e
a
t
e
P
i
c
t
u
r
e
I
n
d
i
r
e
c
t
P
I
C
T
D
E
S
C
Enumerations
1/7/2020 • 2 minutes to read • Edit Online
The following enumerations are used to create standard COM objects and property pages.
GUIDKIND
KEYMODIFIERS
PICTUREATTRIBUTES
POINTERINACTIVE
QACONTAINERFLAGS
Functions
1/7/2020 • 2 minutes to read • Edit Online
The following functions are used to create standard COM objects and property pages.
OleCreatePropertyFrame
OleCreatePropertyFrameIndirect
OleLoadPicturePath
OleTranslateColor
Interfaces
1/7/2020 • 2 minutes to read • Edit Online
The following interfaces are used to create standard COM objects and property pages.
INTERFACE DESCRIPTION
IPointerInactive Enables an object to remain inactive most of the time, yet still
participate in interaction with the mouse, including drag and
drop.
IPropertyPageSite Provides the main features for a property page site object.
The following structures are used to create standard COM objects and property pages.
CADWORD
CALPOLESTR
CAUUID
CONTROLINFO
FONTDESC
LICINFO
OCPFIPARAMS
PAGERANGE
PAGESET
PICTDESC
PROPPAGEINFO
QACONTAINER
QACONTROL
COM Language Translations
1/7/2020 • 2 minutes to read • Edit Online
Components created using the Component Object Model (COM ) can be reused in applications written in any
programming language that supports COM. This is because COM is a binary standard and, as such, is language-
independent.
COM objects are documented in the most relevant programming language or languages. For example, objects that
are created for use in webpages are typically documented in the Microsoft Visual Basic development system,
whereas system-level objects are typically documented in C++. However, because COM is language-neutral, you
are not limited to using an object in the same language in which it is written or documented. For example, you can
write an application in JScript that uses a control created in C++ and documented in Visual Basic.
The following topics discuss the differences between programming languages and describe how to translate COM
object syntax from one language to another. Additional topics describe how to use COM objects in various
scripting languages and environments.
Syntax Differences
Data Type Conversions
IDL Files
Translating COM Object Syntax for Programming Languages
Scripting with COM Objects
The intent is to address the most common language translation issues that arise when using COM objects. The
techniques and principles described apply to any programming or scripting language that supports COM. Because
scripting languages and programming languages represent different programming paradigms, translation
between scripting languages and programming languages is not addressed.
Related topics
C
o
m
p
o
n
e
n
t
O
b
j
e
c
t
M
o
d
e
l
(
C
O
M
)
Syntax Differences
1/7/2020 • 2 minutes to read • Edit Online
The most apparent change as you move between programming languages is the change in syntax.
Consider the EnhEvents object's Add method, shown as it is declared in three different languages.
HRESULT Add(
double Time,
BSTR Name,
VARIANT* pVal
);
Although the syntax of each language expresses the method differently, the functionality is the same. In each
language, the Add method takes the parameters Time and Name and returns an EnhEvent object. In the C++
example, the method returns the object by using a third, output parameter, pVal.
Typically, the functionality of a COM object is the same across programming languages. Because of this,
documentation for a COM object is useful even if the object is documented in another programming language
than the one you are using. The descriptions of the object's functionality, parameters, and return values are, with
few exceptions, valid for all languages.
For information about how to convert the syntax of a COM object to another programming language, see
Translating COM Object Syntax for Programming Languages.
The syntax differences among the scripting languages JavaScript, JScript, and VBScript are less pronounced than
the syntax differences among the programming languages shown preceding. For example, consider the square
function as it is implemented in each of these three scripting languages:
Function square(x)
square = x*x
End Function
Notice that the scripting languages, unlike the programming languages, are weakly typed. In other words, you do
not have to specify the data type of a parameter or return value when you declare a function. Instead, the variables
are automatically cast to the appropriate data type. In the case of VBScript, all variables are of the same data type,
Variant.
The JavaScript and JScript syntax for square is the same. JScript is largely compatible with JavaScript. However,
JScript includes some objects not currently supported by JavaScript, such as ActiveXObject, Enumerator, Error,
Global, and VBArray. For more information about these objects, see the JScript Language Reference.
On the surface, JavaScript and JScript syntax resembles Java syntax. This similarity is only superficial. The Java
language was developed independently from both JavaScript and JScript and is not related to either.
VBScript, on the other hand, is a subset of the Visual Basic programming language. Because of this, VBScript
syntax is a subset of Visual Basic syntax and is often interchangeable with Visual Basic syntax.
For information on using COM objects in scripting languages, see Scripting with COM Objects.
Data Type Conversions
1/7/2020 • 2 minutes to read • Edit Online
Each programming language defines certain types and containers for data. Most of these data types, especially the
primitives, map easily to other programming languages. Some data types, however, have no equivalent in another
language and cannot be converted.
For specific information about data types not recognized by your programming language, see the following topics:
Translating to C++
Translating to Visual Basic
Translating to Java
The following table lists conversions between programming languages for common data types.
For information about VARTYPE values and how to use them, see the topic IDispatch Data Types and Structures.
The data type conversions between scripting languages are simpler than those for programming languages.
JScript and JavaScript both support the same data types, and VBScript supports only a single data type, Variant.
Thus, all JScript and JavaScript data types become Variant types when converted to VBScript. When you convert
VBScript to JScript or JavaScript, the Variant types become numbers, strings, Boolean values, and so on.
IDL Files
1/7/2020 • 2 minutes to read • Edit Online
COM uses the Microsoft Interface Definition Language (MIDL ) to describe COM objects. MIDL is an extension of
the IDL for distributed computing environments defined by the Open Software Foundation, which was developed
to define interfaces for remote procedure calls in traditional client/server applications. MIDL includes most of the
attributes and statements of Object Definition Language (ODL ), the language originally used to generate type
libraries for OLE Automation.
In C++ and Java, a developer building a COM object creates an IDL file that the MIDL compiler then processes to
create a type library or header and proxy files, or both. A type library is a binary file that describes the COM object
or COM interfaces, or both. A type library is the compiled version of the IDL file. However, type libraries support
ODL semantics only. In particular, they cannot represent all the information from an IDL file related to IDL
attributes like [size_is]. You need to create and use proxy files for IDL files affected by information loss in the type
library.
In Visual Basic, a developer creating a COM object does not create an IDL file. Instead, Visual Basic gathers
information using class and project properties and directly creates the type library.
Translating COM Object Syntax for Programming
Languages
1/7/2020 • 2 minutes to read • Edit Online
To call a COM object from an application written in a programming language other than the one used to write the
COM object, you must first translate the object's syntax to your programming language. This can be done using
the following steps:
1. View the COM object's type library in your programming language's syntax. Doing this provides you with
descriptions of the object's classes, interfaces, methods, properties and events in the language syntax you
use.
Microsoft developer products provide several tools to assist you in viewing and converting type libraries.
For more information, see Type Library Viewers and Conversion Tools and How Developer Tools Use Type
Libraries.
Once you can view the object's type library in your preferred programming language, you can compare its
syntax to that in the documentation for the object. If the object is documented in a programming language
other than the one you are using, the data types and syntax may differ, but descriptions of parameters,
return values, and the object's functionality should be the same.
2. Take into account any special considerations for translating to your programming language.
Because each programming language defines concepts that may not have an equivalent in other languages,
some of an object's functionality may work differently in another language, or not be available at all. For
example, the Visual Basic programming language does not recognize C++ unsigned data types, such as
unsigned long. An application written in Visual Basic cannot use COM methods that accept or return
unsigned data type variables.
3. Add the COM object's compiled code to your project. The compiled code is typically contained in a .dll or
.ocx file. This step is necessary for the compiler to recognize the COM object's classes. After you add the
COM object, your application can use its classes and interfaces.
The following topics describe how to translate and use COM objects in a variety of programming languages:
Translating to C++
Translating to Visual Basic
Translating to Java
These topics describe conversion tools and processes provided by Microsoft developer products. For instructions
on how to program COM objects using development tools created by other companies, see those development
tools' documentation.
Type Library Viewers and Conversion Tools
1/7/2020 • 2 minutes to read • Edit Online
Type libraries contain the specification for one or more COM elements, including classes, interfaces, enumerations,
and more. These files are stored in a standard binary format. A type library can be a stand-alone file with the .tlb
file name extension, or it can be stored as a resource in an executable file, which can have an .ocx, .dll, or .exe file
name extension. The type library viewers and conversion tools described following read this format to gain
information about the COM elements in the library.
Before you can program an object in a particular programming language, you must be able to view its type library
in that language. Doing this provides you with the proper syntax for the classes, interfaces, methods, properties,
and events of the COM object.
Microsoft development products provide the following tools that you can use to generate, extract, and view type
library information.
C++
OLE -COM Object Viewer
MIDL compiler
MkTypLib
Visual Basic
Visual Basic Object Browser
Java
JActiveX
Java Type Library Wizard
JavaTLB
For an overview of how these tools interact with type libraries, see How Developer Tools Use Type Libraries.
How Developer Tools Use Type Libraries
1/7/2020 • 2 minutes to read • Edit Online
The following diagram illustrates how the various development tools interact with a COM object's type library.
Each type library exposes standard programmatic interfaces that tools can call to get information about the
elements described in that type library. In this diagram, GUID stands for globally unique identifier and RPC for
remote procedure call.
In the preceding diagram, the C++ conversion tools, such as the MIDL compiler and the wizards provided by the
Microsoft Visual C++ development system, generate header and stub files. You can add these files to your project
in order to use the COM object described by the type library.
Similarly, in Java the developer tools generate Java class and source files, which you can then import into your
application.
In Visual Basic, the scenario is somewhat simpler. You do not need to generate additional files. The Visual Basic
environment provides dialog boxes listing the COM objects currently installed on your computer. You select the
component you want to call from your application, and it is added to your project, either as a component or a
reference.
The OLE -COM viewer reads a type library, generates a temporary IDL file based on the type library, and displays
it to users. The OLE -COM viewer also displays the C++ syntax for the COM elements listed in the type library.
For more information about type libraries, see Type Libraries and the Object Description Language.
Translating to C++
1/7/2020 • 2 minutes to read • Edit Online
Visual C++ provides several tools to assist you in adding COM objects to your project. You can add an ActiveX
control to your project, use the MFC Class Wizard, or run the MIDL compiler on an IDL file.
If you are using a C++ development environment other than Visual C++, consult that product's documentation
for information on COM conversion tools.
Once you have added the COM object's include or stub files to your project, your application can use the COM
object's classes.
Visual C++ also provides the OLE -COM Object Viewer, which you can use to view compiled type library
information. The object viewer presents the COM classes in C++ syntax.
For more information, see the following topics:
Translating to C++ from Visual Basic
Translating to C++ from Java
Adding an ActiveX Control to a Visual C++ Project
MIDL Compiler
MkTypLib Command-Line Tool
OLE -COM Object Viewer
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
J
a
v
a
T
r
a
n
s
l
a
t
i
n
g
t
o
V
i
s
u
a
l
B
a
s
i
c
Translating to C++ from Visual Basic
1/7/2020 • 2 minutes to read • Edit Online
Visual Basic handles pointers implicitly. In C++, your application is responsible for performing any necessary
pointer arithmetic.
By default, Visual Basic passes parameters by reference (as pointers). Parameters that are meant to be passed by
value only are specified by the keyword ByVal. For example, a ByVal Integer parameter in Visual Basic is
equivalent to a short parameter in C++, whereas a ByRef Integer parameter in Visual Basic is equivalent to a
short* parameter.
A parameter that is declared As String in Visual Basic is declared as a pointer to a BSTR in C++. Setting a string
pointer to NULL in C++ is equivalent to setting the string to the vbNullString constant in Visual Basic. Passing a
zero-length string ("") to a function designed to receive NULL does not work, because this passes a pointer to a
zero-length string instead of a zero pointer.
C++ and Visual Basic differ slightly in how they represent properties. In C++, properties are represented as a set
of accessor functions, one that sets the property value and one that retrieves the property value. In Visual Basic,
properties are represented as a single item that can be used to retrieve or set the property value.
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
C
+
+
Translating to C++ from Java
1/7/2020 • 2 minutes to read • Edit Online
Java handles pointers and memory management implicitly. In C++, your application is responsible for allocating
and deallocating memory, and for performing any necessary pointer arithmetic.
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
C
+
+
Adding an ActiveX Control to a Visual C++ Project
1/7/2020 • 2 minutes to read • Edit Online
The following procedure adds dispatch class and header files for an ActiveX control to a Visual C++ project.
To add an ActiveX control to a Visual C++ Project
1. On the Project menu, click Add to Project. A shortcut menu appears.
2. Click Components and Controls. The Components and Controls Gallery dialog box appears.
3. Click the component to add to your project. Visual C++ displays a dialog box from which you can select a
subset of the component's classes to add to your project.
4. Click to select the check boxes of the classes you want to add, and click OK.
Visual C++ generates dispatch class and header files for the component and adds them to your project.
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
C
+
+
MIDL Compiler
1/7/2020 • 2 minutes to read • Edit Online
The MIDL compiler processes an IDL file to generate a type library and output files. The type of output files
generated by the MIDL compiler depends on the attributes specified in the IDL file's interface attribute list.
If the attribute list contains the [object] keyword, the MIDL compiler generates COM interface output files: an
interface proxy file, an interface header file, and a globally unique identifier (GUID ) file for the interface. If the IDL
file contains a library statement, MIDL generates a type library file with the .tlb file name extension. If there are
any interfaces in the IDL file that do not have the [object] keyword and are not enclosed in a library statement,
the MIDL compiler generates interface output files appropriate for remote procedure calls (RPCs): a client stub file,
a server stub file, and a header file. For more information, see the topics Interface Definitions and Type Libraries
and Generating a Type Library with MIDL.
To generate a type library and output files from an IDL file:
From the command prompt, run
midl filename
where filename is the name of the IDL file.
The MIDL compiler also supports several optional parameters. For a complete list, see "MIDL Command-Line
Reference" in the Visual C++ documentation, or run the following command line:
midl /?
Related topics
M
i
c
r
o
s
o
f
t
I
n
t
e
r
f
a
c
e
D
e
f
i
n
i
t
i
o
n
L
a
n
g
u
a
g
e
T
r
a
n
s
l
a
t
i
n
g
t
o
C
+
+
MkTypLib Command-Line Tool
1/7/2020 • 2 minutes to read • Edit Online
[The Mktyplib.exe tool is obsolete. Use the MIDL compiler instead. If you need backward compatibility with old
Automation programs, use the MIDL compiler with the /mktyplib203 option.]
MkTypLib is a command-line application that processes an IDL file to produce a type library. It can also be used to
generate a C or C++ header file.
To generate a type library from a ODL file:
From the command prompt, run the following command:
**mktyplib **filename
where filenameis the name of the ODL file.
MkTypLib also supports several optional parameters. For a complete list, run the following command line:
mktyplib /?
Because MkTypLib is an obsolete application, it cannot parse IDL files or files with interfaces defined outside of a
library statement. For more information, see Differences Between MIDL and MkTypLib.
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
C
+
+
OLE-COM Object Viewer
1/7/2020 • 2 minutes to read • Edit Online
The OLE -COM object viewer, Oleview.exe, is an application supplied with Visual C++ that displays the COM
objects installed on your computer and the interfaces they support. You can use this object viewer to view type
libraries.
To view a COM object's type library:
1. On the object viewer File menu, click View TypeLib. An Open dialog box appears.
2. Specify the type library file you want to open, and click OK.
The object viewer displays the object's interfaces.
For more information, see Using the OLE/COM Object Viewer in the Visual C++ documentation.
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
C
+
+
Translating to Visual Basic
1/7/2020 • 2 minutes to read • Edit Online
You can add a COM object to your Visual Basic project either as a reference or a component. Once the object is
added to your project, your application can access its classes and interfaces. You can then use the Visual Basic
Object Browser to view the object's type library information in Visual Basic syntax.
Typically, controls are added to a project as a components and noncontrols are added as references. When a
COM object is added as a component, it appears in the Visual Basic toolbox. New instances of that object are
created by dragging the object icon from the toolbox onto a Visual Basic form or other type of container. New
instances of COM objects added as references are created using the new keyword.
The distinction between using a class as a reference versus a component is subtle but important. When you add
an object as a reference, you can use only the type library that the control provides, or the "raw" type library.
If you add a control as a component, Visual Basic merges the extender properties and methods of the form in
which the control is embedded with the control's type library, thus providing a wrapped, extended version of the
type library. With this version of the type library, you can use extender properties such as Top and Left as if they
were part of the control, instead of the control's container.
Visual Basic does not currently support multiple type libraries built into a single .dll file. If you run into a DLL that
incorporates multiple type libraries, you should get stand-alone copies of the type libraries from the source that
supplied the object in order to use the object with Visual Basic.
For more information, see the following topics:
Translating to Visual Basic from C++
Translating to Visual Basic from Java
Adding a Component to a Visual Basic Project
Adding a Reference to a Visual Basic Project
Visual Basic Object Browser
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
C
+
+
T
r
a
n
s
l
a
t
i
n
g
t
o
J
a
v
a
Translating to Visual Basic from C++
1/7/2020 • 2 minutes to read • Edit Online
Using the C++ programming language, developers can directly access the memory that stores a particular
variable. Memory pointers provide this direct access. In Visual Basic, pointers are handled for you. For example, a
parameter declared as a pointer to an int in C++ is equivalent to a parameter declared in Visual Basic as a
ByRef Integer.
A parameter that is declared As String in Visual Basic is declared as a pointer to a BSTR in C++. Setting a string
pointer to NULL in C++ is equivalent to setting the string to the vbNullString constant in Visual Basic. Passing in
a zero-length string ("") to a function designed to receive NULL does not work, as this passes a pointer to a zero-
length string instead of a zero pointer.
C++ supports data containers, namely structures and unions, that have no equivalent in early versions of Visual
Basic. For this reason, COM objects typically wrap information that usually is stored in structures and unions in
object classes. Some COM objects, however, may contain structures, causing portions of the object's methods or
functionality to be inaccessible to Visual Basic.
Some C++ data types are not supported in Visual Basic, for example unsigned types and HWND types. Methods
that accept or return these data types are not available in Visual Basic.
Visual Basic uses Automation-compatible data types as its internal data types. Thus, C++ data types that are
Automation-compatible are also compatible with Visual Basic. Data types that are not Automation-compatible may
not be able to be converted to Visual Basic.
The following table lists the data types are supported by Visual Basic and their VARTYPE equivalents. VARTYPE
is an enumeration that lists the Automation variant types.
Date VT_DATE
Currency VT_CY
Object *VT_DISPATCH
String VT_BSTR
Boolean VT_BOOL
Currency VT_DECIMAL
Single VT_R4
Double VT_R8
Decimal VT_DECIMAL
VISUAL BASIC DATA TYPE VARTYPE EQUIVALENT
Byte VT_DECIMAL
Variant VT_VARIANT
All parameters in Visual Basic, unless labeled with the keyword ByVal, are passed by reference (as pointers)
instead of by value.
C++ and Visual Basic differ slightly in how they represent properties. In C++, properties are represented as a set
of accessor functions, one that sets the property value and one that retrieves the property value. In Visual Basic,
properties are represented as a single item that can be used to retrieve or set the property value.
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
V
i
s
u
a
l
B
a
s
i
c
Translating to Visual Basic from Java
1/7/2020 • 2 minutes to read • Edit Online
Visual Basic uses Automation-compatible data types as its internal data types. Thus, Java data types that are
Automation-compatible are also compatible with Visual Basic. Data types that are not Automation-compatible may
not be able to be converted to Visual Basic.
Java and Visual Basic differ slightly in how they represent properties. In Java, properties are represented as a set of
accessor functions, one that sets the property value and one that retrieves the property value. In Visual Basic,
properties are represented as a single item that can be used to retrieve or set the property value.
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
V
i
s
u
a
l
B
a
s
i
c
Adding a Component to a Visual Basic Project
1/7/2020 • 2 minutes to read • Edit Online
The following procedure describes how to add a COM object as a component to a Visual Basic project. Your
application can then use the classes of that object.
Adding a control as a component exposes the Visual Basic extender properties and methods as if they were part of
the control. In contrast, when you add an object as a reference you can only use the type library provided by the
control, or the "raw" type library.
To insert a control into a Visual Basic project
1. On the Project menu, click Components.
2. Click to select the check box next to the component you want to add. If the component is not listed, locate the
.dll or .ocx file using Browse.
3. Click OK.
The component is now part of the project and appears in the object toolbar. Your application can create instances
of the control by dragging the control from the toolbar and dropping it onto a form or dialog box.
Related topics
A
d
d
i
n
g
a
R
e
f
e
r
e
n
c
e
t
o
a
V
i
s
u
a
l
B
a
s
i
c
P
r
o
j
e
c
t
T
r
a
n
s
l
a
t
i
n
g
t
o
V
i
s
u
a
l
B
a
s
i
c
Adding a Reference to a Visual Basic Project
1/7/2020 • 2 minutes to read • Edit Online
The following procedure describes how to add a reference to a COM object to a Visual Basic project. Your
application can then use the classes of that object.
When you add an object as a reference, you can only use the type library provided by the control, or the "raw" type
library. In contrast, adding a control as a component also exposes the Visual Basic extender properties and
methods as if they were part of the control.
To make a Visual Basic reference to a component
1. On the Project menu, click References.
2. Click to select the check box next to the component you want to add. If the component is not listed, locate the
.dll or .ocx file using Browse.
3. Click OK.
The component is now part of the project. Your application can create class instances using the New keyword.
Related topics
A
d
d
i
n
g
a
C
o
m
p
o
n
e
n
t
t
o
a
V
i
s
u
a
l
B
a
s
i
c
P
r
o
j
e
c
t
T
r
a
n
s
l
a
t
i
n
g
t
o
V
i
s
u
a
l
B
a
s
i
c
Visual Basic Object Browser
1/7/2020 • 2 minutes to read • Edit Online
After a COM object has been added to your project as a reference or component, you can use the Visual Basic
Object Browser to view type library information for that object in Visual Basic.
To view a COM object in the Object Browser:
On the View menu, click Object Browser.
The left side of the Object Browser window displays all of the classes of references and components added to the
current project. The right side contains the methods, properties, and events of those classes.
You can filter which COM object classes are displayed by selecting an object library from the library selection
drop-down list.
For more information, see Browsing ActiveX Component Type Libraries in the Visual Basic documentation.
In some cases, the Visual Basic Object Browser appears not to show a return type for a function or property. No
return type appears when the return type is the default type, Variant. If the description pane of the Object Browser
describes the element as a function or property and a return type is not shown, the return type statement is "As
Variant".
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
V
i
s
u
a
l
B
a
s
i
c
Translating to Java
1/7/2020 • 2 minutes to read • Edit Online
The Microsoft Visual J++ development system for Java provides two tools that you can use to generate type
library information for a COM object in Java syntax, the Java Type Library Wizard and the JActiveX command-
line tool. Using either of these tools, you can generate Java class files for a COM object.
In Visual J++ version 6.0, the JActiveX tool replaces the JavaTLB command-line tool. For more information, see
the Visual J++ documentation.
If you are using a Java development environment other than Visual J++, consult that product's documentation
for information on COM conversion tools.
Once you have generated the class files for a component, you can add the component classes to your Java
application using the import statement.
You can then create and use the object's classes in your Java application. For more information about the Java
import statement, see a reference on the Java programming language.
For more information, see the following topics:
Translating to Java from C++
Translating to Java from Visual Basic
JActiveX Command-Line Tool
Java Type Library Wizard
JavaTLB Command-Line Tool
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
C
+
+
T
r
a
n
s
l
a
t
i
n
g
t
o
V
i
s
u
a
l
B
a
s
i
c
Translating to Java from C++
1/7/2020 • 2 minutes to read • Edit Online
Using the C++ programming language, developers can directly access the memory that stores a particular
variable. Memory pointers provide this direct access. In Java, pointers are handled for you.
In Java, struct, union, and typedef composite data types are handled exclusively through the use of classes. For
example, the C++ VARIANT data type maps to com.ms.com.Variant in Java.
In C++, strings are an array of characters. In Java, strings are objects. Methods that act on strings treat the string
as a complete object.
COM methods return a value known as a HRESULT, which is a 32-bit error code. The Java support for Microsoft
Internet Explorer defines a class, com.ms.com.ComException, which wraps the HRESULT error code.
Java does not support unsigned data types except for char, which is a 16-bit unsigned integer. Methods that accept
or return other unsigned data types cannot be used from Java.
Java does not support multidimensional arrays. Methods that accept or return multidimensional arrays are not
available from Java.
Boolean values in Java cannot be cast to 0 and 1.
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
J
a
v
a
Translating to Java from Visual Basic
1/7/2020 • 2 minutes to read • Edit Online
By default, Visual Basic passes parameters by reference. Parameters that are meant to be passed by value only are
specified by the keyword ByVal.
Java does not support multidimensional arrays. Methods that accept or return multidimensional arrays are not
available from Java.
Java and Visual Basic differ slightly in how they represent properties. In Java, properties are represented as a set of
accessor functions, one that sets the property value and one that retrieves the property value. In Visual Basic,
properties are represented as a single item that can be used to retrieve or set the property value.
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
J
a
v
a
JActiveX Command-Line Tool
1/7/2020 • 2 minutes to read • Edit Online
The JActiveX command-line application is a component of Visual J++ 6.0. It reads the type library of a Microsoft
ActiveX control and generates the corresponding Java source files. You can then compile these source files and
import them into your Java application.
To generate Java source files for a COM object, from the command prompt, run:
jactivex filename
where filename is the name of the file that contains the type library. This file may have any of the following file
name extensions: .tlb, .olb, .ocx, .dll, or .exe.
For more information about the optional parameters you can set in JActiveX, see the Visual J++ documentation,
or type the following command line:
jactivex /?
WARNING
Do not use Visual J++ compilers prior to version 1.02.3920 to compile the files generated by JActiveX.exe. This is because
the generated source files must be compiled with a @com-aware compiler. Only Visual J++ compilers later than version
1.02.3920 are @com-aware.
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
J
a
v
a
Java Type Library Wizard
1/7/2020 • 2 minutes to read • Edit Online
The Java Type Library Wizard is a component of Visual J++ 5.0. This wizard generates class files and Java type
library information for a COM object.
To generate Java class files and type library information
1. On the Tools menu, click Java Type Library Wizard. A list of the installed COM components appears.
2. Click to select the check boxes next to the items you want to convert.
3. Click OK. The type library wizard generates class files for the selected components. It prints the import
statement required to insert each component into a Java application or applet and a summary text file that
contains the Java type library information for the object.
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
J
a
v
a
JavaTLB Command-Line Tool
1/7/2020 • 2 minutes to read • Edit Online
JavaTLB is a component of Visual J++ 5.0. JavaTLB is a command-line application that generates class files for a
COM object. Methods that contain data types that cannot be accurately and safely represented in Java are not
converted.
Unlike the Java Type Library Wizard, JavaTLB does not generate a summary file containing the Java type library
information.
To generate Java class files for a single COM object, from the command prompt run:
javatlb filename
where filenameis the name of the file that contains the type library. This file may have any of the following file
name extensions: .tlb, .olb, .ocx, .dll, or .exe.
To generate Java class files for multiple COM objects, from the command prompt run:
**javatlb @**TextFile
where TextFile is the name of a text file that contains a list of the files containing the COM object's type libraries.
NOTE
In Visual J++ 6.0, the JavaTLB command-line tool is replaced by the JActiveX tool. For more information, see the Visual J++
6.0 documentation.
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
J
a
v
a
Scripting with COM Objects
1/7/2020 • 2 minutes to read • Edit Online
A scripting language is a programming language that is parsed at run time by a scripting engine, a component
that translates scripts written in that language into machine code. Each scripting engine translates a specific
scripting language. A scripting host is an application, such as a Web browser, that hosts a scripting engine to run
scripts. If your scripting host supports COM, you can write scripts that use COM objects. The following topics
describe scripting hosts that support COM objects, common scripting languages, and how to translate between
scripting languages.
A scripting language differs from a compiled language in that it is translated into machine code at run time. This
means that each time you run a script, the scripting engine first parses the code and then runs it. In contrast,
compiled languages, such as C++, are translated to machine code once, during compilation. When you run a
compiled application, the operating system simply runs the precompiled code.
Because a scripting engine must reparse a script each time it runs, scripting languages are typically slower and
less efficient than their precompiled counterparts. The advantage of scripts, however, is they are easy to write and
maintain. Scripting languages are usually simpler than precompiled languages, and when a script changes, it does
not need to be recompiled. For lightweight and rapidly changing applications, such as webpages, scripting
languages are ideal.
There are several host environments in which you can write scripts that use COM objects, as described following:
Embedding COM Objects in Web Pages
Using COM Objects in Active Server Pages
Using COM Objects in Windows Script Host
Scripting COM Objects in Custom Applications
In each of the host environments mentioned preceding, a scripting engine parses and runs the script. Because the
engine for each scripting language is a separate component, you can add a new scripting language to an
environment by adding a new engine.
The most commonly used scripting languages are:
Microsoft Visual Basic Scripting Edition (VBScript), a subset of Visual Basic.
JavaScript, the Netscape scripting language, formerly known as LiveScript.
Microsoft JScript development software, the Microsoft implementation of the ECMA 262 language
specification.
Microsoft provides scripting engines for JScript and VBScript. Other software companies provide ActiveX
scripting engines for languages such as PerlScript, PScript, Python, and others.
For more information see the ECMA 262 language specification.
Note that most scripting languages, such as VBScript and JScript, cannot access or modify files. This inability
prevents the script from altering data on client computers. COM objects, however, have no such limitations. Once
they are downloaded and installed on client computers, they can perform any standard application action. Thus,
users should only download and run ActiveX controls from trusted sources.
For information on translating between scripting languages, see the following topics:
Translating to VBScript
Translating to JScript
Translating to JavaScript
Embedding COM Objects in Web Pages
1/7/2020 • 2 minutes to read • Edit Online
You can use COM objects in webpages. To do this, first create an instance of that COM object. After an object
instance is created, you can use it in subsequent scripts on that webpage.
To create a COM object instance in a webpage, you can use an OBJECT tag. Alternatively, if your scripting
language provides a native way to create COM objects, you can create an object instance using script.
Note that embedding COM objects in webpages only works with browsers that support ActiveX and COM, for
example Internet Explorer.
The following example illustrates using the OBJECT tag to embed a COM object in a webpage:
<OBJECT
ID = vid
CLASSID = "clsid:31263EC0-2957-11CF-A1E5-00AA9EC79700"
BORDER = 0
VSPACE = 0
HSPACE = 0
ALIGN = TOP
HEIGHT = 100%
WIDTH = 100%
>
</OBJECT>
You can also create a COM object instance in script, if your scripting language provides a way to create COM
objects. For example, VBScript provides the CreateObject method and JScript provides the ActiveXObject object.
Creating objects in script is illustrated in the following examples.
In addition to the CreateObject method and the ActiveXObject object, both VBScript and JScript provide the
method GetObject, which returns an object instance.
After a COM object has been created, you can reference it in subsequent scripts by using the identifier specified in
the OBJECT tag's ID attribute. In the preceding example, this identifier was specified as "vid." Note that the script
that uses the COM object must appear after the OBJECT tag or script that creates the object instance; otherwise,
the object identifier is undefined. The following script uses the objXL object to display the version information for
Microsoft Excel.
Related topics
S
c
r
i
p
t
i
n
g
w
i
t
h
C
O
M
O
b
j
e
c
t
s
Using COM Objects in Active Server Pages
1/7/2020 • 2 minutes to read • Edit Online
You can script COM objects in Active Server Pages (ASP ) applications. To do so, you must first create an instance
of the object either by using the OBJECT tag or by calling the CreateObject method of the ASP Server object.
Once a COM object has been created, you can use it in subsequent scripts on the ASP page.
Using ASP, you can work with many different types of scripting engines, each of which supports a different
scripting language. ASP comes with VBScript and JScript scripting engines. You can also plug in scripting engines
developed by other companies to support languages such as PerlScript, PScript, Python, and others.
If you do not set the scripting language for an ASP page, VBScript is the default. To specify a scripting language
other than VBScript, include a line such as the following at the top of each ASP page:
To use a COM object in an ASP page, you must first create an instance of that object. You do this by using the
OBJECT tag and specifying the value "SERVER" for the RUNAT attribute, as shown in the following example. By
default, the OBJECT tag creates an instance of the object on the client. Setting the RUNAT attribute to SERVER
causes the object to be created on the server. The object must run on the server in order to be used by ASP.
<OBJECT
RUNAT=SERVER
ID=MyAds
CLASSID="Clsid:1621F7C0-60AC-11CF-9427-444553540000">
</OBJECT>
You can also create an instance of a COM object on an ASP page by calling the CreateObject method of the ASP
Server object. Using Server.CreateObject is slower than creating the object using an OBJECT tag, but it is slightly
more readable because it specifies the programmatic identifier instead of the class identifier of the COM object.
The Server object is exposed by ASP and does not need to be created. How to call Server.CreateObject is
illustrated in the following examples. The first example is VBScript:
<%
Set MyAds = Server.CreateObject("MSWC.AdRotator")
%>
<%
var MyAds = Server.CreateObject("MSWC.AdRotator")
%>
Calling CreateObject is slower than using the OBJECT tag to create a COM object. In applications where
performance is critical, you should use the OBJECT tag.
After you have created an instance of the COM object, you can use it in scripts. Doing this is illustrated in the
VBScript example following, which sets the value of the COM object's Border property.
Related topics
S
c
r
i
p
t
i
n
g
w
i
t
h
C
O
M
O
b
j
e
c
t
s
Using COM Objects in Windows Script Host
1/7/2020 • 2 minutes to read • Edit Online
Microsoft Windows Script Host is a scripting utility you can use to run scripts within the base operating system.
You can use Windows Script Host to automate common tasks and to create powerful macros and logon scripts.
Windows Script Host comes with VBScript and JScript ActiveX scripting engines. Other software companies
provide ActiveX scripting engines for languages such as PerlScript, PScript, Python, and others.
To use a COM object in a script run by Windows Script Host, you must first create an instance of the object. After a
COM object has been created, you can then use it in scripts.
Windows Script Host consists of two applications. One runs scripts from the Windows desktop (WScript.exe); the
other runs scripts from the command prompt (CScript.exe).
To run a script from the desktop, simply double-click a script file. Script files are text files. By convention, VBScript
files have the extension .vbs and JScript files .js.
To run a script from the command prompt, run the Cscript.exe application with a command line such as the
following:
cscript c:\"sample scripts"\chart.vbs
where c:\"sample scripts"\chart.vbs is the path to the file containing the script.
You can print out a list of the parameters supported by Cscript.exe by entering the following command line:
call cscript //?
To use a COM object in a script run by Windows Script Host, you must first create an instance of the object. You
can do this by calling the CreateObject method (in VBScript) or the ActiveXObject object (in JScript). The following
example illustrates calling CreateObject using VBScript:
Dim objXL
Set objXL = CreateObject("Excel.Application")
After you have created an instance of the COM object, you can write script that uses the object, for example:
objXL.Visible = true;
In addition to the CreateObject method and ActiveXObject object, both VBScript and JScript provide the method
GetObject, which returns an object instance.
Related topics
S
c
r
i
p
t
i
n
g
w
i
t
h
C
O
M
O
b
j
e
c
t
s
Scripting COM Objects in Custom Applications
1/7/2020 • 2 minutes to read • Edit Online
Microsoft provides several environments for scripting COM objects: Active Server Pages, Windows Script Host,
and so on. Independent software vendors (ISVs) can also license Microsoft scripting engines for use in their
applications. For example, an ISV creating a word processor might want to add a macro language to the
application so users could automate simple tasks. By licensing a scripting engine, the ISV can use a language such
as VBScript or JScript as the application's macro language.
In addition to licensing VBScript and JScript scripting engines, ISVs can write their own ActiveX scripting engines.
These scripting engines can then be plugged into any host environment that supports the ActiveX scripting engine
standard. For example, an ISV might write a PerlScript scripting engine and install it on an ASP server, thus
enabling the ASP server to process PerlScript scripts.
Related topics
S
c
r
i
p
t
i
n
g
w
i
t
h
C
O
M
O
b
j
e
c
t
s
Translating to VBScript
1/7/2020 • 2 minutes to read • Edit Online
VBScript is a subset of the Microsoft Visual Basic for Applications language. Because VBScript is intended to be
safe for use in client-side applications such as webpages, it does not provide file input and output or direct access
to the underlying operating system. This prevents a Web-based script from deleting or altering files on your
computer. For a complete list of Visual Basic features that are not supported in VBScript, see the Visual Basic for
Applications documentation.
In addition to the language features provided by VBScript, the scripting host may also expose a VBScript object
model that your script can access. For example, Internet Explorer exposes an object model that enables scripts to
interact with and programmatically control the browser. For more information about working with such object
models, see the documentation on your scripting host.
The following topics describe issues you should consider when translating a script to VBScript from JavaScript or
JScript:
Translating to VBScript from JScript
Translating to VBScript from JavaScript
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
J
a
v
a
S
c
r
i
p
t
T
r
a
n
s
l
a
t
i
n
g
t
o
J
S
c
r
i
p
t
Translating to VBScript from JScript
1/7/2020 • 2 minutes to read • Edit Online
In VBScript, the For...Each loop enumerates the members of a collection; in JScript, the for...in loop enumerates
the members of a JScript object or array. To enumerate a collection in JScript, use an Enumerator object.
JScript provides the Error object, which can be used to trap and handle errors. The Error object is analogous to the
VBScript Err object.
In JScript, there are several data types such as numbers, strings, Booleans, objects, and the null attribute. VBScript
only uses one data type, Variant, which can be subtyped to represent strings, numbers, Booleans, and so on.
In JScript, arrays can be expanded dynamically by setting a new value for the array's length property. In VBScript,
arrays cannot be enlarged; they must be redimensioned using the redim statement.
Both VBScript and JScript support functions. VBScript, however, also supports subroutines. Subroutines are
similar to functions but do not return a value.
JScript is case-sensitive. VBScript is not.
JScript is supported by a wide variety of Web browsers, including both Internet Explorer and Netscape Navigator.
Netscape Navigator does not support VBScript.
JScript arrays are not arrays of the variable type VARIANT SAFEARRAY. A JScript script must use a VBArray
object to access the VARIANT SAFEARRAYvariable. VBScript scripts can access VARIANT
SAFEARRAYvariables directly.
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
V
B
S
c
r
i
p
t
Translating to VBScript from JavaScript
1/7/2020 • 2 minutes to read • Edit Online
In JavaScript, there are several data types, such as numbers, strings, Booleans, objects, and the null attribute.
VBScript only uses one data type, Variant, which can be subtyped to represent strings, numbers, Booleans, and so
on.
In JavaScript, arrays can be expanded dynamically by setting a new value for the array's length property. In
VBScript, arrays cannot be enlarged; they must be redimensioned using the redim statement.
Both VBScript and JavaScript support functions. VBScript, however, also supports subroutines. Subroutines are
similar to functions, except they do not return a value.
JavaScript is case-sensitive. VBScript is not.
JavaScript is supported by a wide variety of Web browsers, including both Internet Explorer and Netscape
Navigator. Netscape Navigator does not support VBScript.
VBScript supports error handling through its Err object. JavaScript does not currently provide a means of trapping
and handling errors.
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
V
B
S
c
r
i
p
t
Translating to JScript
1/7/2020 • 2 minutes to read • Edit Online
JScript is the Microsoft implementation of the ECMA 262 language specification. It is supported by both Internet
Explorer and Netscape Navigator. JScript is the first scripting language to conform to the ECMA 262 standard.
JScript is supported by a wide range of Web browsers, including both Internet Explorer and Navigator.
In addition to the language features provided by JScript, the scripting host may also expose an object model that
your script can access. For example, Internet Explorer exposes an object model that enables scripts to interact with
and programmatically control the browser. For more information about working with such object models, see the
documentation for your scripting host.
For more information about JScript, see the JScript Language Reference. For more information see the ECMA
262 language specification.
The following topics describe issues you should consider when translating a script to JScript from JavaScript or
VBScript:
Translating to JScript from VBScript
Translating to JScript from JavaScript
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
J
a
v
a
S
c
r
i
p
t
T
r
a
n
s
l
a
t
i
n
g
t
o
V
B
S
c
r
i
p
t
Translating to JScript from VBScript
1/7/2020 • 2 minutes to read • Edit Online
In VBScript, the For...Each loop enumerates the members of a collection; in JScript, the for...in loop enumerates
the members of a JScript object or array. To enumerate a collection in JScript, use an Enumerator object.
In JScript, there are several data types such as numbers, strings, Booleans, objects, and the null attribute. VBScript
only uses one data type, Variant, which can be subtyped to represent strings, numbers, Booleans, and so on.
In JScript, arrays can be expanded dynamically by setting a new value for the array's length property. In VBScript,
arrays cannot be enlarged; they must be redimensioned using the redim statement.
Both VBScript and JScript support functions. VBScript, however, also supports subroutines. Subroutines are
similar to functions but do not return a value.
JScript is case-sensitive. VBScript is not.
JScript is supported by both Internet Explorer and Netscape Navigator. Netscape Navigator does not support
VBScript.
JScript provides the Error object, which can be used to trap and handle errors. The Error object is analogous to the
VBScript Err object.
JScript arrays are not arrays of the variable type VARIANT SAFEARRAY. If your script receives a VARIANT
SAFEARRAY variable from a COM object or VBScript script, it must use a VBArray object to access the
VARIANT SAFEARRAY variable.
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
J
S
c
r
i
p
t
Translating to JScript from JavaScript
1/7/2020 • 2 minutes to read • Edit Online
JScript is largely compatible with JavaScript. However, JScript version 5.0 includes some objects not currently
supported by JavaScript, such as ActiveXObject, Enumerator, Error, Global, and VBArray.
JScript 5.0 supports exception handling through try...catch statements. JavaScript does not currently provide an
error-handing mechanism.
When working with either JScript or JavaScript, there are some subtle differences between the object model
implementations supported by various Web browsers. To write script that runs on both Internet Explorer and
Netscape Navigator, limit the features used by your scripts to those specified in the World Wide Web Consortium
(W3C ) standard for HTML version 3.2. For more information about this standard, see HTML 3.2 Reference
Specification.
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
J
S
c
r
i
p
t
Translating to JavaScript
1/7/2020 • 2 minutes to read • Edit Online
JavaScript is a scripting language that was created by Netscape. It was originally called LiveScript. Despite the
similarities in name and syntax, JavaScript is not related to the Java programming language. Java is a full-featured
programming language developed by Sun Microsystems, Inc.
JavaScript is supported by a wide range of Web browsers, including both Internet Explorer and Netscape
Navigator.
In addition to the language features provided by JavaScript, the scripting host may also expose an object model
that your script can access. For example, Internet Explorer exposes an object model that enables scripts to interact
with and programmatically control the browser. For more information about working with such object models, see
the documentation on your scripting host.
For more information about JavaScript, see a JavaScript reference.
The following topics describe issues you should consider when translating a script to JavaScript from VBScript or
JScript:
Translating to JavaScript from VBScript
Translating to JavaScript from JScript
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
J
S
c
r
i
p
t
T
r
a
n
s
l
a
t
i
n
g
t
o
V
B
S
c
r
i
p
t
Translating to JavaScript from VBScript
1/7/2020 • 2 minutes to read • Edit Online
In JavaScript, there are several data types such as numbers, strings, Booleans, objects, and the null attribute.
VBScript only uses one data type, Variant, which can be subtyped to represent strings, numbers, Booleans, and so
on.
In JavaScript, arrays can be expanded dynamically by setting a new value for the array's length property. In
VBScript, arrays cannot be enlarged; they must be redimensioned using the redim statement.
Both VBScript and JavaScript support functions. VBScript, however, also supports subroutines. Subroutines are
similar to functions but do not return a value.
JavaScript is case-sensitive. VBScript is not.
JavaScript is supported by a wide variety of Web browsers, including both Internet Explorer and Netscape
Navigator. VBScript is only supported by Internet Explorer.
VBScript provides error handling support through its Err object. JavaScript does not currently provide a means of
trapping and handling errors.
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
J
a
v
a
S
c
r
i
p
t
Translating to JavaScript from JScript
1/7/2020 • 2 minutes to read • Edit Online
JScript is largely compatible with JavaScript. However, JScript includes some objects not currently supported by
JavaScript, such as ActiveXObject, Enumerator, Error, Global, and VBArray.
JScript version 5.0 supports exception handling through try...catch statements. JavaScript does not currently
provide an error-handing mechanism.
When working with either JScript or JavaScript, there are some subtle differences between the object model
implementations supported by various Web browsers. To write script that runs on both Internet Explorer and
Netscape Navigator, limit the features used by your scripts to those specified in the World Wide Web Consortium
(W3C ) standard for HTML version 3.2.
Related topics
T
r
a
n
s
l
a
t
i
n
g
t
o
J
a
v
a
S
c
r
i
p
t
COM Glossary
1/7/2020 • 25 minutes to read • Edit Online
a The process of loading an object in memory, which puts it into the running state.
c
t
i
v
a
t
i
o
n
a A COM object that is in the running state and has a visible user interface.
c
t
i
v
e
s
t
a
t
e
a
b
s
o
l
u
t
e
m
o
n
i
k
e
r
A moniker that specifies the absolute location of an object. An absolute moniker is analogous to a full path.
a
d
v
i
s
o
r
y
h
o
l
d
e
r
A COM object that caches, manages, and sends notifications of changes to container applications' advisory
sinks.
a
d
v
i
s
o
r
y
s
i
n
k
A COM object that can receive notifications of changes in an embedded object or linked object because it
implements the IAdviseSink or IAdviseSink2 interface. Containers that need to be notified of changes in
objects implement an advisory sink. Notifications originate in the server, which uses an advisory holder
object to cache and manage notifications to containers.
a
g
g
r
e
g
a
t
e
o
b
j
e
c
t
A COM object that is made up of one or more other COM objects. One object in the aggregate is designated
the controlling object, which controls which interfaces in the aggregate are exposed and which are private.
This controlling object has a special implementation of IUnknown called the controlling IUnknown. All
objects in the aggregate must pass calls to IUnknown methods through the controlling IUnknown.
a
g
g
r
e
g
a
t
i
o
n
A composition technique for implementing COM objects. It allows you to build a new object by reusing one
or more existing objects' interface implementations. The aggregate object chooses which interfaces to expose
to clients, and the interfaces are exposed as if they were implemented by the aggregate object. Clients of the
aggregate object communicate only with the aggregate object.
a
m
b
i
e
n
t
p
r
o
p
e
r
t
y
A run-time property that is managed and exposed by the container. Typically, an ambient property represents
a characteristic of a form, such as background color, that needs to be communicated to a control so that the
control can assume the look and feel of its surrounding environment.
a
n
t
i
-
m
o
n
i
k
e
r
The inverse of a file, item, or pointer moniker. An anti-moniker is added to the end of a file, item, or pointer
moniker to nullify it. Anti-monikers are used in the construction of relative monikers.
a
r
t
i
f
i
c
i
a
l
r
e
f
e
r
e
n
c
e
c
o
u
n
t
i
n
g
A technique used to help protect an object before calling a function or method that could prematurely
destroy it. A program calls IUnknown::AddRef to increment the object's reference count before making the
call that could free the object. After the function returns, the program calls IUnknown::Release to decrement
the count.
a
s
y
n
c
h
r
o
n
o
u
s
b
i
n
d
i
n
g
A type of binding in which it is necessary for the process to occur asynchronously to avoid performance
degradation for the end user. Typically, asynchronous binding is used in distributed environments such as the
World Wide Web. OLE supports asynchronous moniker classes and callback mechanisms that allow the
process of locating and initializing an object in a distributed environment to occur while other operations are
being carried out.
a
s
y
n
c
h
r
o
n
o
u
s
c
a
l
l
A call to a function that is executed separately so that the caller can continue processing instructions without
waiting for the function to return.
a
s
y
n
c
h
r
o
n
o
u
s
m
o
n
i
k
e
r
A moniker that supports asynchronous binding. For example, instances of the system-supplied URL moniker
class are asynchronous monikers.
a
u
t
o
m
a
t
i
o
n
A way to manipulate an application's objects from outside the application. Automation is typically used to
create applications that expose objects to programming tools and macro languages, create and manipulate
one application's objects from another applications, or to create tools for accessing and manipulating objects.
b
i
n
d
c
o
n
t
e
x
t
A COM object that implements the IBindCtx interface. Bind contexts are used in moniker operations to hold
references to the objects activated when a moniker is bound. The bind context contains parameters that apply
to all operations during the binding of a generic composite moniker and provides the moniker
implementation with access to information about its environment.
b
i
n
d
i
n
g
Associating a name with its referent. Specifically, locating the object named by a moniker, putting it into its
running state if it isn't already, and returning an interface pointer to it. Objects can be bound at run time (also
called late binding or dynamic binding) or at compile time (also called static binding).
c
a
c
h
e
A (usually temporary) local store of information. In OLE, a cache contains information that defines the
presentation of a linked or embedded object when the container is opened.
c
a
c
h
e
i
n
i
t
i
a
l
i
z
a
t
i
o
n
Filling a linked or embedded object's cache with presentation data. The IOleCache interface provides
methods that a container can call to control the data that gets cached for linked or embedded objects.
c
l
a
s
s
The definition of an object in code. In C++, the class of an object is defined as a data type, but this is not the
case in other languages. Because OLE can be coded in any language, class is used to refer to the general
object definition.
c
l
a
s
s
f
a
c
t
o
r
y
A COM object that implements the IClassFactory interface and that creates one or more instances of an
object identified by a given class identifier(CLSID ).
c
l
a
s
s
i
d
e
n
t
i
f
i
e
r
(
C
L
S
I
D
)
A globally unique identifier (GUID ) associated with an OLE class object. If a class object will be used to create
more than one instance of an object, the associated server application should register its CLSID in the system
registry so that clients can locate and load the executable code associated with the object(s). Every OLE
server or container that allows linking to its embedded objects must register a CLSID for each supported
object definition.
c
l
a
s
s
o
b
j
e
c
t
In object-oriented programming, an object whose state is shared by all the objects in a class and whose
behavior acts on that classwide state data. In COM, class objects are called class factories, and typically have
no behavior except to create new instances of the class.
c
l
i
e
n
t
s
i
t
e
The display site for an embedded or linked object within a compound document. The client site is the
principal means by which an object requests services from its container.
C
L
S
I
D
A globally unique identifier (GUID ) associated with an OLE class object. If a class object will be used to create
more than one instance of an object, the associated server application should register its CLSID in the system
registry so that clients can locate and load the executable code associated with the object(s). Every OLE
server or container that allows linking to its embedded objects must register a CLSID for each supported
object definition.
c
o
m
m
i
t
To persistently save any changes made to a storage or stream object since it was opened or changes were last
saved.
c
o
m
p
o
n
e
n
t
An object that encapsulates both data and code, and provides a well-specified set of publicly available
services.
C
o
m
p
o
n
e
n
t
O
b
j
e
c
t
M
o
d
e
l
(
C
O
M
)
The OLE object-oriented programming model that defines how objects interact within a single process or
between processes. In COM, clients have access to an object through interfaces implemented on the object.
c
o
m
p
o
s
i
t
e
m
e
n
u
b
a
r
A shared menu bar composed of menu groups from both a container application and an in-place-activated
server application.
c
o
m
p
o
s
i
t
e
m
o
n
i
k
e
r
A moniker that consists of two or more monikers that are treated as a unit. A composite moniker can be non-
generic, meaning that its component monikers have special knowledge of each other, or generic, meaning
that its component monikers know nothing about each other except that they are monikers
c A document that includes linked or embedded objects, as well as its own native data.
o
m
p
o
u
n
d
d
o
c
u
m
e
n
t
C
O
M
o
b
j
e
c
t
An object that conforms to the OLE Component Object Model (COM ). A COM object is an instance of an
object definition, which specifies the object's data and one or more implementations of interfaces on the
object. Clients interact with a COM object only through its interfaces.
c
o
n
n
e
c
t
a
b
l
e
o
b
j
e
c
t
A COM object that implements, at a minimum, the IConnectionPointContainer interface, for the
management of connection point objects. Connectable objects support communication from the server to the
client. A connectable object creates and manages one or more connection point subobjects, which receive
events from interfaces implemented on other objects and send them on to the client.
c
o
n
n
e
c
t
i
o
n
p
o
i
n
t
o
b
j
e
c
t
A COM object that is managed by a connectable object and that implements the IConnectionPoint
interface. One or more connection point objects can be created and managed by a connectable object. Each
connection point object manages incoming events from a specific interface on another object and sends
those events on to the client.
c
o
n
t
a
i
n
e
r
a
p
p
l
i
c
a
t
i
o
n
An application that supports compound documents. The container application provides storage for an
embedded or linked object, a site for its display, access to the display site, and an advisory sink for receiving
notifications of changes in the object.
c
o
n
t
a
i
n
m
e
n
t
A composition technique for implementing COM objects. It allows one object to reuse some or all of the
interface implementations of one or more other objects. The outer object acts as a client to the other objects,
delegating implementation when it wishes to use the services of one of the contained objects.
c
o
n
t
e
x
t
In COM+, a set of run-time properties associated with one or more COM objects that are used to provide
services for those objects.
c
o
n
t
r
o
l
An embeddable, reusable COM object that supports, at a minimum, the IOleControl interface. Controls are
typically associated with the user interface. They also support communication with a container and can be
reused by multiple clients, depending upon licensing criteria.
c
o
n
t
r
o
l
p
r
o
p
e
r
t
y
A run-time property that is exposed and managed by the control itself. For example, the font and text size
used by the control are control properties.
c
o
n
t
r
o
l
l
i
n
g
o
b
j
e
c
t
The object within an aggregate object that controls which interfaces within the aggregate object are exposed
and which are private. The IUnknown interface of the controlling object is called the controlling IUnknown.
Calls to IUnknown methods of other objects in the aggregate must be passed to the controlling IUnknown.
c
o
n
t
r
o
l
s
i
t
e
A structure implemented by a control container for managing the display and storage of a control. Within a
given container, each control has a corresponding control site.
d
a
t
a
t
r
a
n
s
f
e
r
o
b
j
e
c
t
An object that implements the IDataObject interface and contains data to be transferred from one object to
another through either the Clipboard or drag-and-drop operations.
d
e
f
a
u
l
t
o
b
j
e
c
t
h
a
n
d
l
e
r
A DLL provided with OLE that acts as a surrogate in the processing space of the container application for the
real object.
With the default object handler, it is possible to look at an object's stored data without actually activating the
object. The default object handler performs other tasks, such as rendering an object from its cached state
when the object is loaded into memory.
d
e
p
e
n
d
e
n
t
o
b
j
e
c
t
A COM object that is typically initialized by another object (the host object). Although the dependent object's
lifetime may only make sense during the lifetime of the host object, the host object does not function as the
controlling IUnknown for the dependent object. In contrast, an object is an aggregated object when its
lifetime (by means of its reference count) is completely controlled by the managing object.
d
i
r
e
c
t
a
c
c
e
s
s
m
o
d
e
One of two access modes in which a storage object can be opened. In direct mode, all changes are
immediately committed to the root storage object.
d
o
c
u
m
e
n
t
o
b
j
e
c
t
An OLE document that can display one or more in-place activated views of its data within a native or foreign
frame, such as a browser, while retaining full control over its user interface. In addition to implementing the
usual OLE document and in-place activation interfaces, a document object must implement IOleDocument,
and each of its views (in the form of a document view object) must implement IOleDocumentView.
d
o
c
u
m
e
n
t
o
b
j
e
c
t
c
o
n
t
a
i
n
e
r
A container application capable of displaying one or more views of one or more document objects and of
managing all contained document objects within a file. Each document object is associated with a document
site, and each document site contains one or more document view sites corresponding to the views
supported by the document object. A document object container also includes a container frame, which
handles menu and toolbar negotiation and the enumeration of contained objects.
d
o
c
u
m
e
n
t
s
i
t
e
A client site implemented by a document object container for managing the display and storage of a
document object. Each document object in a container has a corresponding document site.
d
o
c
u
m
e
n
t
s
i
t
e
o
b
j
e
c
t
A COM object that implements the IOleDocumentSite interface, in addition to the usual client-site
interfaces (such as IOleClientSite).
d
o
c
u
m
e
n
t
v
i
e
w
A particular presentation of a document's data. A single document object can have one or more views, but a
single document view can belong to one and only one document object.
d
o
c
u
m
e
n
t
v
i
e
w
o
b
j
e
c
t
A COM object that implements the IOleDocumentView interface and corresponds to a particular
document view. An object with multiple document views aggregates a separate document view object for
each view.
d
o
c
u
m
e
n
t
v
i
e
w
s
i
t
e
An object aggregated by a document site object for managing the display space for a particular view of a
document object. Within a given document site, each document view has a corresponding document view
site.
d
o
c
u
m
e
n
t
v
i
e
w
s
i
t
e
o
b
j
e
c
t
A COM object that is aggregated in a document site object and implements the IOleInPlaceSite interface
and, optionally, the IContinueCallback interface.
d
r
a
g
a
n
d
d
r
o
p
An operation in which the end user uses the mouse or other pointing device to move data to another location
in the same window or another window.
e
m
b
e
d
To insert an object into a compound document in such a way as to preserve the data formats native to that
object, and to enable it to be edited from within its container using tools exposed by its server.
e
m
b
e
d
d
e
d
o
b
j
e
c
t
An object whose data is stored in a compound document, but the object runs in the process space of its
server. The default object handler provides a surrogate in the processing space of the container application
for the real object.
e
x
t
e
n
d
e
d
p
r
o
p
e
r
t
y
A run-time property, such as a control's position and size, that a user would assume to be exposed by the
control but is exposed and managed by the container.
f
i
l
e
m
o
n
i
k
e
r
A moniker based on a path in the file system. File monikers can be used to identify objects that are saved in
their own files. A file moniker is a COM object that supports the system-provided implementation of the
IMoniker interface for the file moniker class.
f
o
n
t
o
b
j
e
c
t
A COM object that provides access to Graphics Device Interface (GDI) fonts by implementing the IFont
interface.
f
r
a
m
e
The part of a container application responsible for negotiating menus, accelerator keys, toolbars, and other
shared user-interface elements with an embedded COM object or a document object.
f
r
a
m
e
o
b
j
e
c
t
A COM object that implements the IOleInPlaceFrame interface and, optionally, the IOleCommandTarget
interface.
g
e
n
e
r
i
c
c
o
m
p
o
s
i
t
e
m
o
n
i
k
e
r
A sequenced collection of monikers, starting with a file moniker to provide the document-level path and
continuing with one or more item monikers that, taken as a whole, uniquely identifies an object.
h
e
l
p
e
r
f
u
n
c
t
i
o
n
A function that encapsulates calls to other functions and interface methods publicly available in the OLE SDK.
Helper functions are a convenient way to call frequently used sequences of function and method calls that
accomplish common tasks.
h
o
s
t
o
b
j
e
c
t
A COM object that forms a hierarchical relationship with one or more other COM objects, known as the
dependent objects. Typically, the host object instantiates the dependent objects, and their existence only
makes sense within the lifetime of the host object. However, the host object does not act as the controlling
IUnknown for the dependent objects, nor does it directly delegate to the interface implementations of those
objects.
H
R
E
S
U
L
T
An opaque result handle defined to be zero for a successful return from a function and nonzero if error or
status information is returned.
h
y
p
e
r
l
i
n
k
o
b
j
e
c
t
A COM object that implements, at a minimum, the IHlink interface and acts as a link to an object at another
location (the target). A hyperlink is made up of four parts: a moniker that identifies the target's location; a
string for the location within the target; a friendly, or displayable, name for the target; and a string that can
contain additional parameters.
h
y
p
e
r
l
i
n
k
b
r
o
w
s
e
c
o
n
t
e
x
t
A COM object that implements the IHlinkBrowseContext interface and maintains the hyperlink navigation
stack. The browse context object manages the hyperlink frame window and hyperlink target object's window.
h
y
p
e
r
l
i
n
k
c
o
n
t
a
i
n
e
r
A container application that supports hyperlinks by implementing the IHlinkSite interface and, if the
container's objects can be targets of other hyperlinks, the IHlinkTarget interface.
h
y
p
e
r
l
i
n
k
f
r
a
m
e
o
b
j
e
c
t
A COM object that implements the IHlinkFrame interface and controls the top-level navigation and display
of hyperlinks for the frame's container and the hyperlink target's server.
h
y
p
e
r
l
i
n
k
s
i
t
e
o
b
j
e
c
t
A COM object that implements the IHlinkSite interface and supplies either the moniker or interface
identifier of its hyperlink container. One hyperlink site can serve multiple hyperlinks.
h
y
p
e
r
l
i
n
k
t
a
r
g
e
t
o
b
j
e
c
t
A COM object that implements the IHlinkTarget interface and supplies its moniker, friendly name, and other
information that other hyperlink objects will use to navigate to it.
i
n
p
a
r
a
m
e
t
e
r
A parameter that is allocated, set, and freed by the caller of a function or interface method. An in parameter is
not modified by the called function.
i
n
/
o
u
t
p
a
r
a
m
e
t
e
r
A parameter that is initially allocated by the caller of a function or interface method, and set, freed, and
reallocated, if necessary, by the process that is called.
i
n
-
p
l
a
c
e
a
c
t
i
v
a
t
i
o
n
Editing an embedded object within the window of its container, using tools provided by the server. Linked
objects do not support in-place activation; they are always edited in the window of the server.
i A server implemented as a DLL that runs in the process space of the client.
n
-
p
r
o
c
e
s
s
s
e
r
v
e
r
i
n
t
e
r
f
a
c
e
A group of semantically related functions that provide access to a COM object. Each OLE interface defines a
contract that allows objects to interact according to the Component Object Model (COM ). While OLE
provides many interface implementations, most interfaces can also be implemented by developers designing
OLE applications.
i
n
t
e
r
f
a
c
e
i
d
e
n
t
i
f
i
e
r
(
I
I
D
)
A globally unique identifier (GUID ) associated with an interface. Some functions take IIDs as parameters to
allow the caller to specify which interface pointer should be returned.
i
t
e
m
m
o
n
i
k
e
r
A moniker based on a string that identifies an object in a container. Item monikers can identify objects smaller
than a file, including embedded objects in a compound document, or a pseudo-object (like a range of cells in
a spreadsheet).
l
i
c
e
n
s
i
n
g
A feature of COM that provides control over object creation. Licensed objects can be created only by clients
that are authorized to use them. Licensing is implemented in COM through the IClassFactory2 interface and
by support for a license key that can be passed at run time.
l
i
n
k
o
b
j
e
c
t
A COM object that is created when a linked COM object is created or loaded. The link object is provided by
OLE and implements the IOleLink interface.
l
i
n
k
e
d
o
b
j
e
c
t
A COM object whose source data physically resides where it was initially created. Only a moniker that
represents the source data and the appropriate presentation data are kept with the compound document.
Changes made to the link source are automatically reflected in the linked object.
l
i
n
k
s
o
u
r
c
e
The data that is the source of a linked object. A link source may be a file or a portion of a file, such as a
selected range of cells within a file (also called a pseudo object).
l
o
a
d
e
d
s
t
a
t
e
The state of an object after its data structures have been loaded into memory and are accessible to the client
process.
l
o
c
a
l
s
e
r
v
e
r
An out-of-process server implemented as an .EXE application running on the same computer as its client
application.
l
o
c
k
A pointer held to-and possibly, a reference count incremented on-a running object. OLE defines two types of
locks that can be held on an object: strong and weak. To implement a strong lock, a server must maintain
both a pointer and a reference count, so that the object will remain "locked" in memory at least until the
server calls IUnknown::Release. To implement a weak lock, the server maintains only a pointer to the
object, so that the object can be destroyed by another process.
m Packaging and sending interface method calls across thread or process boundaries.
a
r
s
h
a
l
i
n
g
m An extension of MIME that allows data format negotiation between a client and an object.
e
d
i
a
t
y
p
e
M An extension of MIME that allows data format negotiation between a client and an object.
I
M
E
c
o
n
t
e
n
t
t
y
p
e
M
u
l
t
i
p
u
r
p
o
s
e
I
n
t
e
r
n
e
t
M
a
i
l
E
x
t
e
n
s
i
o
n
(
M
I
M
E
)
An Internet protocol originally developed to allow exchange of electronic mail messages with rich content
across heterogeneous network, computer, and email environments. In practice, MIME has also been adopted
and extended by non-mail applications.
m
o
n
i
k
e
r
An object that implements the IMoniker interface. A moniker acts as a name that uniquely identifies a COM
object. In the same way that a path identifies a file in the file system, a moniker identifies a COM object in the
directory namespace.
m
o
n
i
k
e
r
c
l
a
s
s
An implementation of the IMoniker interface. System-supplied moniker classes include file monikers, item
monikers, generic composite monikers, anti-monikers, pointer monikers, and URL monikers.
m
o
n
i
k
e
r
c
l
i
e
n
t
An application that uses monikers to acquire interface pointers to objects managed by another application.
m
o
n
i
k
e
r
p
r
o
v
i
d
e
r
An application that makes available monikers that identify the objects it manages, so that the objects are
accessible to other applications.
n
a
m
e
s
p
a
c
e
e
x
t
e
n
s
i
o
n
An in-process COM object that implements IShellFolder, IPersistFolder, and IShellView, which are
sometimes referred to as the namespace extension interfaces. A namespace extension is used either to extend
the shell's namespace or to create a separate namespace. Primary users are the Windows Explorer and
common file dialog boxes.
n The data used by an OLE server application when editing an embedded object.
a
t
i
v
e
d
a
t
a
o
b
j
e
c
t
In OLE, a programming structure encapsulating both data and functionality that are defined and allocated as
a single unit and for which the only public access is through the programming structure's interfaces. A COM
object must support, at a minimum, the IUnknown interface, which maintains the object's existence while it
is being used and provides access to the object's other interfaces.
o
b
j
e
c
t
s
t
a
t
e
The relationship between a compound document object in its container and the application responsible for
the object's creation: active, passive, loaded, or running. Passive objects are stored on disk or in a database,
and the object is not selected or active. In the loaded state, the object's data structures have been loaded into
memory, but they are not available for operations such as editing. Running objects are both loaded and
available for all operations. Active objects are running objects that have a visible user interface.
o
b
j
e
c
t
t
y
p
e
n
a
m
e
A unique identification string that is stored as part of the information available for an object in the
registration database.
O
L
E
Microsoft's object-based technology for sharing information and services across process and computer
boundaries.
o
u
t
-
o
f
-
p
r
o
c
e
s
s
s
e
r
v
e
r
A server, implemented as an .EXE application, which runs outside the process of its client, either on the same
computer or a remote computer.
o An out parameter is allocated by the function being called, and freed by caller.
u
t
p
a
r
a
m
e
t
e
r
p The state of a COM object when it is stored (on disk or in a database). The object is not selected or active.
a
s
s
i
v
e
s
t
a
t
e
p
e
r
s
i
s
t
e
n
t
p
r
o
p
e
r
t
y
Information that can be stored persistently as part of a storage object such as a file or directory. Persistent
properties are grouped into property sets, which can be displayed and edited.
A persistent property is different from the run-time properties of objects created with OLE Controls and
Automation technologies, which can be used to affect system behavior. The PROPVARIANT structure
defines all valid types of persistent properties, whereas the VARIANT structure defines all valid types of run-
time properties.
p
e
r
s
i
s
t
e
n
t
s
t
o
r
a
g
e
Storage of a file or object in a medium such as a file system or database so that the object and its data persist
when the file is closed and then re-opened at a later time.
p A COM object that provides access to GDI images by implementing the IPicture interface.
i
c
t
u
r
e
o
b
j
e
c
t
p
o
i
n
t
e
r
m
o
n
i
k
e
r
A moniker that maps an interface pointer to an object in memory. Whereas most monikers identify objects
that can be persistently stored, pointer monikers identify objects that cannot. They allow such objects to
participate in a moniker binding operation.
p
r
i
m
a
r
y
v
e
r
b
The action associated with the most common or preferred operation users perform on an object. The primary
verb is always defined as verb zero in the system registration database. An object's primary verb is executed
by double-clicking on the object.
p
r
o
p
e
r
t
y
Information that is associated with an object. In OLE, properties fall into two categories: run-time properties
and persistent properties. Run-time properties are typically associated with control objects or their
containers. For example, background color is a run-time property set by a control's container. Persistent
properties are associated with stored objects.
p
r
o
p
e
r
t
y
f
r
a
m
e
The user interface mechanism that displays one or more property pages for a control. The OLE Controls run-
time system provides a standard implementation of a property frame that can be accessed by using the
OleCreatePropertyFrame helper function.
p A four-byte signed integer that identifies a persistent property within a property set.
r
o
p
e
r
t
y
i
d
e
n
t
i
f
i
e
r
p
r
o
p
e
r
t
y
p
a
g
e
A COM object with its own CLSID that is part of a user interface, implemented by a control, and allows the
control's properties to be viewed and set. Property page objects implement the IPropertyPage interface.
p
r
o
p
e
r
t
y
p
a
g
e
s
i
t
e
The location within a property frame where a property page is displayed. The property frame implements the
IPropertyPageSite interface, which contains methods to manage the sites of each of the property pages
supplied by a control.
p
r
o
p
e
r
t
y
s
e
t
A logically related group of properties that is associated with a persistently stored object. To create, open,
delete, or enumerate one or more property sets, implement the IPropertySetStorage interface. If you are
using compound files, you can use OLE's implementation of this interface rather than implementing your
own.
p
r
o
p
e
r
t
y
s
e
t
s
t
o
r
a
g
e
A COM storage object that holds a property set. A property set storage is a dependent object associated with
and managed by a storage object.
p
r
o
x
y
An interface-specific object that packages parameters for that interface in preparation for a remote method
call. A proxy runs in the address space of the sender and communicates with a corresponding stub in the
receiver's address space.
p In standard marshaling, a proxy that manages all the interface proxies for a single object.
r
o
x
y
m
a
n
a
g
e
r
p
s
e
u
d
o
o
b
j
e
c
t
A portion of a document or embedded object, such as a range of cells in a spreadsheet, that can be the source
for a COM object.
r
e
f
e
r
e
n
c
e
c
o
u
n
t
i
n
g
Keeping a count of each interface pointer held on an object to ensure that the object is not destroyed before
all references to it are released.
r
e
l
a
t
i
v
e
m
o
n
i
k
e
r
A moniker that specifies the location of an object relative to the location of another object. A relative moniker
is analogous to a relative path, such as ..\backup\report.old.
r
e
m
o
t
e
s
e
r
v
e
r
A server application, implemented as an EXE, running on a different computer from the client application
using it.
r
e
v
e
r
t
To discard any changes made to an object since the last time the changes were committed or the object's
storage was opened.
r
o
o
t
s
t
o
r
a
g
e
o
b
j
e
c
t
The outermost storage object in a document. A root storage object can contain other nested storage and
stream objects. For example, a compound document is saved on disk as a series of storage and stream
objects within a root storage object.
r
u
n
n
i
n
g
s
t
a
t
e
The state of a COM object when its server application is running and it is possible to access its interfaces and
receive notification of changes.
r
u
n
n
i
n
g
o
b
j
e
c
t
t
a
b
l
e
(
R
O
T
)
A globally accessible table on each computer that keeps track of all COM objects in the running state that can
be identified by a moniker. Moniker providers register an object in the table, which increments the object's
reference count. Before the object can be destroyed, its moniker must be released from the table.
r
u
n
-
t
i
m
e
p
r
o
p
e
r
t
y
Discrete state information associated with a control object or its container. There are three types of run-time
properties: ambient properties, control properties, and extended properties.
s The process by which a server can perform its own registry operations.
e
l
f
-
r
e
g
i
s
t
r
a
t
i
o
n
s
e
r
v
e
r
a
p
p
l
i
c
a
t
i
o
n
An application that can create COM objects. Container applications can then embed or link to these objects.
s
t
a
t
i
c
o
b
j
e
c
t
An object that contains only a presentation, with no native data. A container can treat a static object as though
it were a linked or embedded object, except that it is not possible to edit a static object.
A static object can result, for example, from the breaking of a link on a linked object-that is, the server
application is unavailable, or the user doesn't want the linked object to be updated anymore.
s
t
o
r
a
g
e
o
b
j
e
c
t
A COM object that implements the IStorage interface. A storage object contains nested storage objects or
stream objects, resulting in the equivalent of a directory/file structure within a single file.
s
t
r
e
a
m
o
b
j
e
c
t
A COM object that implements the IStream interface. A stream object is analogous to a file in a directory/file
system.
s
t
u
b
When a function's or interface method's parameters are marshaled across a process boundary, the stub is an
interface-specific object that unpackages the marshaled parameters and calls the required method. The stub
runs in the receiver's address space and communicates with a corresponding proxy in the sender's address
space.
s
y
n
c
h
r
o
n
o
u
s
c
a
l
l
A function call that does not allow further instructions in the calling process to be executed until the function
returns.
s
y
s
t
e
m
r
e
g
i
s
t
r
y
A system-wide repository of information supported by Windows, which contains information about the
system and its applications, including OLE clients and servers.
t
r
a
n
s
a
c
t
e
d
a
c
c
e
s
s
m
o
d
e
One of two access modes in which a storage object can be opened. When opened in transacted mode,
changes are stored in buffers until the root storage object commits its changes.
t
y
p
e
i
n
f
o
r
m
a
t
i
o
n
Information about an object's class provided by a type library. To provide type information, a COM object
implements the IProvideClassInfo interface.
u
n
i
f
o
r
m
d
a
t
a
t
r
a
n
s
f
e
r
A model for transferring data through the clipboard, drag and drop, or Automation. Objects conforming to
this model implement the IDataObject interface. This model replaces DDE (dynamic data exchange).
u Unpacking parameters that have been sent to a proxy across process boundaries.
n
m
a
r
s
h
a
l
i
n
g
u
n
i
v
e
r
s
a
l
r
e
s
o
u
r
c
e
l
o
c
a
t
o
r
(
U
R
L
)
The identifier used by the World Wide Web for the names and locations of objects on the Internet. OLE
provides a moniker class, URL moniker, whose implementation can be used to bind a client to objects
identified by a URL.
U
R
L
m
o
n
i
k
e
r
A moniker based on a universal resource locator (URL ). A client can use URL monikers to bind to objects that
reside on the Internet. The system-supplied URL moniker class supports both synchronous and
asynchronous binding.